Mobile and desktop applications
Sign users in to a mobile or desktop app with OneiD using the system browser, PKCE and a private-use or loopback redirect URI.
Mobile and desktop applications sign users in with the authorization code flow with PKCE, following the practices in RFC 8252, OAuth 2.0 for Native Apps. The app opens the system browser for sign-in and receives the result through a redirect URI that leads back to the app. The app is a public client: it has no secret.
The rules in short
- Public client. An installed app cannot keep a secret. Do not embed one.
- PKCE with
S256. Always required for public clients. - The system browser. Open the sign-in in the platform browser or its in-app browser tab, never in an embedded web view.
- A redirect URI the app can receive: a private-use URI scheme, a loopback address, or a claimed https URL.
- Exact match. The redirect URI the app sends must equal a registered one, including the port for loopback.
Why the system browser
An embedded web view lets the app read what the user types, including the password, and does not share the OneiD session with the browser. The system browser, or an in-app browser tab such as ASWebAuthenticationSession on iOS or Custom Tabs on Android:
- keeps the password out of your app
- shows the user the real OneiD address
- shares the OneiD session, so single sign-on works across apps and the web
Choose a redirect URI
Private-use URI scheme (mobile and desktop)
Use a scheme based on a domain you control, in reverse order, followed by :/ and a path:
com.example.app:/callback
OneiD accepts private-use schemes only for public clients and only in reverse-domain form. Register the scheme with the operating system so that it opens your app.
Loopback (desktop)
A desktop app can start a local HTTP listener and use a loopback redirect:
http://127.0.0.1:52817/callback
OneiD allows http only for loopback addresses: 127.0.0.1, [::1] and localhost. Prefer 127.0.0.1 or [::1] over localhost, as RFC 8252 recommends.
Warning OneiD matches redirect URIs exactly, including the port. RFC 8252 suggests that servers accept any port on a loopback redirect, but OneiD does not. Choose a fixed port for your app, register exactly that URI, and make sure the listener binds to that port. If the port can be taken, register a small number of alternative ports and try them in order.
Claimed https URL (mobile)
On iOS (Universal Links) and Android (App Links), an app can claim an https URL on a domain you control, for example https://app.example.com/callback. It is an ordinary https redirect URI to OneiD, and it gives the strongest guarantee that only your app receives the code.
What to ask your administrator for
- Client type
public. - Grant types: authorization code, and refresh token if the app should stay signed in.
- Redirect URIs, exactly as the app sends them, for example
com.example.app:/callbackorhttp://127.0.0.1:52817/callback. - Post-logout redirect URIs, if the app signs users out through OneiD.
- Allowed scopes, for example
openid profile offline_access orders.read.
Native apps do not call OneiD from a web page, so they do not need allowed CORS origins.
The flow
1. The app creates code_verifier, state and nonce, and derives code_challenge.
2. The app opens the system browser at https://YOUR_ONEID/connect/authorize.
3. The user signs in at OneiD.
4. OneiD redirects to com.example.app:/callback?code=...&state=...&iss=...
The operating system hands this URL to the app.
5. The app checks state and iss, closes the browser tab,
and POSTs code + code_verifier + client_id to /connect/token.
6. The app validates the ID token and stores the tokens securely.
The authorisation request:
GET /connect/authorize?client_id=YOUR_CLIENT_ID&response_type=code&redirect_uri=com.example.app%3A%2Fcallback&scope=openid%20profile%20offline_access&state=Kc7tN2wQ9xLr4Bz1&nonce=Vm3pS8hJd6Gy0Fq5&code_challenge=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM&code_challenge_method=S256 HTTP/1.1
Host: YOUR_ONEID
The token request, sent by the app directly:
POST /connect/token HTTP/1.1
Host: YOUR_ONEID
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code
&code=EXAMPLE_AUTHORIZATION_CODE
&redirect_uri=com.example.app%3A%2Fcallback
&code_verifier=dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk
&client_id=YOUR_CLIENT_ID
The response and the ID token checks are the same as for any client. See Authorization code flow with PKCE.
Checkpoint After sign-in, the browser tab closes or hands control back, your app receives the callback URL with
code,stateandiss, and the token request returns HTTP 200 with anid_token.
Store tokens
- Use the platform’s secure storage: the Keychain on iOS and macOS, the Android Keystore, the Windows Credential Manager or Data Protection API, or the Secret Service on Linux.
- Store the newest refresh token every time you refresh. OneiD rotates refresh tokens, and reusing an old one after about 30 seconds revokes the whole chain. If several parts of your app may refresh at once, let one of them do it. See Refresh tokens.
Libraries
Use a maintained library that implements RFC 8252 rather than writing the flow yourself:
- iOS and macOS: AppAuth for iOS
- Android: AppAuth for Android
- Desktop: a general OpenID Connect client library for your language that supports PKCE and a loopback or private-use redirect
These libraries work with any standards-based provider. Configure them with the OneiD address as the issuer, so they read discovery from https://YOUR_ONEID/.well-known/openid-configuration.
Sign-out
To sign the user out of OneiD as well as your app, open the end session endpoint in the same browser the app used for sign-in, with id_token_hint and a registered post_logout_redirect_uri. Clear the tokens from secure storage first. See Sign-out.