Done
Done ID

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.

PlatformLibrary examples
Browser (SPA)oidc-client-ts, keycloak-js
iOSAppAuth-iOS
AndroidAppAuth-Android
.NETMicrosoft.AspNetCore.Authentication.OpenIdConnect
Node.jsopenid-client

The Done OS web app uses keycloak-js with PKCE. It is a working example of the browser login.

How the flow works

  1. Your app sends the user to the authorization endpoint of Done ID.
  2. The user signs in on the Done ID login page.
  3. Done ID sends the user back to your redirect URI with a one-time code.
  4. Your app sends the code to the token endpoint and receives tokens.
  5. 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:

ParameterValue
client_idYour client ID
response_typecode
redirect_uriOne of the redirect URIs of your client
scopeopenid and the other scopes that you need. See Scopes.
stateA random value. Your app compares it when the user comes back.
code_challengeBrowser and mobile apps: the PKCE challenge
code_challenge_methodBrowser 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:

ParameterServer-side loginBrowser or mobile login
grant_typeauthorization_codeauthorization_code
codeThe code from the redirectThe code from the redirect
redirect_uriThe same URI as in the login requestThe same URI as in the login request
client_idYour client IDYour client ID
client_secretYour client secretDo not send
code_verifierDo not sendThe 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:

ScopeAdds
profileName and username
emailemail and email_verified
legal-entity.organizationThe user selects a company, and the token contains the company.
legal-entity.individualThe 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 valueLevel
urn:done:acr:basicEmail and password, or another login method
urn:done:acr:strongBankID

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:

ParameterEffect
ui_localesThe language of the page, for example sv or en.
login_hintFills in the email field.
done_countrySets the country of the user, for example Sweden. By default, Done ID detects the country.
done_bankid_by_country=trueShows the BankID of the country of the user as the first login method.
done_hide_elementsHides elements. Give a comma-separated list without spaces.

These are the elements that you can hide:

Element IDElement
social-bankidSwedish BankID button
social-norwegian-bankidNorwegian BankID button
social-microsoftMicrosoft login button
kc-form-loginEmail and password form

Log out

To end the Done ID session, send the user to <issuer>/protocol/openid-connect/logout with these parameters:

ParameterValue
id_token_hintThe ID token of the user
post_logout_redirect_uriOne of the post-logout redirect URIs of your client
client_idYour 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):

  1. Open the login page in the system browser (ASWebAuthenticationSession on iOS, Custom Tabs on Android). Do not use an embedded web view.
  2. Use PKCE with S256.
  3. Use a claimed HTTPS redirect URI or a custom scheme that you own.
  4. Keep the refresh token in the secure storage of the device (Keychain on iOS, Keystore on Android).

See also