# Maskinporten reference

## Spec

See the [📚 Nais application reference](/workloads/application/reference/spec.md#maskinporten).

## Runtime variables & credentials

Your application will automatically be injected with environment variables at runtime.

| Environment Variable | Description |
| --- | --- |
| `NAIS_TOKEN_ENDPOINT` | Used to [🎯 consume an external API with Maskinporten](/auth/maskinporten/how-to/consume.md). |
| `NAIS_TOKEN_INTROSPECTION_ENDPOINT` | Used to [🎯 secure your application with Maskinporten](/auth/maskinporten/how-to/secure.md). |

For further details about these endpoints, see the [OpenAPI specification](/auth/reference.md#openapi-specification).

### Variables for manually validating tokens

These variables are optional and should only be used for [manually validating tokens](#manual-token-validation) when 🎯 [securing your application with Maskinporten](/auth/maskinporten/how-to/secure.md).

| Name | Description |
| :--- | :--- |
| `MASKINPORTEN_WELL_KNOWN_URL` | The well-known URL for the [metadata discovery document](/auth/explanations.md#well-known-url-metadata-document) |
| `MASKINPORTEN_ISSUER` | `issuer` from the [metadata discovery document](/auth/explanations.md#issuer). |
| `MASKINPORTEN_JWKS_URI` | `jwks_uri` from the [metadata discovery document](/auth/explanations.md#jwks-endpoint-public-keys). |

`MASKINPORTEN_WELL_KNOWN_URL` is optional if you're using `MASKINPORTEN_ISSUER` and `MASKINPORTEN_JWKS_URI` directly.

## Client ID

The client ID for your application in Maskinporten can be found with the following command:

```shell
kubectl get maskinportenclient -n <team> <name> -o jsonpath='{.status.clientID}'
```

## Claims

See the [Access Token reference in Maskinporten](https://docs.digdir.no/docs/Maskinporten/maskinporten_protocol_token#the-access-token) for a list of all claims.

## Fully qualified scopes

A fully qualified Maskinporten scope consists of a *prefix* and a *subscope*:

```text
scope := <prefix>:<subscope>
```

### Prefix

The *prefix* is set to `nav` for all scopes.

### Subscope

A *subscope* should describe the resource to be exposed as accurately as possible.
It consists of three parts; *product*, *separator* and *name*:

```text
subscope := <product><separator><name>
```

- ***product***: The [`product`](/workloads/application/reference/spec.md#maskinportenscopesexposesproduct) is a logical grouping of resources, such as `arbeid`, `helse`, or `pensjon`.
- ***separator***: The [`separator`](/workloads/application/reference/spec.md#maskinportenscopesexposesseparator) should be set to `/`.
- ***name***: The [`name`](/workloads/application/reference/spec.md#maskinportenscopesexposesname) describes the resource itself.
  It may contain multiple parts separated by `/`.

  The name may also contain a suffix to separate between access levels.
  For instance, you could separate between `write` access:

  ```text
  name := sykepenger/afp.write
  ```

  ...and `read` access:

  ```text
  name := sykepenger/afp.read
  ```

### Example

For the following scope definition:

```yaml
spec:
  maskinporten:
    enabled: true
    scopes:
      exposes:
        # nav:helse/sykepenger/afp.read
        - enabled: true
          product: "helse"
          separator: "/"
          name: "sykepenger/afp.read"
```

the subscope is then:

```text
subscope := helse/sykepenger/afp.read
```

which results in the fully qualified scope:

```text
scope := nav:helse/sykepenger/afp.read
```

## Manual token validation

While we recommend using [the `NAIS_TOKEN_INTROSPECTION_ENDPOINT` endpoint for validating tokens](#runtime-variables-credentials),
you can alternatively validate tokens natively within your application.

Manual validation can be useful if you want to avoid the small overhead of an additional network call
and rather depend on a native library within your ecosystem of choice.
You should be familiar with the [auth concepts](/auth/explanations.md).

Validating a JWT involves a number of steps.
These steps are outlined and described below in a language- and framework-agnostic way.

> **Libraries for token validation**
> We recommend using a library in your language of choice to handle all the validation steps described below.
> Here are some recommended libraries:

> - [navikt/oasis](https://github.com/navikt/oasis) (JavaScript)
> - [navikt/token-support](https://github.com/navikt/token-support) (Java / Kotlin)

> Validation is also supported by many popular frameworks:

> - [Ktor](https://ktor.io/docs/server-jwt.html) (Kotlin)
> - [Spring Security](https://docs.spring.io/spring-security/reference/servlet/oauth2/resource-server/jwt.html) (Java / Kotlin)

To validate the token, start by validating the [signature and standard time-related claims](/auth/explanations.md#token-validation).

Additionally, perform the following validations:

**Issuer validation**

Validate that the `iss` claim has a value that is equal to either:

1. the `MASKINPORTEN_ISSUER` environment variable, or
2. the `issuer` property from the [metadata discovery document](/auth/explanations.md#well-known-url-metadata-document).
  The document is found at the endpoint pointed to by the `MASKINPORTEN_WELL_KNOWN_URL` environment variable.

**Audience validation**

The `aud` claim is not included by default in Maskinporten tokens and does not need to be validated.
It is only included if the consumer has requested an [audience-restricted token](https://docs.digdir.no/maskinporten_func_audience_restricted_tokens.html).

Only validate the `aud` claim if you want to require your consumers to use audience-restricted tokens.
The expected audience value is up to you to define and must be communicated to your consumers.
The value must be an absolute URI (such as `https://some-provider.no` or `https://some-provider.no/api`).

**Signature validation**

Validate that the token is signed with a public key published at the JWKS endpoint.
This endpoint URI can be found in one of two ways:

1. the `MASKINPORTEN_JWKS_URI` environment variable, or
2. the `jwks_uri` property from the metadata discovery document.
  The document is found at the endpoint pointed to by the `MASKINPORTEN_WELL_KNOWN_URL` environment variable.

**Scope validation**

Your application must validate the `scope` claim in the token.

The `scope` claim is a string that contains a whitespace-separated list of scopes, for example:

```json
{
    "scope": "nav:helse/sykepenger/afp.read nav:helse/sykepenger/afp.write"
}
```

Validate that the `scope` claim contains the expected scope(s).

The semantics and authorization that a scope represents is up to you to define and enforce in your application code.

**Claims validation**

[Other claims](#claims) may be present in the token.
Your application should validate these other claims according to your own requirements.
