Standards compliant OpenIdConnect library for flutter that supports:
- Code flow with PKCE (the evolution of implicit flow). This allows poping a web browser (included) for authentication to any open id connect compliant IdP.
- Password flow. For use when you control the client and server and you wish to have your users login directly to your IdP.
- Device flow. For use typically with console applications and similar. Used currently for Windows, Linux and MacOs until WebView is supported on those platforms.
- Full OpenIdConnect Client library that encapsulates the entire process including refresh tokens, refreshing and publishes an event stream for your application.
The base library supports most of the basic OpenIdConnect functionality:
- Authorize/Login (for all 3 code flows)
- Logout
- Revoke Token
- Refresh Token
- User Info
In addition there is a complete OpenIdConnectClient which supports all 3 authorization flows AND automatically maintains login information in secure (ish, web is always the problem with this) storage and automatically refreshes tokens as needed.
Currently supports:
- iOS
- Android
- Web
- Windows
- MacOs
- Linux
For Linux and macOS currently your IdP MUST support device code flow to function properly with interactive login. Otherwise you must use password flow. This is because webView is not yet supported on these environments.
- Dart SDK:
>=3.8.0 <4.0.0 - Flutter SDK:
>=3.27.0
- Android:
minSdkVersion 23 - iOS:
13.0 - macOS:
10.15 - Linux / Windows / Web: no additional package-enforced OS floor beyond the Flutter toolchain you build with
- Add
openidconnectto yourpubspec.yamlfile. - Import
package:openidconnect/openidconnect.dart. - Call the various methods on
OpenIdConnect, or useOpenIdConnectClientand subscribe to its events. - If you still call
initalizeEncryption(...)or passencryptionKeyintoOpenIdConnectClient.create(...), you may keep doing so while upgrading. In2.xthose APIs are compatibility no-ops because endorsed secure storage handles persistence internally. - Review the platform configuration notes below before testing interactive sign-in.
- Android / iOS: usually a custom scheme such as
my.app://callback - macOS: either a custom scheme or a loopback URL such as
http://localhost:14100/callback - Linux / Windows: a loopback URL such as
http://localhost:14100/callback - Web: an HTTPS callback page you host, typically
/callback.html
- Requires Android
minSdkVersion 23 - Add the
native_authenticationcallback receiver activity/intent filter for your redirect URI - Add
INTERNETpermission if your app does not already declare it - Configure Android App Links as well if you use HTTPS callbacks instead of a custom scheme
Helpful references:
The example Android manifest in this repository shows the callback activity wiring for CallbackReceiverActivity.
Custom-scheme manifest snippet:
<uses-permission android:name="android.permission.INTERNET" />
<application ...>
<activity
android:name="dev.celest.native_authentication.CallbackReceiverActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:scheme="openidconnect.example"
android:host="callback" />
</intent-filter>
</activity>
</application>- Requires iOS
13.0+ - Add your custom callback scheme under
CFBundleURLTypesinInfo.plist, or configure Associated Domains for universal links - No OIDC-specific camera/microphone/photo/location permission strings are required by this package
Helpful references:
Custom-scheme Info.plist snippet:
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLName</key>
<string>openidconnect.example</string>
<key>CFBundleURLSchemes</key>
<array>
<string>openidconnect.example</string>
</array>
</dict>
</array>- Requires macOS
10.15+ - Add your custom callback scheme under
CFBundleURLTypesinInfo.plist, or configure Associated Domains for HTTPS callbacks - For sandboxed apps, enable the network entitlements you need, especially outbound client access and loopback/server access if you use localhost callbacks
- No OIDC-specific privacy usage strings are required by this package
Helpful references:
- Apple: Defining a custom URL scheme for your app
- Apple: Supporting associated domains
- Apple: Entitlements
Custom-scheme Runner/Info.plist snippet:
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLName</key>
<string>openidconnect.example</string>
<key>CFBundleURLSchemes</key>
<array>
<string>openidconnect.example</string>
</array>
</dict>
</array>Sandboxed macOS apps that use localhost callbacks should typically enable:
<key>com.apple.security.network.client</key>
<true/>
<key>com.apple.security.network.server</key>
<true/>- Use a loopback redirect URI such as
http://localhost:14100/callback - Register that exact redirect URI with your identity provider
- No plist/manifest permission prompts are required by this package itself on these platforms
-
Copy
callback.htmlfromopenidconnect_webinto thewebfolder of your app. -
Register the exact callback URL, typically
https://your-app.example.com/callback.html, with your IdP. -
Serve the app from
https:orhttp://localhostso browser secure storage works. -
OpenIdConnect web supports both popup and same-tab redirect-loop interactive login. Use the popup flow when authentication starts from a direct user gesture. Use
useWebPopup = falsewhen a popup would be blocked, and complete the result viaOpenIdConnect.processStartup(...)orOpenIdConnectClient.create(...)after the app reloads.
Note: It is VERY important to make sure you test on Firefox with the web, as it's behavior for blocking popups is significantly more restrictive than Chromium browsers.
Because of the ever changing nature of desktop support on flutter and incomplete plugin implementations the following are outstanding and will be updated when the functionality exists to do so:
- Add more end-to-end coverage around interactive login/logout flows.
- More documentation!
Pull requests most welcome to fix any bugs found or address any of the above TODOs. I'm not a C++, Kotlin or Swift developer, so custom implementations for various environments would be greatly appreciated.
If adding a custom environment other than android and iOS please follow the flutter best practices and add a separate implementation project with: flutter create --template=plugin --platforms={YourPlatformHere} openidconnect_{YourPlatformHere} and add your code as appropriate there and then update the example project to use the new implementation.
Your new implementation needs to import the platform interface which is exactly one entry. That entry passes in the url to display in the secure browser and the redirect url that you should watch for to respond accordingly. (You can ignore the redirect url on most platforms that support custom URLs such as Android, iOS etc.) You should return the entire redirected URL which should include the ?code= (and perhaps state) when complete.
Everything else is handled in native dart code so the implementation is very straight forward.