Entra ID reference¶
Access policies¶
Applications¶
By default, no applications have access to your API. You must explicitly grant access to consumer applications.
spec:
accessPolicy:
inbound:
rules:
- application: app-a
- application: app-b
namespace: other-namespace
- application: app-c
namespace: other-namespace
cluster: other-cluster
The above configuration authorizes the following applications:
- application
app-a
running in the same namespace and same cluster as your application - application
app-b
running in the namespaceother-namespace
in the same cluster - application
app-c
running in the namespaceother-namespace
in the clusterother-cluster
Users¶
By default, no users have access to your application. You must explicitly grant access to either specific groups, all users, or both.
Groups¶
The following configuration only grants users that are direct members of the specified groups access to your application:
spec:
azure:
application:
enabled: true
allowAllUsers: false
claims:
groups:
- id: "<group identifier>"
Warning
Invalid group identifiers are skipped and will not be granted access to your application. Ensure that they are correct and exist in Entra ID.
All users¶
The following configuration grants all users access your application:
Groups and all users¶
If you want to implement custom group-based authorization logic in your application, combine the above two configurations:
spec:
azure:
application:
enabled: true
allowAllUsers: true
claims:
groups:
- id: "<group identifier>"
This has the following effects:
- All users will have access to your application
- If a given user is a direct member of any matching group, the group's identifier will be emitted in the
groups
claim.
Fine-grained permissions¶
You may define custom permissions for your application in Entra ID and grant them to other consumer applications. Permissions will appear as claims in the consumer's token. Your application can then use these claims to implement custom authorization logic.
Warning
Custom permissions only apply in the context of your own application. They are not global permissions.
All the following conditions must be met for the custom permission to appear:
- The token is acquired by a consumer of your application.
- The consumer has been granted a custom permission in your access policy definition.
- The target audience is your application.
Custom scopes¶
A scope only applies to tokens acquired on behalf of an employee.
Applications defined in the access policy are always assigned the default scope named defaultaccess
.
spec:
accessPolicy:
inbound:
rules:
- application: app-a
namespace: other-namespace
cluster: other-cluster
permissions:
scopes:
- "custom-scope"
The above configuration grants the application app-a
the scope custom-scope
.
Scopes will appear as a space separated string in the scp
claim within the user's token.
Example decoded on-behalf-of token (click to expand)
{
"aud": "8a5...",
"iss": "https://login.microsoftonline.com/.../v2.0",
"iat": 1624957183,
"nbf": 1624957183,
"exp": 1624961081,
"aio": "AXQ...",
"azp": "e37...",
"azpacr": "1",
"groups": [
"2d7..."
],
"name": "Navnesen, Navn",
"oid": "15c...",
"preferred_username": "Navn.Navnesen@nav.no",
"rh": "0.AS...",
"scp": "custom-scope defaultaccess",
"sub": "6OC...",
"tid": "623...",
"uti": "i03...",
"ver": "2.0"
}
Custom roles¶
A role only applies to tokens acquired as an application (machine-to-machine calls).
Applications defined in the access policy are always assigned the default role named access_as_application
.
spec:
accessPolicy:
inbound:
rules:
- application: app-a
namespace: other-namespace
cluster: other-cluster
permissions:
roles:
- "custom-role"
The above configuration grants the application app-a
the role custom-role
.
Roles will appear in the roles
claim as an array of strings within the application's token.
Example decoded client credentials token (click to expand)
{
"aud": "8a5...",
"iss": "https://login.microsoftonline.com/.../v2.0",
"iat": 1624957347,
"nbf": 1624957347,
"exp": 1624961247,
"aio": "E2Z...",
"azp": "e37...",
"azpacr": "1",
"oid": "933...",
"rh": "0.AS...",
"roles": [
"access_as_application",
"custom-role"
],
"sub": "933...",
"tid": "623...",
"uti": "kbG...",
"ver": "2.0"
}
Claims¶
Notable claims in tokens from Entra ID:
azp
(authorized party)-
The client ID of the application that requested the token (this would be your consumer).
azp_name
(authorized party name)-
Human-readable client name of the consumer application that requested the token. This complements the client ID found in the
azp
claim and is intended for display purposes only.Not guaranteed to be unique. Should not be used for authorization.
groups
-
JSON array of group identifiers that the user is a member of:
{ "groups": [ "43451d82-19cd-4828-918d-cbf7d5b572ec", "8f0bd3b2-9d3d-4f27-8543-5938db3e6a3e", "2d7..." ] }
Used to implement group-based authorization logic in your application.
Only appears in flows where an end-user is involved, i.e. either login or on-behalf-of.
In order for a group to appear in the claim, all the following conditions must be true:
- The given user is a direct member of the group.
- The group has been granted access to the application.
idtyp
(identity type)-
This is a special claim used to determine whether a token is a machine-to-machine (app-only) token or a on-behalf-of (user) token.
A token is a machine-to-machine token if and only if this claim exists and has the value equal to
app
. NAVident
-
Internal identifier for the employees in NAV.
Only appears in flows where an end-user is involved, i.e. either login or on-behalf-of.
roles
-
JSON array of roles that the application has access to:
Only appears in machine-to-machine tokens.
Consumers defined in the access policy are always assigned the default role named
access_as_application
. You can optionally define and grant them custom roles. scp
(scope)-
The value of this claim is a space-separated string that lists the scopes that the application has access to:
Only appears in on-behalf-of tokens.
Consumers defined in the access policy are always assigned the default scope named
defaultaccess
. You can optionally define and grant them custom scopes.
For a complete list of claims, see the Access Token Claims Reference in Entra ID. We only use v2.0 tokens.
Runtime Variables & Credentials¶
Your application will automatically be injected with environment variables at runtime.
Variables for acquiring tokens¶
These variables are used to:
Name | Description |
---|---|
AZURE_APP_CLIENT_ID |
Client ID that uniquely identifies the application in Entra ID. |
AZURE_APP_CLIENT_SECRET |
Client secret for the application in Entra ID. |
AZURE_APP_WELL_KNOWN_URL |
The well-known URL for the metadata discovery document. |
AZURE_OPENID_CONFIG_TOKEN_ENDPOINT |
token_endpoint from the metadata discovery document. |
AZURE_APP_WELL_KNOWN_URL
is optional if you're using AZURE_OPENID_CONFIG_TOKEN_ENDPOINT
directly.
Variables for validating tokens¶
These variables are used to secure your API:
Name | Description |
---|---|
AZURE_APP_CLIENT_ID |
Client ID that uniquely identifies the application in Entra ID. |
AZURE_APP_WELL_KNOWN_URL |
The well-known URL for the metadata discovery document. |
AZURE_OPENID_CONFIG_ISSUER |
issuer from the metadata discovery document. |
AZURE_OPENID_CONFIG_JWKS_URI |
jwks_uri from the metadata discovery document. |
AZURE_APP_WELL_KNOWN_URL
is optional if you're using AZURE_OPENID_CONFIG_ISSUER
and AZURE_OPENID_CONFIG_JWKS_URI
directly.
Spec¶
For all possible configuration options, see the NAIS application reference.
Tenants¶
Available tenants in Entra ID. NAV has two tenants in Entra ID:
Tenant Name | Description |
---|---|
nav.no |
Production tenant |
trygdeetaten.no |
Development tenant |
Logging into the trygdeetaten.no
tenant
The trygdeetaten.no
tenant is used for development purposes.
To log in to this tenant, you will need a separate account other than your personal NAV account.
There are two types of accounts you can use:
- Synthetic test accounts: Visit the IDA self-service portal. See the #ida channel on Slack for details.
- Personal account: Visit navikt/devuser-check and see the "FAQ" section. Otherwise, consult the #tech-azure channel on Slack.
See also .spec.azure.application.tenant
.
Troubleshooting¶
This section lists common problems and solutions.
Missing application access policy¶
Your application (named A
in the examples below) attempts to consume another application (named B
).
When requesting a token from Entra ID, your application may receive a 400 Bad Request
with an invalid_grant
error response and the following message:
AADSTS501051:
Application
'<client ID>'
(<cluster>:<namespace>:<A>
) is not assigned to a role for the application 'api://<cluster>.<namespace>.<B>
' (<cluster>:<namespace>:<B>
)"
Or the other variant:
AADSTS65001:
The user or administrator has not consented to use the application with ID '
<client ID>
' named '<cluster>:<namespace>:<A>
'.Send an interactive authorization request for this user and resource.
Solution / Answer
-
Ensure that the scope value in your application's request follows the correct format:
api://<cluster>.<namespace>.<application>/.default>
-
Ensure that application
B
's access policy includes applicationA
. - If all else fails, request assistance in the
#nais
channel on Slack.
Missing user access policy¶
When attempting to sign-in or perform the on-behalf-of flow, an application may receive a 400 Bad Request
with an invalid_grant
error response and the following message:
AADSTS50105:
Your administrator has configured the application
<cluster>:<namespace>:<A>
('<client id>
') to block users unless they are specifically granted ('assigned') access to the application.The signed in user '{EmailHidden}' is blocked because they are not a direct member of a group with access, nor had access directly assigned by an administrator.
Please contact your administrator to assign access to this application
Solution / Answer
- Ensure that application
A
has configured user access. - Ensure that the given user is a direct member of any configured groups).
- If all else fails, request assistance in the
#nais
channel on Slack.
Tenant mismatch for signed-in user¶
While attempting to log in, you may receive the following error message from Entra ID:
Selected user account does not exist in tenant '
some-tenant
' and cannot access the application '<client-id>
' in that tenant.The account needs to be added as an external user in the tenant first.
Please use a different account.
Solution / Answer
- Ensure that the user uses an account that matches your application's tenant when logging in.
- If all else fails, request assistance in the
#nais
channel on Slack.