# 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.

Source: https://oltinid.com/docs/guides/native-applications/ · Section: Guides · All OneiD documentation: https://oltinid.com/llms.txt

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:

```text
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:

```text
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:/callback` or `http://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

```text
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:

```http
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:

```http
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](https://oltinid.com/docs/guides/authorization-code-pkce/).

> **Checkpoint:** After sign-in, the browser tab closes or hands control back, your app receives the callback URL with `code`, `state` and `iss`, and the token request returns HTTP 200 with an `id_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](https://oltinid.com/docs/guides/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](https://oltinid.com/docs/guides/logout/).

## Learn more

- [Authorization code flow with PKCE](https://oltinid.com/docs/guides/authorization-code-pkce/)
- [Refresh tokens](https://oltinid.com/docs/guides/refresh-tokens/)
- [Register an application](https://oltinid.com/docs/get-started/register-an-application/)
