mirror of
https://github.com/zitadel/zitadel.git
synced 2025-01-07 22:58:02 +00:00
docs: improve Flutter quickstart (#1936)
Signed-off-by: Christoph Bühler <cbuehler@rootd.ch>
This commit is contained in:
parent
4ecbb932e8
commit
04b84d2c7b
@ -2,7 +2,7 @@
|
|||||||
title: Flutter
|
title: Flutter
|
||||||
---
|
---
|
||||||
|
|
||||||
This guide demonstrates, how you integrate **ZITADEL** as an idendity provider to your Flutter app.
|
This guide demonstrates how you integrate **ZITADEL** as an idendity provider to a Flutter app.
|
||||||
|
|
||||||
At the end of the guide you have a mobile application on Android and iOS with the ability
|
At the end of the guide you have a mobile application on Android and iOS with the ability
|
||||||
to authenticate users via ZITADEL.
|
to authenticate users via ZITADEL.
|
||||||
@ -20,11 +20,26 @@ To move further in this quickstart, you'll need the following things prepared:
|
|||||||
|
|
||||||
## Flutter with ZITADEL
|
## Flutter with ZITADEL
|
||||||
|
|
||||||
|
In your native application on ZITADEL, you need to add a callback (redirect) uri
|
||||||
|
which matches the selected custom url scheme. As an example, if you intend to
|
||||||
|
use `ch.myexample.app://sign-me-in` as redirect URI on ZITADEL and in your app,
|
||||||
|
you need to register the `ch.myexample.app://` custom url scheme within Android and iOS.
|
||||||
|
|
||||||
|
:::caution Use Custom Redirect URI!
|
||||||
|
|
||||||
|
You'll need the custom redirect url to be compliant with the OAuth 2.0
|
||||||
|
authentication for mobile devices ([RFC 8252 specification](https://tools.ietf.org/html/rfc8252)).
|
||||||
|
Otherwise your app might get rejected.
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
### Hello World
|
### Hello World
|
||||||
|
|
||||||
After you created the basic Flutter app, the app will show the following screen:
|
After you created the basic Flutter app, the app will show the following screen:
|
||||||
|
|
||||||
![Flutter Hello World](/img/flutter/hello-world.png)
|
<div style={{'text-align': 'center', 'margin-bottom': '1rem'}}>
|
||||||
|
<img src="/img/flutter/hello-world.png" alt="Flutter Hello World" height="500px" />
|
||||||
|
</div>
|
||||||
|
|
||||||
You may want to change the Flutter SDK version in `pubspec.yaml` from
|
You may want to change the Flutter SDK version in `pubspec.yaml` from
|
||||||
|
|
||||||
@ -67,38 +82,71 @@ flutter pub add flutter_secure_storage
|
|||||||
To use this app auth method on Android 11, you'll need to add a `query` to the `AndroidManifest.xml`.
|
To use this app auth method on Android 11, you'll need to add a `query` to the `AndroidManifest.xml`.
|
||||||
Go to `<projectRoot>/android/app/src/main/AndroidManifest.xml` and add to the `<manifest>` root:
|
Go to `<projectRoot>/android/app/src/main/AndroidManifest.xml` and add to the `<manifest>` root:
|
||||||
|
|
||||||
```xml
|
```xml title="<projectRoot>/android/app/src/main/AndroidManifest.xml"
|
||||||
<queries>
|
<queries>
|
||||||
<intent>
|
<intent>
|
||||||
<action android:name="android.intent.action.VIEW" />
|
<action android:name="android.intent.action.VIEW" />
|
||||||
<category android:name="android.intent.category.BROWSABLE" />
|
<category android:name="android.intent.category.BROWSABLE" />
|
||||||
<data android:scheme="https" />
|
<data android:scheme="https" />
|
||||||
</intent>
|
</intent>
|
||||||
|
<intent>
|
||||||
|
<action android:name="android.intent.action.VIEW" />
|
||||||
|
<category android:name="android.intent.category.APP_BROWSER" />
|
||||||
|
<data android:scheme="https" />
|
||||||
|
</intent>
|
||||||
</queries>
|
</queries>
|
||||||
```
|
```
|
||||||
|
|
||||||
This allows the app to query for internal browser activities.
|
This allows the app to query for internal browser activities.
|
||||||
|
|
||||||
Furthermore, for `secure_storage`, you need to set the minimum SDK version to 18
|
Furthermore, for `secure_storage`, you need to set the minimum SDK version to 18
|
||||||
in `<projectRoot>/android/app/src/build.gradle` and add the manifest placeholder
|
in `<projectRoot>/android/app/src/build.gradle`. Then, add the manifest placeholder
|
||||||
for your redirect url (the custom url scheme). In the end, the `defaultConfig`
|
for your redirect url (the custom url scheme). In the end, the `defaultConfig`
|
||||||
section of the `build.gradle` file should look like this:
|
section of the `build.gradle` file should look like this:
|
||||||
|
|
||||||
```gradle
|
```groovy title="<projectRoot>/android/app/src/build.gradle"
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId "ch.caos.zitadel_quickstart"
|
applicationId "<<YOUR APPLICATION ID, for example ch.myexample.my_fancy_app>>"
|
||||||
minSdkVersion 18
|
minSdkVersion 18
|
||||||
targetSdkVersion 30
|
targetSdkVersion 30
|
||||||
versionCode flutterVersionCode.toInteger()
|
versionCode flutterVersionCode.toInteger()
|
||||||
versionName flutterVersionName
|
versionName flutterVersionName
|
||||||
manifestPlaceholders = [
|
manifestPlaceholders = [
|
||||||
'appAuthRedirectScheme': 'ch.caos.zitadel'
|
'appAuthRedirectScheme': '<<YOUR CUSTOM URL SCHEME, for example ch.myexample.app>>'
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### Important on iOS
|
||||||
|
|
||||||
|
In a similar way to Android, you need to register the custom url scheme within iOS to
|
||||||
|
be able to use custom redirect schemes. In the `Info.plist` file of the Runner
|
||||||
|
project, you can add the `CFBundleTypeRole` and the `CFBundleUrlSchemes`.
|
||||||
|
|
||||||
|
```xml title="<projectRoot>/ios/Runner/Info.plist"
|
||||||
|
<key>CFBundleURLTypes</key>
|
||||||
|
<array>
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleTypeRole</key>
|
||||||
|
<string>Editor</string>
|
||||||
|
<key>CFBundleURLSchemes</key>
|
||||||
|
<array>
|
||||||
|
<string>YOUR CUSTOM URL SCHEME, for example ch.myexample.app</string>
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
|
</array>
|
||||||
|
```
|
||||||
|
|
||||||
### Add Authentication
|
### Add Authentication
|
||||||
|
|
||||||
|
:::note
|
||||||
|
|
||||||
|
The auth redirect scheme "`ch.myexample.app`" does register all auth urls with the given
|
||||||
|
scheme for the app. So an url pointing to `ch.myexample.app://signin` and another one
|
||||||
|
for `ch.myexample.app://logout` will work with the same registration.
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
To reduce the commented default code, we will modify the `main.dart` file.
|
To reduce the commented default code, we will modify the `main.dart` file.
|
||||||
|
|
||||||
First, the `MyApp` class: it remains a stateless widget:
|
First, the `MyApp` class: it remains a stateless widget:
|
||||||
@ -207,9 +255,9 @@ Future<void> _authenticate() async {
|
|||||||
try {
|
try {
|
||||||
final result = await _appAuth.authorizeAndExchangeCode(
|
final result = await _appAuth.authorizeAndExchangeCode(
|
||||||
AuthorizationTokenRequest(
|
AuthorizationTokenRequest(
|
||||||
'CLIENT_ID',
|
'<<CLIENT_ID>>', // Client ID of the native application
|
||||||
'CALLBACK_URL',
|
'<<CALLBACK_URL>>', // The registered url from zitadel (e.g. ch.myexample.app://signin)
|
||||||
issuer: 'ISSUER',
|
issuer: '<<ISSUER>>', // most of the cases: https://issuer.zitadel.ch
|
||||||
scopes: [
|
scopes: [
|
||||||
'openid',
|
'openid',
|
||||||
'profile',
|
'profile',
|
||||||
@ -359,6 +407,10 @@ class _MyHomePageState extends State<MyHomePage> {
|
|||||||
|
|
||||||
If you run this application, you can authenticate with a valid ZITADEL user.
|
If you run this application, you can authenticate with a valid ZITADEL user.
|
||||||
|
|
||||||
![Flutter Unauthenticated](/img/flutter/not-authed.png)
|
<div style={{display:'flex', 'justify-content': 'center'}}>
|
||||||
|
<div style={{display:'flex', 'align-items': 'center'}}>
|
||||||
![Flutter Authenticated](/img/flutter/authed.png)
|
<img src="/img/flutter/not-authed.png" alt="Unauthenticated" height="500px" />
|
||||||
|
<span style={{padding:'1rem'}}>becomes</span>
|
||||||
|
<img src="/img/flutter/authed.png" alt="Flutter Authenticated" height="500px" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@ -21,37 +21,37 @@ module.exports = {
|
|||||||
type: 'doc',
|
type: 'doc',
|
||||||
docId: 'manuals/introduction',
|
docId: 'manuals/introduction',
|
||||||
label: 'Manuals',
|
label: 'Manuals',
|
||||||
position: 'left'
|
position: 'left',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'doc',
|
type: 'doc',
|
||||||
label: 'Quickstarts',
|
label: 'Quickstarts',
|
||||||
docId: 'quickstarts/introduction',
|
docId: 'quickstarts/introduction',
|
||||||
position: 'left'
|
position: 'left',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'doc',
|
type: 'doc',
|
||||||
label: 'Guides',
|
label: 'Guides',
|
||||||
docId: 'guides/introduction',
|
docId: 'guides/introduction',
|
||||||
position: 'left'
|
position: 'left',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'doc',
|
type: 'doc',
|
||||||
label: 'APIs',
|
label: 'APIs',
|
||||||
docId: 'apis/introduction',
|
docId: 'apis/introduction',
|
||||||
position: 'left'
|
position: 'left',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'doc',
|
type: 'doc',
|
||||||
docId: 'concepts/introduction',
|
docId: 'concepts/introduction',
|
||||||
label: 'Concepts',
|
label: 'Concepts',
|
||||||
position: 'left'
|
position: 'left',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'doc',
|
type: 'doc',
|
||||||
docId: 'legal/introduction',
|
docId: 'legal/introduction',
|
||||||
label: 'Legal',
|
label: 'Legal',
|
||||||
position: 'left'
|
position: 'left',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
href: 'https://github.com/caos/zitadel',
|
href: 'https://github.com/caos/zitadel',
|
||||||
@ -118,10 +118,10 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
algolia: {
|
algolia: {
|
||||||
apiKey: 'bff480bce03126c2d348345647854e91',
|
apiKey: 'bff480bce03126c2d348345647854e91',
|
||||||
indexName: 'zitadel'
|
indexName: 'zitadel',
|
||||||
},
|
},
|
||||||
prism: {
|
prism: {
|
||||||
additionalLanguages: ['csharp'],
|
additionalLanguages: ['csharp', 'dart', 'groovy'],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
presets: [
|
presets: [
|
||||||
@ -130,8 +130,7 @@ module.exports = {
|
|||||||
{
|
{
|
||||||
docs: {
|
docs: {
|
||||||
sidebarPath: require.resolve('./sidebars.js'),
|
sidebarPath: require.resolve('./sidebars.js'),
|
||||||
editUrl:
|
editUrl: 'https://github.com/caos/zitadel/edit/main/docs/',
|
||||||
'https://github.com/caos/zitadel/edit/main/docs/',
|
|
||||||
},
|
},
|
||||||
theme: {
|
theme: {
|
||||||
customCss: require.resolve('./src/css/custom.css'),
|
customCss: require.resolve('./src/css/custom.css'),
|
||||||
@ -145,6 +144,6 @@ module.exports = {
|
|||||||
{
|
{
|
||||||
domain: 'docs.zitadel.ch',
|
domain: 'docs.zitadel.ch',
|
||||||
},
|
},
|
||||||
]
|
],
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
4374
docs/yarn.lock
4374
docs/yarn.lock
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user