descope

Creator: coderz1093

Last updated:

0 purchases

descope Image
descope Images

Languages

Categories

Add to Cart

Description:

descope

Descope for Flutter #
The Descope package for flutter provides convenient access to the
Descope user management and authentication APIs for applications written for Flutter.
You can read more on the Descope Website.
Features #

Quickstart
Session Management
Custom Claims
Error handling
Running Flows
Authenticate users using the authentication methods that suit your needs:

OTP (one-time password)
TOTP (timed one-time password / authenticator app)
Magic Link
Enchanted Link
OAuth (social)
SSO / SAML
Passkeys
Passwords



Quickstart #
A Descope Project ID is required to initialize the SDK. Find it
on the project page in
the Descope Console.
import 'package:descope/descope.dart';

// Where your application state is being created
Descope.setup('<Your-Project-ID>');

// Optionally, you can configure the SDK to your needs
Descope.setup('<Your-Project-Id>', (config) {
// set a custom base URL (needs to be set up in the Descope console)
config.baseUrl = 'https://my.app.com';
// enable the logger
if (kDebugMode) {
config.logger = DescopeLogger();
}
});

// Load any available sessions
await Descope.sessionManager.loadSession();
copied to clipboard
Authenticate the user in your application by starting one of the
authentication methods. For example, let's use OTP via email:
// sends an OTP code to the given email address
await Descope.otp.signUp(method: DeliveryMethod.email, loginId: '[email protected]');
copied to clipboard
Finish the authentication by verifying the OTP code the user entered:
// if the user entered the right code the authentication is successful
final authResponse = await Descope.otp.verify(method: DeliveryMethod.email, loginId: '[email protected]', code: code);

// we create a DescopeSession object that represents an authenticated user session
final session = DescopeSession.fromAuthenticationResponse(authResponse);

// the session manager automatically takes care of persisting the session
// and refreshing it as needed
Descope.sessionManager.manageSession(session);
copied to clipboard
On the next application launch check if there's a logged in user to
decide which screen to show:
// check if we have a valid session from a previous launch and that it hasn't expired yet
if (Descope.sessionManager.session?.refreshToken?.isExpired == true) {
// Show main UI
} else {
// Show login UI
}
copied to clipboard
Use the active session to authenticate outgoing API requests to the
application's backend:
request.setAuthorization(Descope.sessionManager);
copied to clipboard
Session Management #
The DescopeSessionManager class is used to manage an authenticated
user session for an application.
The session manager takes care of loading and saving the session as well
as ensuring that it's refreshed when needed. When the user completes a sign
in flow successfully you should set the DescopeSession object as the
active session of the session manager.
final authResponse = await Descope.otp.verify(method: DeliverMethod.Email, loginId: '[email protected]', code: '123456');
final session = DescopeSession.fromAuthenticationResponse(authResponse);
Descope.sessionManager.manageSession(session);
copied to clipboard
The session manager can then be used at any time to ensure the session
is valid and to authenticate outgoing requests to your backend with a
bearer token authorization header.
request.setAuthorization(Descope.sessionManager);
copied to clipboard
If your backend uses a different authorization mechanism you can of course
use the session JWT directly instead of the extension function. You can either
add another extension function on http.Request such as the one above, or you
can do the following.
await Descope.sessionManager.refreshSessionIfNeeded();
final sessionJwt = Descope.sessionManager.session?.sessionJwt;
if (sessionJwt != null) {
request.headers['X-Auth-Token'] = sessionJwt;
} else {
// unauthorized
}
copied to clipboard
When the application is relaunched the DescopeSessionManager can load the existing
session and you can check straight away if there's an authenticated user.
await Descope.sessionManager.loadSession();
copied to clipboard
If you prefer to call loadSession in your main() function, before the platform's
runApp() function is called, then you'll need to ensure the widget bindings are
initialized first:
void main() async {
WidgetsFlutterBinding.ensureInitialized();

Descope.setup('...');
await Descope.sessionManager.loadSession();

final session = Descope.sessionManager.session;
if (session != null) {
print('User is logged in: ${session.user}');
}

runApp(
...
);
}
copied to clipboard
When the user wants to sign out of the application we revoke the
active session and clear it from the session manager:
final refreshJwt = Descope.sessionManager.session?.refreshJwt;
if (refreshJwt != null) {
Descope.auth.logout(refreshJwt);
Descope.sessionManager.clearSession();
}
copied to clipboard
You can customize how the DescopeSessionManager behaves by using
your own storage and lifecycle objects. See the documentation
for more details.
Custom Claims #
You can request for a sign in operation to add additional custom claims to the
user's JWT during authentication.
For example, the following code starts an OTP sign in and requests a custom claim
with the authenticated user's full name:
const options = SignInOptions(customClaims: {'name': '{{user.name}}'});
await Descope.otp.signIn(method: DeliveryMethod.email, loginId: '[email protected]', options: options);
copied to clipboard
Note that any custom claims added via this method are considered insecure and will
be nested under the nsec custom claim.
Error Handling #
All authentication operations throw a DescopeException in case of a failure. There are several
ways to catch and handle a DescopeException, and you can use whichever one is more
appropriate in each specific use case.
try {
final authResponse = await Descope.otp.verify(method: DeliveryMethod.email, loginId: loginId, code: code);
final session = DescopeSession.fromAuthenticationResponse(authResponse);
Descope.sessionManager.manageSession(session);
} on DescopeException catch (e) {
switch(e) {
case DescopeException.wrongOTPCode:
case DescopeException.invalidRequest:
showBadCodeAlert();
break;
case DescopeException.networkError:
showNetworkErrorRetry();
break;
default:
showUnexpectedErrorAlert(with: e);
}
}
copied to clipboard
See the DescopeException class for specific error values. Note that not all API errors
are listed in the SDK yet. Please let us know via a Github issue or pull request if you
need us to add any entries to make your code simpler.
Running Flows #
We can authenticate users by building and running Flows. Flows are built in the Descope
flow editor. The editor allows you to easily
define both the behavior and the UI that take the user through their
authentication journey. Read more about it in the Descope
getting started guide.
The flow setup differs according to the targeted platforms
Mobile Flows Setup #
Setup #1: Define and host your flow
Before we can run a mobile flow, it must first be defined and hosted. Every project
comes with predefined flows out of the box. You can customize your flows to suit your needs
and host it. Follow
the getting started guide for more details.
You can host the flow yourself or leverage Descope's hosted flow page. Read more about it here.
You can also check out the auth-hosting repo itself.
(Android Only) Setup #2: Enable App Links
Running a flow via the Flutter SDK, when targeting Android, requires setting up App Links.
This is essential for the SDK to be notified when the user has successfully
authenticated using a flow. Once you have a domain set up and
verified
for sending App Links, you'll need to handle the incoming deep links in your app:
Define a route to handle the App Link sent at the end of a flow
this code example demonstrates how app links should be handled - you can customize it to fit your app
final _router = GoRouter(
routes: [
GoRoute(
path: '/',
builder: (_, __) => const MyHomePage(title: 'Flutter Demo Home Page'), // Your main app
routes: [
GoRoute(
path: 'auth', // This path needs to correspond to the deep link you configured in your manifest - see below
redirect: (context, state) async {
try {
Descope.flow.exchange(state.uri); // Call exchange to complete the flow
} catch (e) {
// Handle errors here
}
return '/'; // This route doesn't display anything but returns the root path where the user will be signed in
},
),
// Magic Link handling will be here. See the documentation below.
],
),
],
);
copied to clipboard
Add a matching Manifest declaration
Read more about the flutter specific meta-data tag mentioned here in the official documentation.
<activity
android:name=".MainActivity"
android:exported="true"
android:launchMode="singleTask"
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize"> <!-- exported, singleTop are enabled by default but singleTask is required for the magic links to work -->

<!-- add the following at the end of the activity tag, after anything you have defined currently -->

<meta-data android:name="flutter_deeplinking_enabled" android:value="true" />
<intent-filter android:autoVerify="true"> <!-- autoVerify required for app links -->
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<!-- replace with your host, the path can change must must be reflected when running the flow -->
<!-- the path should correspond with the routing path defined above -->
<data android:scheme="https" android:host="<YOUR_HOST_HERE>" android:path="/auth" />
<!-- see magic link setup below for more details -->
<data android:scheme="https" android:host="<YOUR_HOST_HERE>" android:path="/magiclink" />
</intent-filter>
</activity>
copied to clipboard
(OPTIONAL) Setup #3: Support Magic Link Redirects
Supporting Magic Link authentication in flows requires some platform specific setup:

On Android: add another path entry to the App Links.
This is essentially another path in the same as the app link from the previous setup step,
with different handling logic. Refer to the previous section for the manifest setup.
On iOS: You'll need to support associated domains
It is recommended to follow the Flutter guide to deep linking for the basic setup.

Regardless of the platform, another path is required to handle magic link redirects specifically. For the sake of this README, let's name
it /magiclink
Define a route to handle the App Link or Universal Link sent when a magic link is sent
this code example demonstrates how app links or universal links should be handled - you can customize it to fit your app
final _router = GoRouter(
routes: [
GoRoute(
path: '/',
builder: (_, __) => const MyHomePage(title: 'Flutter Demo Home Page'),
routes: [
GoRoute(
path: 'auth',
redirect: (context, state) {
try {
Descope.flow.exchange(state.uri);
} catch (e) {
// Handle errors here
}
return '/';
},
),
// Adding the magic link handling here:
GoRoute(
path: 'magiclink', // This path needs to correspond to the deep link you configured in your manifest or associated domain - see below
redirect: (context, state) async {
try {
await Descope.flow.resume(state.uri); // Resume the flow after returning from a magic link
} catch (e) {
// Handle errors here
}
return '/'; // This route doesn't display anything but returns the root path where the user will be signed in
},
),
],
),
],
);
copied to clipboard
Web Flows Setup #
When targeting the Web, the flow is embedded into the web app as a Web Component.
Provide a flowId to indicate which flow to run. It's recommended to provide the CSS key-value
pairs to control how the flow is positioned and displayed in your page.
final options = DescopeFlowOptions(
web: DescopeWebFlowOptions(
flowId: 'flowId',
flowContainerCss: {
"background-color": "antiquewhite",
"width": "500px",
"min-height": "300px",
"margin": "auto",
"position": "relative",
"top": "50%",
"transform": "translateY(-50%)",
"display": "flex",
"flex-direction": "column",
"align-items": "center",
"justify-content": "center",
"box-shadow": "0px 0px 10px gray",
},
loadingElement: myCustomLoadingElement,
));
copied to clipboard
Handling Redirections
When targeting the web, authentication methods that redirect, such as OAuth and Magic Link,
will redirect back to your web-app according to how they're defined in the flow. When the redirection
happens, make sure any query parameters in the URL remain intact and call the flow start function.
The flow will pick up where it left off.
Run a Flow #
After completing the prerequisite steps, it is now possible to run a flow.
Since this is an async operation, it is recommended to enter a "loading state"
to prevent any unwanted user interactions until the flow is displayed.
The flow will run in a Chrome Custom Tab on Android,
or via ASWebAuthenticationSession on iOS.
Run the flow by calling the flow start function:
final options = DescopeFlowOptions(
mobile: DescopeMobileFlowOptions(
flowUrl: '<URL_FOR_FLOW_IN_MOBILE_SETUP_#1>',
deepLinkUrl: '<URL_FOR_APP_LINK_IN_MOBILE_SETUP_#2>'
),
web: DescopeWebFlowOptions(
flowId: 'flowId',
flowContainerCss: {
"background-color": "antiquewhite",
"width": "500px",
"min-height": "300px",
"margin": "auto",
"position": "relative",
"top": "50%",
"transform": "translateY(-50%)",
"display": "flex",
"flex-direction": "column",
"align-items": "center",
"justify-content": "center",
"box-shadow": "0px 0px 10px gray",
},
));
final authResponse = await Descope.flow.start(options);
final session = DescopeSession.fromAuthenticationResponse(authResponse);
Descope.sessionManager.manageSession(session);
copied to clipboard
When targeting Android, in order to complete the flow successfully, Descope.flow.exchange() function must be called.
See the app link setup for more details.
Authentication Methods #
We can authenticate users by using any combination of the authentication methods
supported by this SDK.
Here are some examples for how to authenticate users:
OTP Authentication #
Send a user a one-time password (OTP) using your preferred delivery method (email / SMS).
An email address or phone number must be provided accordingly.
The user can either sign up, sign in or sign up or in
// Every user must have a loginID. All other user information is optional
final maskedEmail = await Descope.otp.signUp(method: DeliveryMethod.email, loginId: '[email protected]',
details: SignUpDetails(name: 'Desmond Copeland'));
copied to clipboard
The user will receive a code using the selected delivery method. Verify that code using:
final authResponse = await Descope.otp.verify(method: DeliveryMethod.email, loginId: '[email protected]', code: '123456');
copied to clipboard
Magic Link #
Send a user a Magic Link using your preferred delivery method (email / SMS).
The Magic Link will redirect the user to a page where the attached token needs to be verified. Depending on the target,
it might be required to use deep links to return to the app.
This redirection can be configured in code, or globally in
the Descope Console
The user can either sign up, sign in or sign up or in
// If configured globally, the redirect URL is optional. If provided however, it will be used
// instead of any global configuration
await Descope.magicLink.signUp(method: DeliveryMethod.email, loginId: '[email protected]',
details: SignUpDetails(name: 'Desmond Copeland'), redirectUrl: 'https://your-redirect-address.com/verify');
copied to clipboard
To verify a magic link, your redirect page must call the validation function
on the token (t) parameter (https://your-redirect-address.com/verify?t=<token>):
final authResponse = await Descope.magicLink.verify(token: '<token>');
copied to clipboard
Enchanted Link #
Using the Enchanted Link APIs enables users to sign in by clicking a link
delivered to their email address. The email will include 3 different links,
and the user will have to click the right one, based on the 2-digit number that is
displayed when initiating the authentication process.
This method is similar to Magic Link but differs in two major ways:

The user must choose the correct link out of the three, instead of having just one
single link.
This supports cross-device clicking, meaning the user can try to log in on one device,
like a computer, while clicking the link on another device, for instance a mobile phone.

The Enchanted Link will redirect the user to page where the its token needs to be verified.
This redirection can be configured in code per request, or set globally in
the Descope Console.
The user can either sign up, sign in or sign up or in
// If configured globally, the redirect URL is optional. If provided however, it will be used
// instead of any global configuration
final enchantedLinkResponse = await Descope.enchantedLink.signUp(loginId: '[email protected]',
details: SignUpDetails(name: 'Desmond Copeland'), redirectUrl: 'https://your-redirect-address.com/verify');
copied to clipboard
Inform the user which link is the correct one, using enchantedLinkResponse.linkId.
After that, start polling for a valid session. It will be returned once the user
clicks on the correct link (assuming the redirected web page calls the validate method);
final authResponse = await Descope.enchantedLink.pollForSession(pendingRef: enchantedLinkResponse.pendingRef);
copied to clipboard
OAuth #
Users can authenticate using their social logins, using the OAuth protocol.
Configure your OAuth settings on the Descope console.
It is recommended to use flutter_web_auth
to handle the redirect and code extraction.
To start a flow call:
import 'package:flutter_web_auth/flutter_web_auth.dart';

// Choose an oauth provider out of the supported providers
// If configured globally, the redirect URL is optional. If provided however, it will be used
// instead of any global configuration.
final authUrl = await Descope.oauth.start(provider: OAuthProvider.google, redirectUrl: 'exampleauthschema://my-app.com/handle-oauth');
copied to clipboard
Take the generated URL and authenticate the user using flutter_web_auth
(read more here).
The user will authenticate with the authentication provider, and will be
redirected back to the redirect URL, with an appended code HTTP URL parameter.
Exchange it to validate the user:
// Redirect the user to the returned URL to start the OAuth redirect chain
final result = await FlutterWebAuth.authenticate(url: authUrl, callbackUrlScheme: 'exampleauthschema');
// Extract the returned code
final code = Uri.parse(result).queryParameters['code'];
// Exchange code for an authentication response
final authResponse = await Descope.oauth.exchange(code: code!);
copied to clipboard
When running in iOS or Android, you can leverage the Sign in with Apple
and Sign in with Google
features to show a native authentication view that allows the user to login using the account
they are already logged into on their device. Note that your application will need some
configuration to support native authentication. See the function documentation for
more details.
void loginWithOAuth() async {
AuthenticationResponse response;
if (!kIsWeb && Platform.isIOS) {
// created a custom Apple provider using the app bundle identifier as the Client ID
response = await Descope.oauth.native(provider: OAuthProvider.named("ios"));
} else if (!kIsWeb && Platform.isAndroid) {
// created a custom Google provider for implicit authentication
response = await Descope.oauth.native(provider: OAuthProvider.named("android"));
} else {
// regular web OAuth
}
final session = DescopeSession.fromAuthenticationResponse(response)
// ...
}
copied to clipboard
SSO/SAML #
Users can authenticate to a specific tenant using SAML or Single Sign On.
Configure your SSO/SAML settings on the Descope console.
It is recommended to use flutter_web_auth
to handle the redirect and code extraction.
To start a flow call:
// Choose which tenant to log into
// If configured globally, the return URL is optional. If provided however, it will be used
// instead of any global configuration.
final authUrl = await Descope.sso.start(emailOrTenantId: 'my-tenant-ID', redirectUrl: 'exampleauthschema://my-app.com/handle-saml');
copied to clipboard
Take the generated URL and authenticate the user using flutter_web_auth
(read more here).
The user will authenticate with the authentication provider, and will be
redirected back to the redirect URL, with an appended code HTTP URL parameter.
Exchange it to validate the user:
// Redirect the user to the returned URL to start the OAuth redirect chain
final result = await FlutterWebAuth.authenticate(url: authUrl, callbackUrlScheme: 'exampleauthschema');
// Extract the returned code
final code = Uri.parse(result).queryParameters['code'];
// Exchange code for an authentication response
final authResponse = await Descope.sso.exchange(code: code!);
copied to clipboard
Passkeys #
Users can authenticate by creating or using a passkey.
Configure your Passkey/WebAuthn settings on the Descope console.
Make sure it is enabled and that the top level domain is configured correctly.
After that, for iOS go through Apple's Supporting passkeys
guide, in particular be sure to have an associated domain configured for your app
with the webcredentials service type, whose value matches the top level domain
you configured in the Descope console earlier.
For Android, please follow the Add support for Digital Asset Links
setup, as described in the official Google docs.
try {
showLoading(true);
final authResponse = await Descope.passkey.signUpOrIn(loginId: loginId);
final session = DescopeSession.fromAuthenticationResponse(authResponse);
Descope.sessionManager.manageSession(session);
showHomeScreen()
} on DescopeException catch (e) {
if (e == DescopeException.passkeyCancelled) {
showLoading(false)
print("Authentication cancelled")
} else {
showError(error)
}
}
copied to clipboard
TOTP Authentication #
The user can authenticate using an authenticator app, such as Google Authenticator.
Sign up like you would using any other authentication method. The sign up response
will then contain a QR code image that can be displayed to the user to scan using
their mobile device camera app, or the user can enter the key manually or click
on the link provided by the provisioningURL.
Existing users can add TOTP using the update function.
// Every user must have a loginID. All other user information is optional
final totpResponse = await Descope.totp.signUp(loginId: '[email protected]', details: SignUpDetails(name: 'Desmond Copeland'));

// Use one of the provided options to have the user add their credentials to the authenticator
// totpResponse.provisioningUrl
// totpResponse.image
// totpResponse.key
copied to clipboard
There are 3 different ways to allow the user to save their credentials in
their authenticator app - either by clicking the provisioning URL, scanning the QR
image or inserting the key manually. After that, signing in is done using the code
the app produces.
final authResponse = await Descope.totp.verify(loginId: '[email protected]', code: '123456');
copied to clipboard
Password Authentication #
It is possible to authenticate a user using a password. Passwords are a legacy way of authentication.
Each of the passwordless methods above are better from a security and usability perspective.
Passwords are disabled by default in the
Descope Console password settings.
Make sure to enable it before attempting authentication.
The user can either sign up or sign in
// Every user must have a loginID. All other user information is optional
final authResponse = await Descope.password.signUp(loginId: '[email protected]', password: 'cleartext-password',
details: SignUpDetails(name: 'Desmond Copeland'));
copied to clipboard
Update or Replace Password
// It's possible to update a user's password when the user has an active session:
await Descope.password.update(loginId: '[email protected]', newPassword: 'newSecurePassword456!', refreshJwt: "user-refresh-jwt");

// Or to replace a user's password by providing their current password.
// this is especially true when a password expires:
final authResponse = await Descope.password.replace(loginId: '[email protected]', oldPassword: 'SecurePassword123!', newPassword: 'NewSecurePassword456!');
copied to clipboard
Send Password Reset Email
Initiate a password reset (update) by sending a magic link email, that needs to be validated
like any other magic link. After authenticating the user using this magic link, it's
possible to use the update function to update the user's password:
await Descope.password.sendReset(loginId: '[email protected]', redirectUrl: "exampleauthschema://my-app.com/handle-reset");
copied to clipboard
Additional Information #
To learn more please see the Descope Documentation and API reference page.
Contact Us #
If you need help you can email Descope Support
License #
The Descope SDK for Flutter is licensed for use under the terms and conditions
of the MIT license Agreement.

License

For personal and professional use. You cannot resell or redistribute these repositories in their original state.

Files In This Product:

Customer Reviews

There are no reviews.