Desktop & mobile apps

Use a Desktop or mobile app client for installed apps. It follows RFC 8252 (OAuth 2.0 for Native Apps): sign-in runs in the system browser, the code comes back to your app, and PKCE protects it. There is no client secret.

Use the system browser

Open the authorization URL in the system browser, or in ASWebAuthenticationSession on iOS/macOS and Custom Tabs on Android. Don't use embedded web views: your app could read the person's password from one, so people should not trust them.

Redirect URLs

Loopback (desktop)

Listen on 127.0.0.1, then register for example http://127.0.0.1:53111/callback. Ports are matched exactly. If your app may use one of several ports, register each one. Pick a few fixed ports and try them in order.

Custom scheme (mobile)

Use a private-use scheme in reverse-domain form, based on a domain you control: com.example.app:/callback. Schemes without a dot are not accepted. On iOS and Android you can also use an https universal or app link that you own.

Libraries

  • iOS / macOS: AppAuth-iOS (OIDAuthorizationService with the discovery document).
  • Android: AppAuth-Android (AuthorizationServiceConfiguration.fetchFromIssuer).
  • Windows / .NET: IdentityModel.OidcClient with a loopback listener.
// AppAuth-Android (Kotlin)
AuthorizationServiceConfiguration.fetchFromIssuer(Uri.parse("https://auth.motaware.com")) { config, ex ->
    val request = AuthorizationRequest.Builder(
        config!!, "mw_yourclientid", ResponseTypeValues.CODE,
        Uri.parse("com.example.app:/callback"))
        .setScopes("openid", "email", "profile", "offline_access")
        .build()   // AppAuth adds PKCE (S256) by default
    startActivityForResult(authService.getAuthorizationRequestIntent(request), RC_AUTH)
}

Storing tokens

Ask for offline_access to get a refresh token, and keep it in the platform's secure store: Keychain on Apple platforms, the Keystore on Android, Credential Manager or DPAPI on Windows. Refresh tokens may be rotated: always store the newest one.