{"id":15442372,"url":"https://github.com/descope/descope-flutter","last_synced_at":"2026-03-01T15:04:34.351Z","repository":{"id":159472353,"uuid":"634640207","full_name":"descope/descope-flutter","owner":"descope","description":"Flutter library used to integrate with Descope","archived":false,"fork":false,"pushed_at":"2025-08-21T18:01:26.000Z","size":688,"stargazers_count":41,"open_issues_count":10,"forks_count":2,"subscribers_count":13,"default_branch":"main","last_synced_at":"2025-08-28T23:09:37.871Z","etag":null,"topics":["app","authentication","descope","flutter","flutter-sdk","mobile","native","sdk","web"],"latest_commit_sha":null,"homepage":"https://docs.descope.com","language":"Dart","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/descope.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2023-04-30T19:21:51.000Z","updated_at":"2025-08-22T04:56:09.000Z","dependencies_parsed_at":null,"dependency_job_id":"ee0240ff-46b7-457b-99c2-275e2baa5767","html_url":"https://github.com/descope/descope-flutter","commit_stats":{"total_commits":88,"total_committers":5,"mean_commits":17.6,"dds":0.4204545454545454,"last_synced_commit":"378d028fd1b709185dbc97b3b01e75f908cb84d2"},"previous_names":["descope/descope-flutter"],"tags_count":16,"template":false,"template_full_name":null,"purl":"pkg:github/descope/descope-flutter","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/descope%2Fdescope-flutter","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/descope%2Fdescope-flutter/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/descope%2Fdescope-flutter/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/descope%2Fdescope-flutter/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/descope","download_url":"https://codeload.github.com/descope/descope-flutter/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/descope%2Fdescope-flutter/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":275130115,"owners_count":25410638,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-14T02:00:10.474Z","response_time":75,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["app","authentication","descope","flutter","flutter-sdk","mobile","native","sdk","web"],"created_at":"2024-10-01T19:27:04.519Z","updated_at":"2026-03-01T15:04:34.339Z","avatar_url":"https://github.com/descope.png","language":"Dart","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Descope for Flutter\n\nThe Descope package for flutter provides convenient access to the\nDescope user management and authentication APIs for applications written for Flutter.\nYou can read more on the [Descope Website](https://descope.com).\n\n## Features\n\n- [Quickstart](#quickstart)\n- [Session Management](#session-management)\n- [Custom Claims](#custom-claims)\n- [Error handling](#error-handling)\n- [Running Flows](#running-flows)\n- Authenticate users using the authentication methods that suit your needs:\n  - [OTP](#otp-authentication) (one-time password)\n  - [TOTP](#totp-authentication) (timed one-time password / authenticator app)\n  - [Magic Link](#magic-link)\n  - [Enchanted Link](#enchanted-link)\n  - [OAuth](#oauth) (social)\n  - [SSO / SAML](#ssosaml)\n  - [Passkeys](#passkeys)\n  - [Passwords](#password-authentication)\n\n## Quickstart\n\nA Descope `Project ID` is required to initialize the SDK. Find it\non the [project page](https://app.descope.com/settings/project) in\nthe Descope Console.\n\n```dart\nimport 'package:descope/descope.dart';\n\n// Where your application state is being created\nDescope.setup('\u003cYour-Project-ID\u003e');\n\n// Optionally, you can configure the SDK to your needs\nDescope.setup('\u003cYour-Project-Id\u003e', (config) {\n  // set a custom base URL (needs to be set up in the Descope console)\n  config.baseUrl = 'https://my.app.com';\n  // Enable the logger for debugging.\n  // You can use DescopeLogger.debugLogger (or DescopeLogger.unsafeLogger) during development or to diagnose issues.\n  // For production it is advised to provide a custom implementation hooked up to the application's log monitoring system.\n  config.logger = DescopeLogger.debugLogger;\n});\n\n// Load any available sessions\nawait Descope.sessionManager.loadSession();\n```\n\nAuthenticate the user in your application by starting one of the\nauthentication methods. For example, let's use OTP via email:\n\n```dart\n// sends an OTP code to the given email address\nawait Descope.otp.signUp(method: DeliveryMethod.email, loginId: 'andy@example.com');\n```\n\nFinish the authentication by verifying the OTP code the user entered:\n\n```dart\n// if the user entered the right code the authentication is successful\nfinal authResponse = await Descope.otp.verify(method: DeliveryMethod.email, loginId: 'andy@example.com', code: code);\n\n// we create a DescopeSession object that represents an authenticated user session\nfinal session = DescopeSession.fromAuthenticationResponse(authResponse);\n\n// the session manager automatically takes care of persisting the session\n// and refreshing it as needed\nDescope.sessionManager.manageSession(session);\n```\n\nOn the next application launch check if there's a logged in user to\ndecide which screen to show:\n\n```dart\n// check if we have a valid session from a previous launch and that it hasn't expired yet\nif (Descope.sessionManager.session?.refreshToken?.isExpired == true) {\n    // Show main UI\n} else {\n    // Show login UI\n}\n```\n\nUse the active session to authenticate outgoing API requests to the\napplication's backend:\n\n```dart\nrequest.setAuthorization(Descope.sessionManager);\n```\n\n## Session Management\n\nThe `DescopeSessionManager` class is used to manage an authenticated\nuser session for an application.\n\nThe session manager takes care of loading and saving the session as well\nas ensuring that it's refreshed when needed. When the user completes a sign\nin flow successfully you should set the `DescopeSession` object as the\nactive session of the session manager.\n\n```dart\nfinal authResponse = await Descope.otp.verify(method: DeliverMethod.Email, loginId: 'andy@example.com', code: '123456');\nfinal session = DescopeSession.fromAuthenticationResponse(authResponse);\nDescope.sessionManager.manageSession(session);\n```\n\nThe session manager can then be used at any time to ensure the session\nis valid and to authenticate outgoing requests to your backend with a\nbearer token authorization header.\n\n```dart\nrequest.setAuthorization(Descope.sessionManager);\n```\n\nIf your backend uses a different authorization mechanism you can of course\nuse the session JWT directly instead of the extension function. You can either\nadd another extension function on `http.Request` such as the one above, or you\ncan do the following.\n\n```dart\nawait Descope.sessionManager.refreshSessionIfNeeded();\nfinal sessionJwt = Descope.sessionManager.session?.sessionJwt;\nif (sessionJwt != null) {\n    request.headers['X-Auth-Token'] = sessionJwt;\n} else {\n    // unauthorized\n}\n```\n\nWhen the application is relaunched the `DescopeSessionManager` can load the existing\nsession and you can check straight away if there's an authenticated user.\n\n```dart\nawait Descope.sessionManager.loadSession();\n```\n\nIf you prefer to call `loadSession` in your `main()` function, before the platform's\n`runApp()` function is called, then you'll need to ensure the widget bindings are\ninitialized first:\n\n```dart\nvoid main() async {\n  WidgetsFlutterBinding.ensureInitialized();\n\n  Descope.setup('...');\n  await Descope.sessionManager.loadSession();\n\n  final session = Descope.sessionManager.session;\n  if (session != null) {\n    print('User is logged in: ${session.user}');\n  }\n\n  runApp(\n    ...\n  );\n}\n```\n\nWhen the user wants to sign out of the application we revoke the\nactive session and clear it from the session manager:\n\n```dart\nfinal refreshJwt = Descope.sessionManager.session?.refreshToken.jwt;\nif (refreshJwt != null) {\n  Descope.sessionManager.clearSession();\n  try {\n    Descope.auth.revokeSessions(RevokeType.currentSession, refreshJwt);\n  } catch (e) {\n    // handle errors\n  }\n}\n```\n\nIt is also possible to revoke all sessions by providing the appropriate `RevokeType` parameter.\n\nYou can customize how the `DescopeSessionManager` behaves by using\nyour own `storage` and `lifecycle` objects. See the documentation\nfor more details.\n\n## Custom Claims\n\nYou can request for a sign in operation to add additional custom claims to the\nuser's JWT during authentication.\n\nFor example, the following code starts an OTP sign in and requests a custom claim\nwith the authenticated user's full name:\n\n```dart\nconst options = SignInOptions(customClaims: {'name': '{{user.name}}'});\nawait Descope.otp.signIn(method: DeliveryMethod.email, loginId: 'desmond_c@mail.com', options: options);\n```\n\nNote that any custom claims added via this method are considered insecure and will\nbe nested under the `nsec` custom claim.\n\n## Error Handling\n\nAll authentication operations throw a `DescopeException` in case of a failure. There are several\nways to catch and handle a `DescopeException`, and you can use whichever one is more\nappropriate in each specific use case.\n\n```dart\ntry {\n  final authResponse = await Descope.otp.verify(method: DeliveryMethod.email, loginId: loginId, code: code);\n  final session = DescopeSession.fromAuthenticationResponse(authResponse);\n  Descope.sessionManager.manageSession(session);\n} on DescopeException catch (e) {\n  switch(e) {\n    case DescopeException.wrongOTPCode:\n    case DescopeException.invalidRequest:\n      showBadCodeAlert();\n      break;\n    case DescopeException.networkError:\n      showNetworkErrorRetry();\n      break;\n    default:\n      showUnexpectedErrorAlert(with: e);\n  }\n}\n```\n\nSee the `DescopeException` class for specific error values. Note that not all API errors\nare listed in the SDK yet. Please let us know via a Github issue or pull request if you\nneed us to add any entries to make your code simpler.\n\n## Running Flows\n\n**Important Note**: `DescopeFlowView` is only available on iOS and Android platforms. Other platforms can still use the [previous implementation of flows](https://github.com/descope/descope-flutter/blob/main/lib/src/sdk/routes.dart#L52) until `DescopeFlowView` is supported.\n\nWe can authenticate users by building and running Flows. Flows are built in the Descope\n[flow editor](https://app.descope.com/flows). The editor allows you to easily\ndefine both the behavior and the UI that take the user through their\nauthentication journey. Read more about it in the  Descope\n[getting started](https://docs.descope.com/build/guides/gettingstarted/) guide.\n\nThe flow setup differs according to the targeted platforms\n\n### Setup #1: Define and host your flow\n\nBefore we can run a mobile flow, it must first be defined and hosted. Every project\ncomes with predefined flows out of the box. You can customize your flows to suit your needs\nand host it. Follow\nthe [getting started](https://docs.descope.com/build/guides/gettingstarted/) guide for more details.\nYou can host the flow yourself or leverage Descope's hosted flow page. Read more about it [here](https://docs.descope.com/customize/auth/oidc/#hosted-flow-application).\nYou can also check out the [auth-hosting repo itself](https://github.com/descope/auth-hosting).\n\n### (OPTIONAL) Setup #2.1: Enable App Links for Magic Link and OAuth (social) on Android\n\nSome authentication methods rely on leaving the application's context to authenticate the\nuser, such as navigating to an identity provider's website to perform OAuth (social) authentication,\nor receiving a Magic Link via email or text message. If you do not intend to use these authentication\nmethods, you can skip this step. Otherwise, in order for the user to get back\nto your application, setting up [App Links](https://developer.android.com/training/app-links#android-app-links) is required.\nOnce you have a domain set up and [verified](https://developer.android.com/training/app-links/verify-android-applinks) for sending App Links,\nyou'll need to handle the incoming deep links in your app, and resume the flow.\n\n### (OPTIONAL) Setup #2.2: Support Magic Link Redirects on iOS\n\nSupporting Magic Link authentication in flows requires some platform specific setup:\nYou'll need to [support associated domains](https://developer.apple.com/documentation/xcode/supporting-associated-domains?language=swift).\nIt is recommended to follow the [Flutter guide to deep linking](https://docs.flutter.dev/cookbook/navigation/set-up-universal-links) for the basic setup or use an equivalent library.\n\nRegardless of the platform, another path is required to handle magic link redirects specifically. For the sake of this README, let's name\nit `/magiclink`. It is possible to set up multiple paths if needed, in exactly the same way.\n\n### Provide a controller when setting up the DescopeFlowView\nThe `DescopeFlowController` is used to mainly use to call functions on the flow view,\nnamely the `resumeFromDeepLink` function to resume a flow after returning from a magic link or social authentication.\nAll app architectures are different, so it's up to you to decide where to store the controller.\nHere's a simple example of storing it in the app's state:\n```dart\nclass AppModel extends ChangeNotifier {\n  final DescopeFlowController _descopeFlowController = DescopeFlowController();\n\n  DescopeFlowController get descopeFlowController =\u003e _descopeFlowController;\n\n  void handleFlowDeepLink(Uri uri) {\n    _descopeFlowController.resumeFromDeepLink(uri);\n  }\n}\n```\n\n### Define a route to handle the App Link sent at the end of a flow\n_this code example demonstrates how app links should be handled - you can customize it to fit your app_\n```dart\n// There are various way to listen for deep links in Flutter. This example does not assume any specific\n// routing package, and focuses on the deep link handling itself.\nfinal _handleIncomingLinks = (Uri uri) {\n  if (uri.path == '/magiclink' || uri.path == '/oauth') { // This path needs to correspond to the deep link you configured in your manifest or associated domain - see below\n    try {\n      model.handleFlowDeepLink(uri);\n    } catch (e) {\n      // Handle errors here\n    }\n  }\n};\n```\n### Setup #3: Validate everything works\nIf deep links are required for your flows, it is recommended to validate that deep linking has been set up correctly.\nYou can do that by running the app on a real device, and sending an app link to, for example, your email address.\nClicking the link should open the app. If it does not, please review your setup and try again.\n\n### Run a Flow\n\nAfter completing the prerequisite steps, it is now possible to run a flow.\nThe flow will run in a dedicated `DescopeFlowView` widget which receives:\n- `DescopeFlowConfiguration` - defines all of the options available when running a flow on both\n  Android and iOS. Read the class documentation for a detailed explanation.\n- `DescopeFlowCallbacks` - the callbacks or the main method the flow communicates with the hosting app.\n    handle `ready`, `success` and `error` events as makes sense for your app.\n- `DescopeFlowController` - used to control the flow view, mainly resuming from deep links. If no deep links\n  are expected, this can be omitted.\n\nAll of these classes have detailed documentation. It is recommended to read them for a deeper understanding of\nhow to use them.\n\nThere are truly many ways to integrate the flow view into your app. Here's a very simple example of\na screen containing a `DescopeFlowView` with minimal configuration:\n```dart\nclass _NativeFlowScreenState extends State\u003cNativeFlowScreen\u003e {\n  bool _loading = true;\n\n  @override\n  Widget build(BuildContext context) {\n    final bg = Theme.of(context).colorScheme.surface;\n    return Scaffold(\n      backgroundColor: bg,\n      appBar: AppBar(\n        backgroundColor: Theme.of(context).colorScheme.inversePrimary,\n        title: const Text('Descope Flow View Example'),\n        leading: IconButton(\n          icon: const Icon(Icons.close),\n          onPressed: () =\u003e context.pop(),\n          tooltip: 'Close',\n        ),\n      ),\n      body: SafeArea(\n        child: Stack(\n          children: [\n            // Solid background to avoid black flash\n            Positioned.fill(child: ColoredBox(color: bg)),\n            // Keep the platform view mounted but invisible until ready\n            Positioned.fill(\n              child: AnimatedOpacity(\n                opacity: _loading ? 0.0 : 1.0,\n                duration: const Duration(milliseconds: 150),\n                child: DescopeFlowView(\n                  config: DescopeFlowConfig(\n                    url: '\u003cURL for where the flow is hosted, for example: https://api.descope.com/login/[MY_PROJECT_ID]?flow=[MY_FLOW_ID]\u003e',\n                    // Optional parameters - will be required according to the flow you're using\n                    // and the authentication methods it contains\n                    androidOAuthNativeProvider: 'google', // an example supporting native Google Sign In on Android\n                    iosOAuthNativeProvider: 'apple', // an example supporting native Sign In with Apple on iOS\n                    oauthRedirect: 'https://YOUR_DEEP_LINK_URL/oauth', // android only - needs to match the app link you configured in your manifest\n                    magicLinkRedirect: 'https://YOUR_DEEP_LINK_URL/magiclink', // needs to match the app link you configured in your manifest or associated domain\n                  ),\n                  callbacks: DescopeFlowCallbacks(\n                    onReady: () {\n                      // simple reveal animation when the flow is ready\n                      if (!mounted) return;\n                      setState(() =\u003e _loading = false);\n                    },\n                    onSuccess: (AuthenticationResponse res) {\n                      // handle the successful authentication response, assuming the model calls\n                      // something along the lines of:\n                      // final session = DescopeSession.fromAuthenticationResponse(res);\n                      // Descope.sessionManager.manageSession(session);\n                      model.handleAuthResponse(res);\n                      if (context.mounted) context.pop();\n                    },\n                    onError: (DescopeException e) {\n                      // handle any errors that might occur during the flow.\n                      // errors generally mean that the flow is unrecoverable and\n                      // needs to be restarted.\n                      model.handleError(e);\n                      if (context.mounted) context.pop();\n                    },\n                  ),\n                  controller: model.descopeFlowController,\n                ),\n              ),\n            ),\n            if (_loading) const Center(child: CircularProgressIndicator()),\n          ],\n        ),\n      ),\n    );\n  }\n}\n```\n\n## Authentication Methods\n\nWe can authenticate users by using any combination of the authentication methods\nsupported by this SDK.\nHere are some examples for how to authenticate users:\n\n### OTP Authentication\n\nSend a user a one-time password (OTP) using your preferred delivery method (_email / SMS_).\nAn email address or phone number must be provided accordingly.\n\nThe user can either `sign up`, `sign in` or `sign up or in`\n\n```dart\n// Every user must have a loginID. All other user information is optional\nfinal maskedEmail = await Descope.otp.signUp(method: DeliveryMethod.email, loginId: 'desmond_c@mail.com',\n    details: SignUpDetails(name: 'Desmond Copeland'));\n```\n\nThe user will receive a code using the selected delivery method. Verify that code using:\n\n```dart\nfinal authResponse = await Descope.otp.verify(method: DeliveryMethod.email, loginId: 'desmond_c@mail.com', code: '123456');\n```\n\n### Magic Link\n\nSend a user a Magic Link using your preferred delivery method (_email / SMS_).\nThe Magic Link will redirect the user to a page where the attached token needs to be verified. Depending on the target,\nit might be required to use **deep links** to return to the app.\nThis redirection can be configured in code, or globally in\nthe [Descope Console](https://app.descope.com/settings/authentication/magicLink)\n\nThe user can either `sign up`, `sign in` or `sign up or in`\n\n```dart\n// If configured globally, the redirect URL is optional. If provided however, it will be used\n// instead of any global configuration\nawait Descope.magicLink.signUp(method: DeliveryMethod.email, loginId: 'desmond_c@mail.com',\n    details: SignUpDetails(name: 'Desmond Copeland'), redirectUrl: 'https://your-redirect-address.com/verify');\n```\n\nTo verify a magic link, your redirect page must call the validation function\non the token (`t`) parameter (`https://your-redirect-address.com/verify?t=\u003ctoken\u003e`):\n\n```dart\nfinal authResponse = await Descope.magicLink.verify(token: '\u003ctoken\u003e');\n```\n\n### Enchanted Link\n\nUsing the Enchanted Link APIs enables users to sign in by clicking a link\ndelivered to their email address. The email will include 3 different links,\nand the user will have to click the right one, based on the 2-digit number that is\ndisplayed when initiating the authentication process.\n\nThis method is similar to [Magic Link](#magic-link) but differs in two major ways:\n\n- The user must choose the correct link out of the three, instead of having just one\n  single link.\n- This supports cross-device clicking, meaning the user can try to log in on one device,\n  like a computer, while clicking the link on another device, for instance a mobile phone.\n\nThe Enchanted Link will redirect the user to page where the its token needs to be verified.\nThis redirection can be configured in code per request, or set globally in\nthe [Descope Console](https://app.descope.com/settings/authentication/enchantedlink).\n\nThe user can either `sign up`, `sign in` or `sign up or in`\n\n```dart\n// If configured globally, the redirect URL is optional. If provided however, it will be used\n// instead of any global configuration\nfinal enchantedLinkResponse = await Descope.enchantedLink.signUp(loginId: 'desmond_c@mail.com',\n    details: SignUpDetails(name: 'Desmond Copeland'), redirectUrl: 'https://your-redirect-address.com/verify');\n```\n\nInform the user which link is the correct one, using `enchantedLinkResponse.linkId`.\nAfter that, start polling for a valid session. It will be returned once the user\nclicks on the correct link (assuming the redirected web page calls the `validate` method);\n\n```dart\nfinal authResponse = await Descope.enchantedLink.pollForSession(pendingRef: enchantedLinkResponse.pendingRef);\n```\n\n### OAuth\n\nUsers can authenticate using their social logins, using the OAuth protocol.\nConfigure your OAuth settings on the [Descope console](https://app.descope.com/settings/authentication/social).\nIt is recommended to use [flutter_web_auth](https://pub.dev/packages/flutter_web_auth)\nto handle the redirect and code extraction.\n\nTo start a flow call:\n\n```dart\nimport 'package:flutter_web_auth/flutter_web_auth.dart';\n\n// Choose an oauth provider out of the supported providers\n// If configured globally, the redirect URL is optional. If provided however, it will be used\n// instead of any global configuration.\nfinal authUrl = await Descope.oauth.start(provider: OAuthProvider.google, redirectUrl: 'exampleauthschema://my-app.com/handle-oauth');\n```\n\nTake the generated URL and authenticate the user using `flutter_web_auth`\n(read more [here](https://pub.dev/packages/flutter_web_auth)).\nThe user will authenticate with the authentication provider, and will be\nredirected back to the redirect URL, with an appended `code` HTTP URL parameter.\nExchange it to validate the user:\n\n```dart\n// Redirect the user to the returned URL to start the OAuth redirect chain\nfinal result = await FlutterWebAuth.authenticate(url: authUrl, callbackUrlScheme: 'exampleauthschema');\n// Extract the returned code\nfinal code = Uri.parse(result).queryParameters['code'];\n// Exchange code for an authentication response\nfinal authResponse = await Descope.oauth.exchange(code: code!);\n```\n\nWhen running in iOS or Android, you can leverage the [Sign in with Apple](https://developer.apple.com/sign-in-with-apple)\nand [Sign in with Google](https://developer.android.com/training/sign-in/credential-manager)\nfeatures to show a native authentication view that allows the user to login using the account\nthey are already logged into on their device. Note that your application will need some\nconfiguration to support native authentication. See the function documentation for\nmore details.\n\n```dart\nvoid loginWithOAuth() async {\n  AuthenticationResponse response;\n  if (!kIsWeb \u0026\u0026 Platform.isIOS) {\n    // created a custom Apple provider using the app bundle identifier as the Client ID\n    response = await Descope.oauth.native(provider: OAuthProvider.named(\"ios\"));\n  } else if (!kIsWeb \u0026\u0026 Platform.isAndroid) {\n    // created a custom Google provider for implicit authentication\n    response = await Descope.oauth.native(provider: OAuthProvider.named(\"android\"));\n  } else {\n    // regular web OAuth\n  }\n  final session = DescopeSession.fromAuthenticationResponse(response)\n  // ...\n}\n```\n\n### SSO/SAML\n\nUsers can authenticate to a specific tenant using SAML or Single Sign On.\nConfigure your SSO/SAML settings on the [Descope console](https://app.descope.com/settings/authentication/sso).\nIt is recommended to use [flutter_web_auth](https://pub.dev/packages/flutter_web_auth)\nto handle the redirect and code extraction.\n\nTo start a flow call:\n\n```dart\n// Choose which tenant to log into\n// If configured globally, the return URL is optional. If provided however, it will be used\n// instead of any global configuration.\nfinal authUrl = await Descope.sso.start(emailOrTenantId: 'my-tenant-ID', redirectUrl: 'exampleauthschema://my-app.com/handle-saml');\n```\n\nTake the generated URL and authenticate the user using `flutter_web_auth`\n(read more [here](https://pub.dev/packages/flutter_web_auth)).\nThe user will authenticate with the authentication provider, and will be\nredirected back to the redirect URL, with an appended `code` HTTP URL parameter.\nExchange it to validate the user:\n\n```dart\n// Redirect the user to the returned URL to start the OAuth redirect chain\nfinal result = await FlutterWebAuth.authenticate(url: authUrl, callbackUrlScheme: 'exampleauthschema');\n// Extract the returned code\nfinal code = Uri.parse(result).queryParameters['code'];\n// Exchange code for an authentication response\nfinal authResponse = await Descope.sso.exchange(code: code!);\n```\n\n### Passkeys\n\nUsers can authenticate by creating or using a [passkey](https://fidoalliance.org/passkeys/).\nConfigure your Passkey/WebAuthn settings on the [Descope console](https://app.descope.com/settings/authentication/webauthn).\nMake sure it is enabled and that the top level domain is configured correctly.\n\nAfter that, for iOS go through Apple's [Supporting passkeys](https://developer.apple.com/documentation/authenticationservices/public-private_key_authentication/supporting_passkeys/)\nguide, in particular be sure to have an associated domain configured for your app\nwith the `webcredentials` service type, whose value matches the top level domain\nyou configured in the Descope console earlier. \nFor Android, please follow the [Add support for Digital Asset Links](https://developer.android.com/training/sign-in/passkeys#add-support-dal)\nsetup, as described in the official Google docs.\n\n```dart\ntry {\n    showLoading(true);\n    final authResponse = await Descope.passkey.signUpOrIn(loginId: loginId);\n    final session = DescopeSession.fromAuthenticationResponse(authResponse);\n    Descope.sessionManager.manageSession(session);\n    showHomeScreen() \n} on DescopeException catch (e) {\n    if (e == DescopeException.passkeyCancelled) {\n      showLoading(false)\n      print(\"Authentication cancelled\")\n    } else {\n      showError(error)\n    }\n}\n```\n\n### TOTP Authentication\n\nThe user can authenticate using an authenticator app, such as Google Authenticator.\nSign up like you would using any other authentication method. The sign up response\nwill then contain a QR code `image` that can be displayed to the user to scan using\ntheir mobile device camera app, or the user can enter the `key` manually or click\non the link provided by the `provisioningURL`.\n\nExisting users can add TOTP using the `update` function.\n\n```dart\n// Every user must have a loginID. All other user information is optional\nfinal totpResponse = await Descope.totp.signUp(loginId: 'desmond@descope.com', details: SignUpDetails(name: 'Desmond Copeland'));\n\n// Use one of the provided options to have the user add their credentials to the authenticator\n// totpResponse.provisioningUrl\n// totpResponse.image\n// totpResponse.key\n```\n\nThere are 3 different ways to allow the user to save their credentials in\ntheir authenticator app - either by clicking the provisioning URL, scanning the QR\nimage or inserting the key manually. After that, signing in is done using the code\nthe app produces.\n\n```dart\nfinal authResponse = await Descope.totp.verify(loginId: 'desmond@descope.com', code: '123456');\n```\n\n### Password Authentication\n\nIt is possible to authenticate a user using a password. Passwords are a legacy way of authentication.\nEach of the passwordless methods above are better from a security and usability perspective.\nPasswords are disabled by default in the\n[Descope Console password settings](https://app.descope.com/settings/authentication/password).\nMake sure to enable it before attempting authentication.\nThe user can either `sign up` or `sign in`\n\n```dart\n// Every user must have a loginID. All other user information is optional\nfinal authResponse = await Descope.password.signUp(loginId: 'desmond_c@mail.com', password: 'cleartext-password',\n    details: SignUpDetails(name: 'Desmond Copeland'));\n```\n\n#### Update or Replace Password\n\n```dart\n// It's possible to update a user's password when the user has an active session:\nawait Descope.password.update(loginId: 'andy@example.com', newPassword: 'newSecurePassword456!', refreshJwt: \"user-refresh-jwt\");\n\n// Or to replace a user's password by providing their current password.\n// this is especially true when a password expires:\nfinal authResponse = await Descope.password.replace(loginId: 'andy@example.com', oldPassword: 'SecurePassword123!', newPassword: 'NewSecurePassword456!');\n```\n\n#### Send Password Reset Email\n\nInitiate a password reset (update) by sending a magic link email, that needs to be validated\nlike any other magic link. After authenticating the user using this magic link, it's\npossible to use the `update` function to update the user's password:\n\n```dart\nawait Descope.password.sendReset(loginId: 'andy@example.com', redirectUrl: \"exampleauthschema://my-app.com/handle-reset\");\n```\n\n## Additional Information\n\nTo learn more please see the [Descope Documentation and API reference page](https://docs.descope.com/).\n\n## Contact Us\n\nIf you need help you can email [Descope Support](mailto:support@descope.com)\n\n## License\n\nThe Descope SDK for Flutter is licensed for use under the terms and conditions\nof the [MIT license Agreement](https://github.com/descope/descope-flutter/blob/main/LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdescope%2Fdescope-flutter","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdescope%2Fdescope-flutter","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdescope%2Fdescope-flutter/lists"}