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, 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").bodyverified = io.jwt.verify_rs256(input.token, json.marshal(jwks))
Key rotation
Use the keys published at the JWKS endpoint of the authorization server for token verification, with key rotation 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]jwks = jwks_cached {jwks_cached := jwks_request("https://authorization-server.example.com/jwks").bodyjwt_header.kid == jwks_cached.keys[_].kid} else = jwks_rotated {# Add query param to second request to avoid both getting the same cache keyjwks_rotated := jwks_request("https://authorization-server.example.com/jwks?r=1").body}jwt_verified = jwt_unverified {io.jwt.verify_rs256(input.token, json.marshal(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 == 200t := response.body.access_token}