Skip to content

Authentication

In order to access the Inatur API, a valid bearer token must be provided in the HTTP request's Authentication header. The Inatur API uses OAuth2 and OpenID Connect to authenticate users and provide secure access to resources.

Environments

There are two available authentication servers. Note that bearer tokens issued from one authentication server will only work with the Inatur resource server in the corresponding environment.

Test

Production

Authenticating

Only the OAuth 2 Authorization Code flow is currently supported. This means that your application will never handle the user's credentials directly, but rather delegate authentication requests to Inatur's centralised OIDC server.

Before you can authenticate your application, you must receive a client ID and client secret from Inatur. Contact Inatur if you don't have these, or if the client secret needs to be regenerated.

Exposing the client secret

Ensure that the client secret is never exposed to the user. If you're building a web application, the client secret should only be accessed on the server and never sent to the user's browser. If you're building an application for mobile devices, use the Authorization Code flow with PKCE as described below.

1. Redirect to the authorization endpoint

Redirect the user to the "Authorization endpoint" URL that matches your current environment (ends with /auth; see the Environments section above). If you're building a mobile app, you should open the URL in a webview owned by your application.

Pass the following values as query parameters:

  • client_id - your application's unique client ID
  • response_type - this must be set to "code"
  • redirect_uri - the URL to which which the user will be sent after successful authentication. You must register this with Inatur, and get in touch if it changes. For mobile applications, this should use a protocol unique to your application, e.g. huntingapp://auth/callback.
  • ui_locales - the language in which the authentication UI should be shown. This must be either "no" for Norwegian or "en" for English. If no parameter is passed, the UI is shown in Norwegian.
  • state - a string that can restore the state of your application after authentication is complete. To prevent CSRF attacks, this should also be uniquely traceable back to your application. You can achieve this either by signing it with a secret key known only to your application, or by storing the string in session storage (or similar). See this page for more information about the state parameter.
  • scopes - the permissions your application is requesting access to. This should be a comma-separated string without spaces, e.g. openid,tilbydere. See Scopes for information about valid scopes.

Client-side applications

When building a mobile or single-page application, your application runs entirely on the user's device. It's therefore not possible to securely store the client secret. Instead, Inatur clients that run in these environments must make use of PKCE (proof key for code exchange).

To implement this, perform the following steps for every individual authentication request:

  1. Generate a code_verifier value. This should be a cryptographically secure random string between 43 and 128 characters long.
  2. Compute a code_challenge from the code_verifier. This can be computed using the following function: base64Encode(sha256(code_verifier))).
  3. Store the code_verifier so that it can be retrieved in the callback handler. In a mobile application this can be stored in memory, whilst a single-page application should use either local or session storage due to the redirect that will occur.
  4. Append the following values to the query parameters you created above:
    • code_challenge_method - this must be set to "S256"
    • code_challenge - the code_challenge generated in the previous stage

2. Handle callback response

After authentication, the user will be redirected back to the address sent in the redirect_uri parameter. You will find the following values in the query parameters:

  • code - the unique authorization code that you'll exchange for an access token in the next section
  • state - the string you previously sent to the authorization server

If the authentication request failed for some reason, you will find error and error_description parameters. Use these to provide an informative message to your users about what happened.

Before proceeding, you must verify the state value to ensure that the request to the callback URL comes from Inatur's server. If the verification fails, the authentication flow should be abandoned.

3. Fetching an access token

The final stage is to exchange the code received in the callback handler for an access token.

Send a POST request to the "Token endpoint" that matches your environment (ends with /token). Inside the body of the request, set the following values:

  • code - the code received from the OIDC server in the callback handler
  • grant_type - this must be set to "authorization_code"
  • redirect_uri - this must the same value as sent when redirecting the user to the OIDC server in the first stage

Make sure the body type is x-www-form-urlencoded.

Server-side applications

If you are authenticating through your own backend, you must send a Basic Authentication header with the request. The value of the header should be the string "Basic" followed by the Base64-encoded result of your client ID and client secret separated by a colon. For example, in JavaScript:

function getAuthHeader(clientId, clientSecret) {
  const encoded = btoa(`${clientId}:${clientSecret}`)
  return { Authorization: `Basic ${encoded}` };
}

Client-side applications

If you are developing a mobile or single-page application and authenticating with PKCE, you must also include the code_verifier generated in the previous stage in the request body.

Handling the response

If the POST request succeeds, you will receive a JSON payload with the following structure as a response:

interface TokenResponse {
  /** Your unique access token. */
  access_token: string,
  /** The number of seconds until the access token expires. */
  expires_in: integer,
  /** A token you can exchange for a new access token. */
  refresh_token: string,
  /** The number of seconds until the refresh token expires. */
  refresh_expires_in: integer
}

You are now ready to make requests against the Inatur API on behalf of the logged-in user. Store the access and refresh tokens in a safe place so they can be used in future requests. When calling an endpoint, send the access_token as a bearer token in the Authorization header.

Secure token storage

It's critical that the access and refresh tokens are stored securely, since any third-party that can access it can then impersonate the user.

  • If you're building a server-rendered application, store the access token in a cookie with the HttpOnly and Secure flags enabled. The refresh token should be stored somewhere more persistent, like a database.

  • If you're building a mobile application, use the operating system's secure credential storage system to store the tokens.

Refreshing expired tokens

After a short period of time, the access token will expire and your application will need to fetch a new one. This should be done transparently in the background, to prevent breaks in the user's flow.

To fetch a new access token, send a POST request to the "Token endpoint" that matches your environment (ends with /token). Inside the body of the request, set the following values:

  • grant_type - this must be set to "refresh_token"
  • refresh_token - the refresh token received as part of the token exchange flow

You also need to send a Basic Authentication header in the same manner as above. Note that if you're building a mobile application using PKCE, you should still send a Basic Authentication header, but leave the client secret blank (i.e. base64Encode("${clientId}:")).

If the refresh request succeeds, you'll receive a response containing a new access_token and refresh_token. If the refresh token has expired, the request will not succeed and the user will need start the authentication procedure from the beginning.

Logging out

To log the user out of your application, you must send a POST request to the "Logout" URL that matches your current environment (see Environments).

Inside the body of the request, set the following values:

  • client_id - your application's unique client ID
  • refresh_token - the refresh token received as part of the token exchange flow

If the logout request succeeds, you will receive a response with HTTP status code 204 (no content).

After logging out, you should also be sure to delete the (now invalid) access and refresh tokens from wherever they are being stored.

Reading information about the logged-in user

The access token issued by the OIDC server is a JWT containing information about the user.

In order to decode the JWT, you will need the certificate keys. See the jwks_uri field in the OIDC configuration details for your environment.

The following values are included in the JWT claims might be useful:

  • sub - the user's unique ID according to the OIDC server. Note that this is different to the ID used internally by the Inatur database

  • name - the name of the user

  • email - the user's email address / username

Note that the name and email fields owned by the auth server, and synced to the Inatur database when changed. This should prevent inconsistencies, but it inconsistencies arise then the value contained in the JWT should be considered the source of truth.

For further information about the logged-in user, call the /user endpoint.