# OAuth2 and OIDC Samples

OAuth2 and OpenID Connect are both pervasive technologies in modern identity systems. While verification of JSON web tokens issued by these systems is documented in the [policy reference](https://www.openpolicyagent.org/docs/latest/policy-reference/#token-verification), the policy examples below aim to cover some other common use cases.

## Metadata discovery

Rather than storing endpoints and other metadata as part of policy data, the authorization server metadata endpoint may be queried for this data.

```
package oidcissuers := {"https://issuer1.example.com", "https://issuer2.example.com"}metadata_discovery(issuer) := http.send({    "url": concat("", [issuers[issuer], "/.well-known/openid-configuration"]),    "method": "GET",    "force_cache": true,    "force_cache_duration_seconds": 86400 # Cache response for 24 hours}).bodyclaims := jwt.decode(input.token)[1]metadata := metadata_discovery(claims.iss)jwks_endpoint := metadata.jwks_uritoken_endpoint := metadata.token_endpoint
```

## Token verification using JWKS endpoint

Below example uses the keys published at the JWKS endpoint of the authorization server for token verification.

```
package oidcjwks_request(url) := http.send({    "url": url,    "method": "GET",    "force_cache": true,    "force_cache_duration_seconds": 3600 # Cache response for an hour})jwks := jwks_request("https://authorization-server.example.com/jwks").raw_bodyverified := io.jwt.verify_rs256(input.token, jwks)
```

### Key rotation

Use the keys published at the JWKS endpoint of the authorization server for token verification, with [key rotation](https://openid.net/specs/openid-connect-core-1_0.html#RotateSigKeys) taken into account.

```
package oidcjwks_request(url) := http.send({    "url": url,    "method": "GET",    "force_cache": true,    "force_cache_duration_seconds": 3600})jwt_unverified := io.jwt.decode(input.token)jwt_header := jwt_unverified[0]# Use the key ID (kid) from the token as a cache key - if a new kid is encountered# we obtain a fresh JWKS object as the keys have likely been rotated.jwks_url := concat("?", [    "https://authorization-server.example.com/jwks",    urlquery.encode_object({"kid": jwt_header.kid}),])jwks := jwks_request(jwks_url).raw_bodyjwt_verified := jwt_unverified {    io.jwt.verify_rs256(input.token, jwks)}claims_verified := jwt_verified[1]
```

## Token retrieval

Programmatically obtain an OAuth2 access token following the client credentials or resource owner password credential flow.

```
package oauth2token := t {    response := http.send({        "url": "https://authorization-server.example.com/token",        "method": "POST",        "headers": {            "Content-Type": "application/x-www-form-urlencoded",            "Authorization": concat(" ", [                "Basic",                base64.encode(sprintf("%v:%v", [client_id, client_secret]))            ]),        },        # To use the resource owner password credentials flow, change grant_type        # to "password" and add username and password parameters to the body        "raw_body": "grant_type=client_credentials",        "force_cache": true,        "force_cache_duration_seconds": 3595, # Given an `expires_in` value of 3600    })    response.status_code == 200    t := response.body.access_token}
```