Passkeys with Mobile SDKs
This guide is meant for developers that are NOT using Descope Flows to design login screens and authentication methods.
If you'd like to use Descope Flows, Quick Start should be your starting point.
Descope supports passkeys which allow for users to authenticate via the FIDO Alliance's WebAuthn standard. This standard allows for users to authenticate using a variety of methods including biometrics, hardware tokens, and more.
Client SDK
Install SDK
// 1. Within XCode, go to File > Add Packages
// 2. Search for the URL of the git repo: https://github.com/descope/descope-swift
// 3. Configure your desired dependency rule
// 4. Click Add Package// 1. Within Android Studio, go to File > Project Structure > Dependencies > Add Dependency > 1 Library Dependency
// 2. Search for the dependency: "com.descope"
// 3. Configure your desired dependency rules
// 4. Click "Ok"// 1. From your Flutter project directory root, install the Descope SDK by running: flutter pub add descope
// 2. Or, add Descope to your pubspec.yml by including this line: descope: ^0.9.0
// View the package on pub.dev: https://pub.dev/packages/descopeImport and initialize SDK
Parameters:
baseUrl: Custom domain that must be configured to manage token response in cookies. This makes sure every request to our service is through your custom domain, preventing accidental domain blockages.
import DescopeKit
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
Descope.setup(projectId: "<Your-Project-Id>")
return true
}import android.app.Application
import com.descope.Descope
class MyApplication : Application() {
override fun onCreate() {
super.onCreate()
Descope.setup(this, projectId = "<Your-Project-Id>")
}
}import 'package:descope/descope.dart';
// Where your application state is being created
Descope.setup('<Your-Project-Id>', (config) {
// Optional: Only set baseURL if using a custom domain with Descope and managing token response with cookies
config.baseUrl = 'https://auth.app.example.com';
});
await Descope.sessionManager.loadSession();Setup and Authentication
Users can authenticate by creating a new passkey or using an existing one. To enable passkey authentication, first configure your Passkey/WebAuthn settings in the Descope Console.
Make sure Passkey/WebAuthn authentication is enabled and that the top-level domain is configured correctly.
For Android, follow Google's official Add support for Digital Asset Links setup guide. Complete the required asset links and manifest configuration so your app can be associated with your domain.
For iOS and macOS, refer to Apple's Supporting Passkeys guide. Make sure your app has an associated domain configured with the webcredentials service type, and that the value matches the top-level domain configured in the Descope Console.
Check Passkey Support
Before presenting passkey options to users, check whether passkeys are supported on the current device:
Passkeys require iOS 15 and above. You can check availability at runtime using:
if #available(iOS 15, *) {
// Passkeys are supported; show passkey UI
} else {
// Fall back to another authentication method
}The Flutter SDK provides an explicit isSupported() method on Descope.passkey that checks whether passkeys are supported on the current device:
- iOS: returns
trueon iOS 15 and above - Android: returns
trueon API 28 (Android 9) and above - Web: checks for WebAuthn browser support
try {
final supported = await Descope.passkey.isSupported();
if (supported) {
// Passkeys are supported; show passkey UI
} else {
// Fall back to another authentication method
}
} on DescopeException catch (e) {
// Handle errors checking passkey support
}Authenticate with a Passkey
Note
The passkey operations are all suspending functions that perform network requests before and after displaying the modal authentication view.
It is thus recommended to switch the user interface to a loading state before calling them, otherwise the user might accidentally interact with the app when the authentication view is not being displayed.
do {
showLoading(true)
let authResponse = try await Descope.passkey.signUpOrIn(loginId: "andy@example.com", options: [])
let session = DescopeSession(from: authResponse)
Descope.sessionManager.manageSession(session)
showHomeScreen()
} catch DescopeError.oauthNativeCancelled {
showLoading(false)
print("Authentication canceled")
} catch {
showError(error)
}// Enter loading state...
try {
val authResponse = Descope.passkey.signUpOrIn(this@MyActivity, loginId)
val session = DescopeSession(authResponse)
Descope.sessionManager.manageSession(session)
} catch (e: DescopeException) {
// Handle errors here
}
// Exit loading state...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 canceled")
} else {
showError(error)
}
}