Auth referenceΒΆ
Libraries for mockingΒΆ
- https://github.com/navikt/mock-oauth2-server
- https://github.com/navikt/fakedings - a wrapper around the above mock server
Libraries and frameworks for validating and acquiring tokensΒΆ
Below is a list of some well-known and widely used libraries for handling OAuth, OpenID Connect, and token validation.
JVMΒΆ
- https://github.com/navikt/token-support
- https://ktor.io/docs/jwt.html
- https://docs.spring.io/spring-security/reference/servlet/oauth2/resource-server/
- https://github.com/pac4j/pac4j
- https://connect2id.com/products/nimbus-oauth-openid-connect-sdk
JavaScriptΒΆ
- https://github.com/navikt/oasis
- https://github.com/panva/jose
- https://github.com/panva/node-openid-client
See also https://jwt.io/libraries for a non-comprehensive list for many other various languages.
Token generatorsΒΆ
In some cases, you want to locally develop and test against a secured API in the development environments. You will need a token to access said API.
See the respective identity provider pages for details on acquiring such tokens:
Login proxyΒΆ
Reference documentation for the login proxy provided by NAIS. Supported identity providers:
- Entra ID for logging in employees.
- ID-porten for logging in citizens.
Login proxy is only available in GCP
Login proxy is only available in GCP clusters, and will not work in on-prem clusters.
AutologinΒΆ
Autologin is not enabled by default. To enable autologin:
Autologin responseΒΆ
Responses returned by autologin depends on the type of request.
Top-level navigation requests result in a HTTP 302 Found
response.
What is a top-level navigation request?
A top-level navigation request is a GET
request that fulfills at least one of the following properties:
- Has the Fetch metadata request headers
Sec-Fetch-Dest=document
andSec-Fetch-Mode=navigate
, or - Has an
Accept
header that includestext/html
GET /some/path
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Referer: https://<ingress>/original/path
This automatically redirects the user to the login endpoint.
To preserve the user's original location, the redirect
parameter is set to the request's Referer
header.
If the Referer
header is empty, the matching ingress context path is used.
Non-navigation requests result in an equivalent response, but with the HTTP 401 Unauthorized
status code:
What is a non-navigation request?
Non-navigation requests are any requests that aren't considered top-level navigation requests. Examples include:
- Non-
GET
requests, such asPOST
orPUT
requests - Any browser request that uses the
Fetch
orXMLHttpRequest
APIs
GET /some/path
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Referer: https://<ingress>/original/path
HTTP/2 401 Unauthorized
Content-Type: application/json
{"error": "unauthenticated, please log in"}
Ensure that your frontend code handles HTTP 401
responses and appropriately notifies the user and/or redirects them to the login endpoint.
Autologin exclusionsΒΆ
Autologin matches all paths for your application's ingresses, except the following:
/oauth2/**
spec.prometheus.path
(if defined)spec.liveness.path
(if defined)spec.readiness.path
(if defined)
You can exclude additional paths by exact match or wildcard patterns:
The paths must be absolute paths. The match patterns use glob-style matching:
- Trailing slashes in paths and patterns are ignored.
- A single asterisk (
/*
) is non-recursive. This matches any subpath directly below the path, excluding itself and any nested paths. - Double asterisks (
/**
) is recursive. This matches any subpath below the path, including itself and any nested paths.
Example match patterns (click to expand)
/allowed
or/allowed/
-
Trailing slashes in paths and patterns are effectively ignored during matching.
β matches:
/allowed
/allowed/
β does not match:
/allowed/nope
/allowed/nope/
/public/*
-
A single asterisk after a slash means any subpath directly below the path, excluding itself and any nested paths.
β matches:
/public/a
β does not match:
/public
/public/a/b
/public/**
-
Double asterisks after a slash means any subpath below the path, including itself and any nested paths.
β matches:
/public
/public/a
/public/a/b
β does not match:
/not/public
/not/public/a
/any*
-
A single asterisk matches any sequence of characters within a path segment.
β matches:
/any
/anything
/anywho
β does not match:
/any/thing
/anywho/mst/ve
/a/*/*
-
β matches:
/a/b/c
/a/bee/cee
β does not match:
/a
/a/b
/a/b/c/d
/static/**/*.js
-
β matches:
/static/bundle.js
/static/min/bundle.js
/static/vendor/min/bundle.js
β does not match:
/static
/static/some.css
/static/min
/static/min/some.css
/static/vendor/min/some.css
EndpointsΒΆ
The following endpoints are available under your application's ingress:
Path | Description | Details |
---|---|---|
GET <ingress>/oauth2/login |
Redirect the user agent here to initiate login. | Login endpoint |
GET <ingress>/oauth2/logout |
Redirect the user agent here to initiate logout. | Logout endpoint |
GET <ingress>/oauth2/session |
Must be requested from user agent. Returns the current user's session metadata | Session endpoint |
POST <ingress>/oauth2/session/refresh |
Must be requested from user agent. Refreshes the tokens and returns the session metadata for the current user | Session refresh endpoint |
Login endpointΒΆ
This endpoint initiates the authentication flow. It is available at:
To log in an end-user, redirect them to this endpoint. After login, they are by default redirected back to the matching context path for your application's ingress:
/
forhttps://<app>.nav.no
/path
forhttps://nav.no/path
Supported query parameters:
redirect
-
Overrides the default redirect:
Value must be an URL encoded absolute path.
prompt
-
Prompts the user to select an account at the identity provider. Useful for switching between multiple accounts.
Value must be
select_account
.
Logout endpointΒΆ
This endpoint triggers single-logout. It is available at:
To log out an end-user, redirect them to this endpoint. After logout, they are by default redirected back to a preconfigured URL.
Supported query parameters:
redirect
-
Overrides the default redirect:
Value must be an URL encoded absolute path.
Session endpointΒΆ
This endpoint returns metadata about the end-user's session as a JSON object. Requests to this endpoint must be triggered from the user agent.
HTTP/2 200 OK
Content-Type: application/json
{
"session": {
"active": true,
"created_at": "2022-08-31T06:58:38.724717899Z",
"ends_at": "2022-08-31T16:58:38.724717899Z",
"ends_in_seconds": 14658,
"timeout_at": "0001-01-01T00:00:00Z",
"timeout_in_seconds": -1
},
"tokens": {
"expire_at": "2022-08-31T14:03:47.318251953Z",
"expire_in_seconds": 4166
"next_auto_refresh_in_seconds": -1,
"refreshed_at": "2022-08-31T12:53:58.318251953Z",
"refresh_cooldown": false,
"refresh_cooldown_seconds": 0
}
}
The table below describes the different fields in the JSON response.
Session Metadata Field Descriptions (click to expand)
Field | Description |
---|---|
session.active |
Whether or not the session is active. If false , the session cannot be refreshed and the user must be redirected to login to obtain a new session. |
session.created_at |
The timestamp that denotes when the session was first created. |
session.ends_at |
The timestamp that denotes when the session will end. After this point, the session is expired and the user must be redirected to login to obtain a new session. |
session.ends_in_seconds |
The number of seconds until session.ends_at . |
session.timeout_at |
The timestamp that denotes when the session will time out. The zero-value, 0001-01-01T00:00:00Z , means no timeout. |
session.timeout_in_seconds |
The number of seconds until session.timeout_at . A value of -1 means no timeout. |
tokens.expire_at |
The timestamp that denotes when the tokens within the session will expire. |
tokens.expire_in_seconds |
The number of seconds until tokens.expire_at . |
tokens.next_auto_refresh_in_seconds |
The number of seconds until the earliest time where the tokens will automatically be refreshed. A value of -1 means that automatic refreshing is not enabled. |
tokens.refreshed_at |
The timestamp that denotes when the tokens within the session was last refreshed. |
tokens.refresh_cooldown |
A boolean indicating whether or not the refresh operation is on cooldown or not. |
tokens.refresh_cooldown_seconds |
The number of seconds until the refresh operation is no longer on cooldown. |
This endpoint will respond with the following HTTP status codes on errors:
HTTP 401 Unauthorized
- no session cookie or matching session found, or maximum lifetime reachedHTTP 500 Internal Server Error
- the login proxy wasn't able to process the request
Otherwise, an HTTP 200 OK
is returned with the metadata with the application/json
as the Content-Type
.
Note that this endpoint will still return HTTP 200 OK
for inactive sessions, as long as the session is not expired.
This allows application to display errors before redirecting the user to login on timeouts.
The HTTP status code alone is insufficient to determine the session state.
Session refresh endpointΒΆ
This endpoint allows for refreshing the end-user's session on demand. Requests to this endpoint must be triggered from the user agent.
Using this endpoint is only necessary when session inactivity timeouts are enabled. The end-user should be prompted to extend their session in accordance with WCAG 2.2.1.
The endpoint will respond with a HTTP 401 Unauthorized
if the session is inactive.
It is otherwise equivalent to the session endpoint.
HTTP/2 200 OK
Content-Type: application/json
{
"session": {
"active": true,
"created_at": "2022-08-31T06:58:38.724717899Z",
"ends_at": "2022-08-31T16:58:38.724717899Z",
"ends_in_seconds": 14658,
"timeout_at": "0001-01-01T00:00:00Z",
"timeout_in_seconds": -1
},
"tokens": {
"expire_at": "2022-08-31T14:03:47.318251953Z",
"expire_in_seconds": 4166,
"next_auto_refresh_in_seconds": 3866,
"refreshed_at": "2022-08-31T12:53:58.318251953Z",
"refresh_cooldown": true,
"refresh_cooldown_seconds": 37
}
}
Session managementΒΆ
A user's session can be inspected by requesting the session endpoint from their user agent.
Session lifetimeΒΆ
Sessions have a maximum lifetime, after which the user is unauthenticated and must perform a new login.
Identity provider | Maximum lifetime |
---|---|
ID-porten | 6 hours |
Entra ID | 10 hours |
Session inactivity timeoutΒΆ
Sessions may have an inactivity timeout. If enabled, the session is marked as invalid if the timeout has been reached. The timeout is reset each time the user's session is refreshed through the session refresh endpoint.
Identity provider | Inactivity timeout |
---|---|
ID-porten | β Yes, 1 hour |
Entra ID | β No timeout |
If inactivity timeout is not enabled, the tokens within the session are automatically refreshed until the session reaches its maximum lifetime.
Automatic session management for ID-porten
nav-dekoratoren displays warnings for sessions nearing lifetime expiry or inactivity timeout, and supports user-initiated session refresh operations.
You do not need to implement your own session management logic if you use nav-dekoratoren
.
The durations for maximum lifetime and inactivity timeout are subject to change. Do not hard-code or depend on these exact values in your application. Prefer using the metadata returned by the session endpoint to determine the session's state.