Skip to content
Docs · iOS and Android

iOS and Android

Native apps sign people in through their environment’s Lobby in the system browser, never a web view: people use their passkeys, saved passwords and Usher session, and the app never sees a password. The SDKs do the rest of OpenID Connect for you, and keep the tokens on the device.

Register the app

In Usher Console, open the environment, then Applications → New application → Mobile or desktop. Give it a private-use redirect made from a domain you own, such as com.example.notes:/oauth/callback. It gets a client ID and no secret: an app on a phone can’t keep one, so it uses PKCE instead. Console shows the set-up for both platforms.

iOS and macOS

swift
import UsherKit

let usher = UsherClient(configuration: .init(
    issuer: URL(string: "https://login.example.com")!,
    clientID: "…",
    redirectURI: URL(string: "com.example.notes:/oauth/callback")!))

let session = try await usher.signIn()
var request = URLRequest(url: URL(string: "https://api.example.com/notes")!)
try await usher.authorize(&request)

Tokens are kept in the Keychain, on this device only.

Android

kotlin
// build.gradle.kts: manifestPlaceholders["usherRedirectScheme"] = "com.example.notes"
val usher = Usher.client(context, UsherConfiguration(
    issuer = "https://login.example.com",
    clientId = "…",
    redirectUri = "com.example.notes:/oauth/callback"))

val session = usher.signIn(Usher.customTabs(activity))

The sign-in opens in a Custom Tab. The session is encrypted with a key in the Android Keystore.

What the SDKs check

  • PKCE, state and nonce on every sign-in, and the issuer named in the answer (RFC 9207).
  • The ID token’s signature against your environment’s keys, and its issuer, audience and expiry.
  • Refresh tokens rotate: each is used once. Signing out revokes it at Usher.
  • DPoP, if you turn it on: tokens bound to a key on the device, useless if copied elsewhere.

To call your own API with the access token, name the API and ask for it with resources: see Your own APIs.