# JSON Web Tokens (JWTs)

Tink supports generating and verifying JWTs, which are a widely used standard on
the web. Tink's JWT implementation provides a *subset* of the JWT standard
defined in [RFC 7519](https://datatracker.ietf.org/doc/html/rfc7519 "JSON Web Token (JWT)") that the Tink team considers safe to use, and
that fits well into the Tink library.

Tink does not support parts of the standard that are rarely used or difficult to
use correctly. These are the limitations:

- Tink only supports the [JWS Compact Serialization](https://datatracker.ietf.org/doc/html/rfc7515#section-3.1 "JWS Compact Serialization") format. [JWS JSON Serialization](https://datatracker.ietf.org/doc/html/rfc7515#section-3.2 "JWS JSON Serialization") and [JWE](https://datatracker.ietf.org/doc/html/rfc7516 "JSON Web Encryption (JWE)") are not supported.
- Tink does not support the `None` value in the `alg` header.
- Tink only supports the headers `typ`, `alg`, and `kid`. All other headers are not supported.
- Tink does not allow tokens to be parsed before the signature or MAC is verified.

## JWTs with Signatures

If tokens are generated and verified by different entities, then you should use
asymmetric keys with the primitives `JwtPublicKeySign` and `JwtPublicKeyVerify`.
The private key is used to generate tokens, and the public key is used to verify
tokens. The [algorithms](https://datatracker.ietf.org/doc/html/rfc7518#section-3) supported by these primitives are:
`ES256`, `ES384`, `ES512`, `RS256`, `RS384`, `RS512`, `PS256`, `PS384` and
`PS512`.

### Choose a key type

JWT signatures use *different* key types than the normal digital signature in
Tink. This is needed because some metadata (such as `alg`and `kid`) needs to be
stored with the key.

We recommend using `JWT_ES256` for most use cases. Tokens generated with this
key type always have a `kid` header. If you prefer slightly shorter tokens
without a `kid` header, choose the key type `JWT_ES256_RAW`. For all supported
key types, see [Supported Key Types](https://developers.google.com/tink/supported-key-types#jwt_signature).

### Public keyset distribution

Tink allows public keysets to be converted to and from the JWK Sets format
defined in [RFC 7517](https://datatracker.ietf.org/doc/html/rfc7517#section-5), which most JWT libraries understand.

> [!NOTE]
> **Note:** Tink's JSON keyset serialization format is *not* a JWK Set and other libraries will probably not be able to read it.

Tink does not support exporting public JWT keys in any other format. The reason
for this is that other formats don't contain the `alg` and `kid` metadata to be
used in the verification, which makes using them more error-prone and may make
it more difficult to rotate keys.

It is preferable to not just share the public keyset once, but to provide a way
to *automatically* update the public keyset. (If not, rotating to a new key is
very hard.) This is often done by publishing the public keyset on a trusted and
secured URL. A server that verifies tokens then has to periodically re-fetch the
public keyset from that URL, for example once per day. To rotate the key, the
new public key needs to be added to the public keyset *at least one day before*
it is used to sign tokens. Otherwise the new tokens signed with the new private
key will be rejected by servers that still use the old public keyset.

> [!NOTE]
> **Note:** Some implementations re-fetch the public key as soon as a token with an unknown `kid` header is received. Implementing this logic is not possible in Tink, since the token is not parsed before it is verified. We don't recommend doing this anyway, as it may result in lots of extra requests to the keyset URL if malicious tokens with random `kid` headers are sent.

### Example use cases

See [I want to create and verify JWTs with
signatures](https://developers.google.com/tink/create-jwts-signature).

## JWTs with MACs

Tink supports JWT with symmetric keys with the primitive `JwtMac`. Only use this
primitive if the tokens are generated and verified by the same entity. The
[algorithms](https://datatracker.ietf.org/doc/html/rfc7518#section-3) supported by this primitive are `HS256`, `HS384`
and `HS512`.

### Choose a key type

JWT MAC key types are *different* from normal MAC key types. We recommend using
`JWT_HS256` for most use cases.