---
id: link-unlink-openid-connect-oauth2
title: Link and Unlink OpenID Connect and OAuth2 Connections
---

:::tip Before you start

Please read the
[Username / Email & Password Credentials Documentation](../../../concepts/credentials/username-email-password.mdx)
[OpenID Connect / OAuth2 Credentials Documentation](../../../concepts/credentials/openid-connect-oidc-oauth2.mdx)
and [User Settings Documentation](../user-settings.mdx) first.

:::

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](https://help.github.com/en/github/authenticating-to-github/sudo-mode).

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

```yaml title="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:

```yaml title="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](../user-settings.mdx#user-settings-process-sequence)
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:

```json5 title="$ 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:

```json5 title="$ 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:

```json5 title="$ 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](../user-login-user-registration/openid-connect-social-sign-in-oauth2.mdx#security-and-defenses)
