OAuth2 webhooks
Ory OAuth2 and OpenID Connect comes with a mechanism that allows updating id_token
and access_token
when a registered client
sends a token refresh request. The flow is realized by calling the defined refresh token hook endpoint which returns updated data.
If the data provided by the webhook is different from the data the client sends, the webhook overwrites the session data with a new set.
The hook is called before any other logic is executed. If the hook execution fails, the entire token refresh flow fails and the
refresh_token
remains unused.
Configuration
Use the Ory CLI with key /oauth2/refresh_token_hook
to enable this feature:
ory patch oauth2-config {project.id} \
--add "/oauth2/refresh_token_hook=\"https://my-example.app/token-refresh-hook\"" \
--format yaml
Webhook payload
The refresh token hook endpoint must accept the following payload format:
{
"subject": "foo",
"client_id": "bar",
"session": {
"id_token": {
"id_token_claims": {
"jti": "jti",
"iss": "http://localhost:4444/",
"sub": "foo",
"aud": ["bar"],
"iat": 1234567,
"exp": 1234567,
"rat": 1234567,
"auth_time": 1234567,
"nonce": "",
"at_hash": "",
"acr": "1",
"amr": [],
"c_hash": "",
"ext": {}
},
"headers": {
"extra": {
"kid": "key-id"
}
},
"username": "username",
"subject": "foo",
"expires_at": 1234567
},
"extra": {},
"client_id": "bar",
"consent_challenge": "",
"exclude_not_before_claim": false,
"allowed_top_level_claims": [],
"kid": "key-id"
},
"requester": {
"client_id": "bar",
"granted_scopes": ["openid", "offline"],
"granted_audience": [],
"grant_types": ["refresh_token"]
},
"granted_scopes": ["openid", "offline"],
"granted_audience": []
}
session
represents the consent session, along with the data that was passed to the
Accept Consent Request in the id_token
field.
requester
is the token request context.
To update the data, the webhook must return a 200 OK
response and the updated session data in the following format:
{
"session": {
"access_token": {
"foo": "bar"
},
"id_token": {
"bar": "baz"
}
}
}
Alternatively, you can choose not to update the session data by returning a 204 No Content
response.
The token subject is never overridden.
Updated tokens
The following examples show fragments of tokens issued after refreshing:
- id_token
- access_token
{
"aud": [
"my_client"
],
"auth_time": 1647427485,
"bar": "baz",
"iss": "http://ory.hydra.example/",
"sub": "foo@bar.com"
}
{
"active": true,
"scope": "openid offline",
"client_id": "my_client",
"sub": "foo@bar.com",
"aud": [],
"iss": "http://ory.hydra.example/",
"token_type": "Bearer",
"token_use": "access_token",
"ext": {
"foo": "bar"
}
}
Rejecting token refresh
To gracefully reject token contents update, the hook must return a 403 Forbidden
response. Any other response results in a
failure of the token update and, as a result, failure of the entire token refresh flow.