User login
Use this integration when users sign in to your app with their Done ID account. It uses the OAuth 2.0 authorization code flow. Browser and mobile apps add PKCE.
Before you start, get a client. See Request a client.
Choose a library
Use a certified OIDC library. Do not write the flow yourself. Configure the library with the issuer URL, and it reads the endpoints from the OIDC configuration.
| Platform | Library examples |
|---|---|
| Browser (SPA) | oidc-client-ts, keycloak-js |
| iOS | AppAuth-iOS |
| Android | AppAuth-Android |
| .NET | Microsoft.AspNetCore.Authentication.OpenIdConnect |
| Node.js | openid-client |
The Done OS web app uses keycloak-js with PKCE. It is a working example of the browser login.
How the flow works
- Your app sends the user to the authorization endpoint of Done ID.
- The user signs in on the Done ID login page.
- Done ID sends the user back to your redirect URI with a one-time
code. - Your app sends the
codeto the token endpoint and receives tokens. - Your app uses the access token to call APIs and uses the ID token to identify the user.
Send the user to Done ID
Send the user to <issuer>/protocol/openid-connect/auth with these parameters:
| Parameter | Value |
|---|---|
client_id | Your client ID |
response_type | code |
redirect_uri | One of the redirect URIs of your client |
scope | openid and the other scopes that you need. See Scopes. |
state | A random value. Your app compares it when the user comes back. |
code_challenge | Browser and mobile apps: the PKCE challenge |
code_challenge_method | Browser and mobile apps: S256 |
Done ID accepts only the S256 PKCE method for browser and mobile clients.
Get the tokens
Send a POST request to <issuer>/protocol/openid-connect/token with Content-Type: application/x-www-form-urlencoded:
| Parameter | Server-side login | Browser or mobile login |
|---|---|---|
grant_type | authorization_code | authorization_code |
code | The code from the redirect | The code from the redirect |
redirect_uri | The same URI as in the login request | The same URI as in the login request |
client_id | Your client ID | Your client ID |
client_secret | Your client secret | Do not send |
code_verifier | Do not send | The PKCE verifier |
A server-side client can also send the client ID and the secret in an HTTP Basic Authorization header (client_secret_basic) instead of in the body (client_secret_post). Done ID accepts both.
The response contains an access_token, an id_token, a refresh_token, and expires_in. See Tokens for the contents and the lifetimes.
Refresh the session
The access token expires after a short time. Before it expires, send a POST request to the token endpoint with grant_type=refresh_token and the refresh_token. A server-side client also sends its client_secret.
If the refresh fails, the Done ID session ended. Send the user to the login page again.
Scopes
Always request openid. These scopes are available:
| Scope | Adds |
|---|---|
profile | Name and username |
email | email and email_verified |
legal-entity.organization | The user selects a company, and the token contains the company. |
legal-entity.individual | The user selects a private person, and the token contains the person. |
If you request legal-entity.organization or legal-entity.individual, Done ID shows a selection page after login. The user selects the company or the person that the session is for. If you request both scopes, the user can select from both.
Ask the Done team which scopes your client has. A request for a scope that your client does not have fails with the error invalid_scope.
Require BankID
Done ID has two authentication levels:
| ACR value | Level |
|---|---|
urn:done:acr:basic | Email and password, or another login method |
urn:done:acr:strong | BankID |
If your app needs strong authentication, add acr_values=urn:done:acr:strong to the login request. Done ID then shows only BankID login methods and hides the password form.
The acr claim in the token shows the level of the login. If your app needs strong authentication, make sure that the claim is urn:done:acr:strong before you give access.
Change the login page
You can add these parameters to the login request to change the Done ID login page:
| Parameter | Effect |
|---|---|
ui_locales | The language of the page, for example sv or en. |
login_hint | Fills in the email field. |
done_country | Sets the country of the user, for example Sweden. By default, Done ID detects the country. |
done_bankid_by_country=true | Shows the BankID of the country of the user as the first login method. |
done_hide_elements | Hides elements. Give a comma-separated list without spaces. |
These are the elements that you can hide:
| Element ID | Element |
|---|---|
social-bankid | Swedish BankID button |
social-norwegian-bankid | Norwegian BankID button |
social-microsoft | Microsoft login button |
kc-form-login | Email and password form |
Log out
To end the Done ID session, send the user to <issuer>/protocol/openid-connect/logout with these parameters:
| Parameter | Value |
|---|---|
id_token_hint | The ID token of the user |
post_logout_redirect_uri | One of the post-logout redirect URIs of your client |
client_id | Your client ID |
If your app keeps a refresh token, revoke it before logout. Send a POST request to <issuer>/protocol/openid-connect/revoke with token, token_type_hint=refresh_token, and client_id. A server-side client also sends its client_secret.
Logout ends the Done ID session for all Done OS apps. After logout, the other apps cannot refresh their tokens, and the user must sign in again.
Single sign-on
All Done OS apps share one Done ID session. If the user already signed in to another Done OS app, Done ID does not show the login page again. Done ID sends the user directly back to your app with a code.
Mobile apps
Follow RFC 8252 (OAuth 2.0 for native apps):
- Open the login page in the system browser (
ASWebAuthenticationSessionon iOS, Custom Tabs on Android). Do not use an embedded web view. - Use PKCE with
S256. - Use a claimed HTTPS redirect URI or a custom scheme that you own.
- Keep the refresh token in the secure storage of the device (Keychain on iOS, Keystore on Android).