OpenID Connect (OIDC)
Before you start reading this document, please make sure to have covered all topics in OAuth 2.0 Concepts.
OpenID Connect works like OAuth2. The primary use case for OpenID Connect is to solve "Login with <Google|Facebook|Hydra>" flows.
To initiate an OpenID Connect flow all you have to do is to add the openid
scope to your OAuth2 Authorize Code Flow:
https://my-hydra/oauth2/auth?client_id=...&response_type=code&scope=openid
You need to make sure that your OAuth2 Client is allowed to request the openid
scope!
Once you exchange the authorize code for the access and refresh token
POST /oauth/token HTTP/1.1
Host: my-hydra
grant_type=authorization_code
&code=xxxxxxxxxxx
&redirect_uri=https://example-app.com/redirect
&client_id=xxxxxxxxxx
&client_secret=xxxxxxxxxx
you will receive an ID Token:
{
"access_token": "MTQ0NjJkZmQ5OTM2NDE1ZTZjNGZmZjI3",
"token_type": "bearer",
"expires_in": 3600,
"refresh_token": "IwOGYzYTlmM2YxOTQ5MGE3YmNmMDFkNTVk",
"id_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjFlOWdkazcifQ.ewogImlzcyI6ICJodHRwOi8vc2VydmVyLmV4YW1wbGUuY29tIiwKICJzdWIiOiAiMjQ4Mjg5NzYxMDAxIiwKICJhdWQiOiAiczZCaGRSa3F0MyIsCiAibm9uY2UiOiAibi0wUzZfV3pBMk1qIiwKICJleHAiOiAxMzExMjgxOTcwLAogImlhdCI6IDEzMTEyODA5NzAKfQ.ggW8hZ1EuVLuxNuuIJKX_V8a_OMXzR0EHR9R6jgdqrOOF4daGU96Sr_P6qJp6IcmD3HP99Obi1PRs-cwh3LO-p146waJ8IhehcwL7F09JdijmBqkvPeB2T9CJNqeGpe-gccMg4vfKjkM8FcGvnzZUN4_KSP0aAp1tOJ1zZwgjxqGByKHiOtX7TpdQyHE5lcMiKPXfEIQILVq0pc_E2DzL7emopWoaoZTF_m0_N0YzFC6g6EJbOEoRoSK5hoDalrcvRYLSrQAZZKflyuVCyixEoV9GfNQC3_osjzw2PAithfubEEBLuVVk4XUVrWOLrLl0nx7RkKU8NXNHq-rvKMzqg",
"scope": "openid"
}
The ID Token's purpose is to authenticate the End-User at the OAuth2 Client Application. It doesn't solve session management or anything else (you still have to manage cookies, logout, ... yourself!) - it's just a "certificate".
Userinfo
The /userinfo
endpoint returns information on a user given an access token. Since Ory OAuth2 & OpenID is agnostic to any
end-user data, the /userinfo
endpoint returns only minimal information per default:
GET https://ory-hydra:4444/userinfo
Authorization: bearer access-token.xxxx
{
"acr": "oauth2",
"sub": "04d75756-xxxx-4xxx-9xxx-xxxxxxxxxxxx"
}
Any information set to the key session.id_token
during accepting the consent request will also be included here.
// This is node-js pseudo code and won't work if you copy it 1:1
const body = {
// grant_scope: ["foo", "bar"],
// ...
session: {
id_token: {
"foo": "bar"
},
}
}
fetch('https://hydra/oauth2/auth/requests/consent/' + challenge + '/accept', {
method: 'PUT',
body: JSON.stringify(body),
headers: { 'Content-Type': 'application/json' }
}).
// then(function (response) {
By making the /userinfo
call with a token issued by this consent request, one would receive:
GET https://ory-hydra:4444/userinfo
Authorization: bearer new-access-token.xxxx
{
"acr": "oauth2",
"sub": "04d75756-xxxx-4xxx-9xxx-xxxxxxxxxxxx"
"foo": "bar"
}
You should only include data that has been authorized by the end-user through an OAuth 2.0 Scope. If an OAuth 2.0 Client, for
example, requests the phone
scope and the end-user authorizes that scope, the phone number should be added to
session.id_token
.
Be aware that the
/userinfo
endpoint is public. Its contents are thus as publicly visible as those of ID Tokens. It's therefore imperative to not expose sensitive information without end-user consent.