docs: improve Flutter quickstart (#1936)

Signed-off-by: Christoph Bühler <cbuehler@rootd.ch>
This commit is contained in:
Christoph Bühler 2021-06-25 13:49:37 +02:00 committed by GitHub
parent 4ecbb932e8
commit 04b84d2c7b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 2267 additions and 2206 deletions

View File

@ -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>

View File

@ -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',
}, },
] ],
], ],
}; };

File diff suppressed because it is too large Load Diff