Version: v0.4

Link and Unlink OpenID Connect and OAuth2 Connections

Because OAuth2 and OpenID Connect (OIDC) require the user to interact with a browser, this strategy does not work with API-only flows. You cannot log in or sign up a user using this strategy

  • with REST API or AJAX requests only;
  • without a browser.

This document summarizes exemplary request payloads for performing "link / unlink your account from Google, Github, ..." flows using the user settings flow with the oidc strategy.

ORY Kratos will prompt the user to re-authenticate before the password is changed, similar to the GitHub sudo mode.

You can configure how long a session is "privileged" by setting:

path/to/kratos/config.yml
selfservice:
flows:
settings:
# Sessions older than a minute requires the user to sign in again before
# the password is changed.
privileged_session_max_age: 1m

The provider's configured JSONNet is not used in this flow. This means that the Identity's Traits will not change when a OpenID Connect / OAuth2 Provider is linked or unlinked.

Here we use a configuration with 3 providers:

path/to/my/kratos/config.yml
selfservice:
strategies:
oidc:
enabled: true
config:
providers:
- id: hydra
# provider, client_id, issuer_url, scope, ...
- id: google
# provider, client_id, issuer_url, scope, ...
- id: github
# provider, client_id, issuer_url, scope, ...

Flow

Redirecting the browser to the Self-Service Settings Endpoint initiates the flow. If the oidc strategy is enabled, the Settings Request Response Payload will include a oidc method.

A provider can be unlinked if there is at least one other method (credential) of signing in (e.g. connected to both GitHub and Google, or having set an email/username + password). A provider can be linked if it has not yet been linked.

In this example, the user used Google to sign in. Because no other credential is enabled, it can not be unlinked and is therefore hidden from the form:

$ curl http://<kratos-admin>/self-service/browser/flows/requests/settings?request=d88e67a6-7011-482b-b448-54629c434f6a
{
id: 'd88e67a6-7011-482b-b448-54629c434f6a',
expires_at: '2020-05-15T11:11:19.909207Z',
issued_at: '2020-05-15T10:11:19.909207Z',
request_url: 'http://127.0.0.1:4433/self-service/browser/flows/settings',
methods: {
// password, profile, ...
oidc: {
method: 'oidc',
config: {
action: 'http://127.0.0.1:4455/.ory/kratos/public/self-service/browser/flows/strategies/oidc/settings/connections?request=e354472c-32b3-4c23-89b7-7edf7418395e',
method: 'POST',
fields: [
{
name: 'csrf_token',
type: 'hidden',
required: true,
value: 'a1CNYwJo3G603eaMLHcDyqPgJz9ArZu2cqJqE+tAvvUkGz63Y1G6WYuBc/EdjFHZM7mSjglbroNQyEAjuY21pw=='
},
{
name: 'link',
type: 'submit',
value: 'hydra'
},
{
name: 'link',
type: 'submit',
value: 'github'
}
]
}
}
},
identity: {
id: 'dd8ce04e-c636-4488-bc92-b5debf73fd30',
schema_id: 'default',
schema_url: '',
traits: {
email: 'superuser@ory.sh',
website: 'https://www.ory.sh'
}
},
update_successful: false
}

Assuming the user chooses to link the GitHub profile, the payload will look like this after a successful flow:

$ curl http://<kratos-admin>/self-service/browser/flows/requests/settings?request=d88e67a6-7011-482b-b448-54629c434f6a
{
"id": "d88e67a6-7011-482b-b448-54629c434f6a",
// expires_at, ...
"update_successful": true // <-- this is now true
"methods": {
"oidc": {
"method": "oidc",
"config": {
"action": "http://127.0.0.1:4455/.ory/kratos/public/self-service/browser/flows/strategies/oidc/settings/connections?request=d88e67a6-7011-482b-b448-54629c434f6a",
"method": "POST",
"fields": [
{
"name": "csrf_token",
"type": "hidden",
"required": true,
"value": "f+SbISlrPFgmV3AtU3GtqJZ5lN0tpRBFLXaeo+6ENw4c/MfQStdBlB1wqja9lS5tSKtXzo1Ex/wPdhPoeLlPrQ=="
},
{
"name": "link",
"type": "submit",
"value": "hydra"
},
{
"name": "unlink", // <- you can now unlink google because github is set up!
"type": "submit",
"value": "google"
},
{
"name": "unlink", // <- this is now unlink!
"type": "submit",
"value": "github"
}
]
}
},
},
// ...
}

If an error occurs during the flow, it will be included in the form error:

$ curl http://<kratos-admin>/self-service/browser/flows/requests/settings?request=d88e67a6-7011-482b-b448-54629c434f6a
{
id: 'd88e67a6-7011-482b-b448-54629c434f6a',
// expires_at, ...
methods: {
oidc: {
method: 'oidc',
config: {
action: 'http://127.0.0.1:4455/.ory/kratos/public/self-service/browser/flows/strategies/oidc/settings/connections?request=d88e67a6-7011-482b-b448-54629c434f6a',
method: 'POST',
messages: [
{
/* id, type */
text: 'Authentication failed because no id_token was returned. Please accept the "openid" permission and try again.'
}
]
// fields
}
}
}
// ...
}

Security and Defenses

Please head over to OpenID Connect Security and Defenses

Last updated on by aeneasr