- 📱 Web Authentication
- 📱 Credentials Manager
- 🌐 Handling Credentials on the Web
- 📱 Authentication API
- 🌐📱 Organizations
- 📱 Bot detection
- Log out
- Sign up
- Adding an audience
- Adding scopes
- Adding custom parameters
- ID token validation
- Using
SFSafariViewController
(iOS only) - Errors
- Android: Custom schemes
Logging the user out involves clearing the Universal Login session cookie and then deleting the user's credentials from your app.
Call the logout()
method in the onPressed
callback of your Logout button. Once the session cookie has been cleared, auth0_flutter
will automatically delete the user's credentials.
Mobile
If you're using your own credentials storage, make sure to delete the credentials afterward.
// Use a Universal Link logout URL on iOS 17.4+ / macOS 14.4+
// useHTTPS is ignored on Android
await auth0.webAuthentication().logout(useHTTPS: true);
Web
if (kIsWeb) {
await auth0Web.logout(returnToUrl: 'http://localhost:3000');
}
💡 You need to import the
'flutter/foundation.dart'
library to access thekIsWeb
constant. If your app does not support other platforms, you can remove this condition.
You can make users land directly on the Signup page instead of the Login page by specifying the 'screen_hint': 'signup'
parameter. Note that this can be combined with 'prompt': 'login'
, which indicates whether you want to always show the authentication page or you want to skip if there's an existing session.
Parameters | No existing session | Existing session |
---|---|---|
No extra parameters | Shows the login page | Redirects to the callback URL |
'screen_hint': 'signup' |
Shows the signup page | Redirects to the callback URL |
'prompt': 'login' |
Shows the login page | Shows the login page |
'prompt': 'login', 'screen_hint': 'signup' |
Shows the signup page | Shows the signup page |
Mobile
final credentials = await auth0
.webAuthentication()
.login(parameters: {'screen_hint': 'signup'});
Web
await auth0Web.loginWithRedirect(
redirectUrl: 'http://localhost:3000',
parameters: {'screen_hint': 'signup'});
⚠️ Thescreen_hint
parameter will work with the New Universal Login Experience without any further configuration. If you are using the Classic Universal Login Experience, you need to customize the login template to look for this parameter and set theinitialScreen
option of theAuth0Lock
constructor.
Specify an audience value to obtain an access token that can be used to make authenticated requests to a backend. The audience value is the API Identifier of your Auth0 API, for example https://example.com/api
.
Mobile
final credentials = await auth0
.webAuthentication()
.login(audience: 'YOUR_AUTH0_API_IDENTIFIER');
Web
await auth0Web.loginWithRedirect(
redirectUrl: 'http://localhost:3000',
audience: 'YOUR_AUTH0_API_IDENTIFIER');
Specify scopes to request permission to access protected resources, like the user profile.
Mobile
The default scope values are openid
, profile
, email
, and offline_access
. Regardless of the values specified, openid
is always included.
final credentials = await auth0
.webAuthentication()
.login(scopes: {'profile', 'email', 'offline_access', 'read:todos'});
Web
The default scope values are openid
, profile
, and email
. Regardless of the values specified, openid
is always included.
await auth0Web.loginWithRedirect(
redirectUrl: 'http://localhost:3000',
scopes: {'profile', 'email', 'read:todos'});
Specify additional parameters by passing a parameters
map.
Mobile
final credentials = await auth0
.webAuthentication()
.login(parameters: {'connection': 'github'});
Web
Custom parameters can be configured globally.
await auth0Web.onLoad(
parameters: {'connection': 'github'});
Custom parameters can be configured when calling loginWithRedirect
. Any globally configured parameter (passed to onLoad()
) can be overriden when passing the same custom parameter to loginWithRedirect
.
await auth0Web.loginWithRedirect(
redirectUrl: 'http://localhost:3000',
parameters: {'connection': 'github'});
auth0_flutter
automatically validates the ID token obtained from Web Auth login, following the OpenID Connect specification. This ensures the contents of the ID token have not been tampered with and can be safely used.
Mobile
You can configure the ID token validation by passing an IdTokenValidationConfig
instance. Check the API documentation to learn more about the available configuration options.
const config = IdTokenValidationConfig(leeway: 180);
final credentials =
await auth0.webAuthentication().login(idTokenValidationConfig: config);
Web
You can configure issuer
and leeway
values through the onLoad()
method.
auth0Web
.onLoad(issuer: 'https://example.com/', leeway: 180)
.then((final credentials) {
// ...
});
The max_age
value can be configured through loginWithRedirect()
and loginWithPopup()
.
await auth0Web.loginWithRedirect(
redirectUrl: 'http://localhost:3000',
maxAge: 7200);
auth0_flutter supports using SFSafariViewController
as the browser instead of ASWebAuthenticationSession
. Note that it can only be used for login, not for logout. According to its docs, SFSafariViewController
must be used "to visibly present information to users":
This is the case for login, but not for logout. Instead of calling logout()
, you can delete the stored credentials –using the Credentials Manager's clearCredentials()
method– and use 'prompt': 'login'
to force the login page even if the session cookie is still present. Since the cookies stored by SFSafariViewController
are scoped to your app, this should not pose an issue.
await auth0.webAuthentication().login(
safariViewController: const SafariViewController(),
parameters: {'prompt': 'login'}); // Ignore the cookie (if present) and show the login page
💡
SFSafariViewController
does not support using a Universal Link as callback URL. See https://auth0.github.io/Auth0.swift/documentation/auth0/useragents to learn more about the differences betweenASWebAuthenticationSession
andSFSafariViewController
.
If you choose to use SFSafariViewController
, you need to perform an additional bit of setup. Unlike ASWebAuthenticationSession
, SFSafariViewController
will not automatically capture the callback URL when Auth0 redirects back to your app, so it is necessary to manually resume the login operation.
There is an Info.plist
file in the ios/Runner
(or macos/Runner
, for macOS) directory of your app. Open it and add the following snippet inside the top-level <dict>
tag. This registers your iOS/macOS bundle identifier as a custom URL scheme, so the callback URL can reach your app.
<!-- Info.plist -->
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<!-- ... -->
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>None</string>
<key>CFBundleURLName</key>
<string>auth0</string>
<key>CFBundleURLSchemes</key>
<array>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
</array>
</dict>
</array>
<!-- ... -->
</dict>
</plist>
💡 If you're opening the
Info.plist
file in Xcode and it is not being shown in this format, you can Right Click onInfo.plist
in the Xcode project navigator and then select Open As > Source Code.
Using the UIKit app lifecycle
// AppDelegate.swift
override func application(_ app: UIApplication,
open url: URL,
options: [UIApplication.OpenURLOptionsKey: Any]) -> Bool {
WebAuthentication.resume(with: url)
return super.application(application, open: url, options: options);
}
Using the UIKit app lifecycle with Scenes
// SceneDelegate.swift
func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
guard let url = URLContexts.first?.url else { return }
WebAuthentication.resume(with: url)
}
Mobile
Web Auth will only throw WebAuthenticationException
exceptions. Check the API documentation to learn more about the available WebAuthenticationException
properties.
try {
final credentials = await auth0.webAuthentication().login();
// ...
} on WebAuthenticationException catch (e) {
print(e);
}
Web
The web implementation will only throw WebException
exceptions. Check the API documentation to learn more about the available WebException
properties.
try {
await auth0Web.loginWithRedirect(redirectUrl: 'http://localhost:3000');
} on WebException catch (e) {
print(e);
}
On Android, https
is used by default as the callback URL scheme. This works best for Android API 23+ if you're using Android App Links, but in previous Android versions, this may show the intent chooser dialog prompting the user to choose either your app or the browser. You can change this behavior by using a custom unique scheme so that Android opens the link directly with your app.
- Update the
auth0Scheme
manifest placeholder on theandroid/build.gradle
file. - Update the Allowed Callback URLs in the settings page of your Auth0 application.
- Pass the scheme value to the
webAuthentication()
method.
final webAuth = auth0.webAuthentication(scheme: 'YOUR_CUSTOM_SCHEME');
// Login
final credentials = await webAuth.login();
// Logout
await webAuth.logout();
💡 Note that custom schemes can only have lowercase letters.
This feature is mobile/desktop only; on web, the SPA SDK used by auth0_flutter keeps its own cache. See Handling Credentials on the Web for more details.
- Check for stored credentials
- Retrieve stored credentials
- Custom implementations
- Local authentication
- Credentials Manager errors
- Disable credentials storage
The Credentials Manager utility allows you to securely store and retrieve the user's credentials. The credentials will be stored encrypted in Shared Preferences on Android, and in the Keychain on iOS/macOS.
💡 If you're using Web Auth, you do not need to manually store the credentials after login and delete them after logout; auth0_flutter does it automatically.
When the users open your app, check for valid credentials. If they exist, you can retrieve them and redirect the users to the app's main flow without any additional login steps.
final isLoggedIn = await auth0.credentialsManager.hasValidCredentials();
if (isLoggedIn) {
// Retrieve the credentials and redirect to the main flow
} else {
// No valid credentials exist, present the login page
}
The credentials will be automatically renewed (if expired) using the refresh token. This method is thread-safe.
final credentials = await auth0.credentialsManager.credentials();
💡 You do not need to call
credentialsManager.storeCredentials()
afterward. The Credentials Manager automatically persists the renewed credentials.
flutter_auth0 exposes a built-in, default Credentials Manager implementation through the credentialsManager
property. You can pass your own implementation to the Auth0
constructor. If you're using Web Auth, this implementation will be used to store the user's credentials after login and delete them after logout.
final customCredentialsManager = CustomCredentialsManager();
final auth0 = Auth0('YOUR_AUTH0_DOMAIN', 'YOUR_AUTH0_CLIENT_ID',
credentialsManager: customCredentialsManager);
// auth0.credentialsManager is now your CustomCredentialsManager instance
You can enable an additional level of user authentication before retrieving credentials using the local authentication supported by the device, for example PIN or fingerprint on Android, and Face ID or Touch ID on iOS.
const localAuthentication =
LocalAuthentication(title: 'Please authenticate to continue');
final auth0 = Auth0('YOUR_AUTH0_DOMAIN', 'YOUR_AUTH0_CLIENT_ID',
localAuthentication: localAuthentication);
final credentials = await auth0.credentialsManager.credentials();
Check the API documentation to learn more about the available LocalAuthentication
properties.
⚠️ Enabling local authentication will not work if you're using a custom Credentials Manager implementation. In that case, you will need to build support for local authentication into your custom implementation.
By default, auth0_flutter
will automatically store the user's credentials after login and delete them after logout, using the built-in Credentials Manager instance. If you prefer to use your own credentials storage, you need to disable the built-in Credentials Manager.
final credentials =
await auth0.webAuthentication(useCredentialsManager: false).login();
The Credentials Manager will only throw CredentialsManagerException
exceptions. You can find more information in the details
property of the exception. Check the API documentation to learn more about the available CredentialsManagerException
properties.
try {
final credentials = await auth0.credentialsManager.credentials();
// ...
} on CredentialsManagerException catch (e) {
print(e);
}
This section describes handling credentials for the web platform. For mobile/desktop, see Credentials Manager.
The management and storage of credentials is handled internally by the underlying Auth0 SPA SDK, including refreshing the access token when it expires. The Flutter SDK provides an API for checking whether credentials are available, and the retrieval of those credentials.
final isLoggedIn = await auth0Web.hasValidCredentials();
if (isLoggedIn) {
// Retrieve the credentials and redirect to the main flow
} else {
// No valid credentials exist, present the login page
}
Credentials can be retrieved on application start using onLoad()
:
auth0Web.onLoad().then((final credentials) {
if (credentials != null) {
// logged in!
}
});
They can also be retrieved at any time using credentials()
:
final credentials = await auth0Web.credentials();
This feature is mobile/desktop only; the SPA SDK used by auth0_flutter does not include an API client.
- Login with database connection
- Sign up with database connection
- Retrieve user information
- Renew credentials
- API client errors
The Authentication API exposes the AuthN/AuthZ functionality of Auth0, as well as the supported identity protocols like OpenID Connect, OAuth 2.0, and SAML. We recommend using Universal Login, but if you prefer to build your own UI you can use our API endpoints to do so. However, some Auth flows (grant types) are disabled by default so you must enable them on the settings page of your Auth0 application, as explained in Update Grant Types.
To log in or sign up with a username and password, the Password
grant type needs to be enabled in your app. If you set the grants via the Management API you should activate both http://auth0.com/oauth/grant-type/password-realm
and Password
. Otherwise, the Auth0 Dashboard will take care of activating both when enabling Password
.
💡 If your Auth0 account has the Bot Detection feature enabled, your requests might be flagged for verification. Check how to handle this scenario in the Bot Detection section.
⚠️ The ID tokens obtained from Web Auth login are automatically validated byauth0_flutter
, ensuring their contents have not been tampered with. This is not the case for the ID tokens obtained from the Authentication API client, including the ones received when renewing the credentials using the refresh token. You must validate any ID tokens received from the Authentication API client before using the information they contain.
final credentials = await auth0.api.login(
usernameOrEmail: '[email protected]',
password: 'secret-password',
connectionOrRealm: 'Username-Password-Authentication');
// Store the credentials afterward
final didStore =
await auth0.credentialsManager.storeCredentials(credentials);
Add an audience value
Specify an audience to obtain an access token that can be used to make authenticated requests to a backend. The audience value is the API Identifier of your Auth0 API, for example https://example.com/api
.
final credentials = await auth0.api.login(
usernameOrEmail: '[email protected]',
password: 'secret-password',
connectionOrRealm: 'Username-Password-Authentication',
audience: 'YOUR_AUTH0_API_IDENTIFIER');
Add scope values
Specify scopes to request permission to access protected resources, like the user profile. The default scope values are openid
, profile
, email
, and offline_access
. Regardless of the values specified, openid
is always included.
final credentials = await auth0.api.login(
usernameOrEmail: '[email protected]',
password: 'secret-password',
connectionOrRealm: 'Username-Password-Authentication',
scopes: {'profile', 'email', 'offline_access', 'read:todos'});
final databaseUser = await auth0.api.signup(
email: '[email protected]',
password: 'secret-password',
connection: 'Username-Password-Authentication',
userMetadata: {'first_name': 'Jane', 'last_name': 'Smith'});
💡 You might want to log the user in after signup. See Login with database connection above for an example.
Passwordless is a two-step authentication flow that requires the Passwordless OTP grant to be enabled for your Auth0 application. Check our documentation for more information.
Request a code to be sent to the user's email or phone number. For email scenarios, a link can be sent in place of the code.
await auth0.api.startPasswordlessWithEmail(
email: "[email protected]", passwordlessType: PasswordlessType.code);
Using PhoneNumber
await auth0.api.startPasswordlessWithPhoneNumber(
phoneNumber: "123456789", passwordlessType: PasswordlessType.code);
To complete the authentication, you must send back that code the user received along with the email or phone number used to start the flow.
final credentials = await auth0.api.loginWithEmailCode(
email: "[email protected]", verificationCode: "000000");
Using SMS
final credentials = await auth0.api.loginWithSmsCode(
phoneNumber: "123456789", verificationCode: "000000");
Note
Sending additional parameters is supported only on iOS at the moment.
Fetch the latest user information from the /userinfo
endpoint.
This method will yield a UserProfile
instance. Check the API documentation to learn more about its available properties.
final userProfile = await auth0.api.userInfo(accessToken: accessToken);
Use a refresh token to renew the user's credentials. It's recommended that you read and understand the refresh token process beforehand.
final newCredentials =
await auth0.api.renewCredentials(refreshToken: refreshToken);
// Store the credentials afterward
final didStore =
await auth0.credentialsManager.storeCredentials(newCredentials);
💡 To obtain a refresh token, make sure your Auth0 application has the refresh token grant enabled. If you are also specifying an audience value, make sure that the corresponding Auth0 API has the Allow Offline Access setting enabled.
The Authentication API client will only throw ApiException
exceptions. You can find more information in the details
property of the exception. Check the API documentation to learn more about the available ApiException
properties.
try {
final credentials = await auth0.api.login(
usernameOrEmail: email,
password: password,
connectionOrRealm: connection);
// ...
} on ApiException catch (e) {
print(e);
}
Organizations is a set of features that provide better support for developers who build and maintain SaaS and Business-to-Business (B2B) applications.
💡 Organizations is currently only available to customers on our Enterprise and Startup subscription plans.
Mobile
final credentials = await auth0
.webAuthentication()
.login(organizationId: 'YOUR_AUTH0_ORGANIZATION_ID');
Web
await auth0Web.loginWithRedirect(
redirectUrl: 'http://localhost:3000',
organizationId: 'YOUR_AUTH0_ORGANIZATION_ID');
To accept organization invitations your app needs to support deep linking, as invitation links are HTTPS-only. Tapping on the invitation link should open your app.
When your app gets opened by an invitation link, grab the invitation URL and pass it to the login method.
Mobile
final credentials =
await auth0.webAuthentication().login(invitationUrl: url);
Web
await auth0Web.loginWithRedirect(
redirectUrl: 'http://localhost:3000',
invitationUrl: url);
This example is mobile/desktop only; the SPA SDK used by auth0_flutter does not include an API client.
If you are performing database login/signup via the Authentication API and would like to use the Bot Detection feature, you need to handle the isVerificationRequired
error. It indicates that the request was flagged as suspicious and an additional verification step is necessary to log the user in. That verification step is web-based, so you need to use Web Auth to complete it.
try {
final credentials = await auth0.api.login(
usernameOrEmail: email,
password: password,
connectionOrRealm: connection,
scopes: scopes);
// ...
} on ApiException catch (e) {
if (e.isVerificationRequired) {
final credentials = await auth0.webAuthentication().login(
scopes: scopes,
useEphemeralSession: true, // Otherwise a session cookie will remain (iOS/macOS only)
parameters: {
'connection': connection,
'login_hint': email // So the user doesn't have to type it again
});
// ...
}
}