> For the complete documentation index, see [llms.txt](https://docs.authgear.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.authgear.com/authentication-and-access/social-enterprise-login-providers/account-linking.md).

# Account Linking

Connect a social or enterprise login to an existing account that shares the same email, instead of creating a duplicate user or rejecting the signup.

When you add social login to an app that already has users, some of them will click **Continue with Google** even though they originally signed up with an email and password. Both identities carry the same email address, but by default Authgear treats the Google signup as an attempt to create a second account and rejects it with an "account already exists" error.

Account linking changes what happens next. Instead of an error, Authgear detects that the incoming Google account matches an existing user, asks the user to log in to that account once to prove they own it, then attaches the Google identity to it. The user ends up with one account and two ways to sign in.

{% hint style="info" %}
Account linking runs automatically **during signup**. To let an already signed-in user connect a provider from your own UI, see [Link and Unlink Social/Enterprise Provider with the SDK](/authentication-and-access/social-enterprise-login-providers/link-and-unlink-social-enterprise-provider-with-the-sdk.md). Users can also manage their connections on the [User Settings](/customization/built-in-ui/user-settings.md) page.
{% endhint %}

## When to use it

Enable account linking when the same person can reach your app through more than one signup method and you want them to keep a single account. Typical situations:

* **You added Google login to an app with existing password users.** A user who signed up with `alice@example.com` and a password clicks **Continue with Google**. Their Google account uses the same email. With account linking they log in with their password once, and from then on can sign in with either method.
* **You offer several social providers.** A user signs up with Google today and taps **Continue with Apple** on their phone next month. Both accounts share one email; linking keeps them on one Authgear account instead of two.
* **You migrated users into Authgear and later enabled an enterprise provider.** Imported users match their Microsoft Entra ID or ADFS accounts by email, so their first enterprise login attaches to the account you imported rather than creating a fresh one.

## How it works

When a user signs up with a social or enterprise provider, Authgear reads a claim from the provider's user profile (the email, by default) and compares it against the identities of existing users. What happens on a match depends on the `action` you configure:

| Action           | Behavior                                                                                                                                                           |
| ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `error`          | Reject the signup with a "duplicated identity" error. This is the default when account linking is not configured.                                                  |
| `login_and_link` | Show the user their existing account and ask them to log in to it. After they authenticate, add the new provider identity to that account and continue the signup. |

{% hint style="warning" %}
The login step in `login_and_link` prevents account takeover. Some identity providers let anyone register with an unverified email, so an email match alone doesn't prove ownership. Without the login step, an attacker could register `alice@example.com` at such a provider and hijack Alice's account.
{% endhint %}

## Enable account linking

This walkthrough uses Google, but the same configuration works for any provider you have set up.

### Prerequisites

* A Google login provider configured in the Portal under **Authentication > Social / Enterprise Login**, with an alias. This guide assumes the alias `google`. See [Connect Apps to Google](/authentication-and-access/social-enterprise-login-providers/social-login-providers/google.md) if you haven't set this up.

### Add the configuration

Configure account linking in your project's YAML config. In the Portal, go to **Advanced > Edit Config** and add an `account_linking` section:

```yaml
account_linking:
  oauth:
    - alias: google
      oauth_claim:
        pointer: "/email"
      user_profile:
        pointer: "/email"
      action: login_and_link
```

Save the config. The change takes effect immediately.

Each entry under `account_linking.oauth` defines one linking rule:

| Field          | Meaning                                                                                                                                                     |
| -------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `alias`        | Which provider this rule applies to. Must match the alias of a provider under **Social / Enterprise Login**.                                                |
| `oauth_claim`  | A JSON pointer to the claim to read from the incoming provider profile. `/email` reads the email Google reports.                                            |
| `user_profile` | A JSON pointer to the attribute to match against existing users' identities. `/email` matches users whose email login ID or standard attribute is the same. |
| `action`       | What to do on a match: `error` or `login_and_link`.                                                                                                         |

{% hint style="info" %}
`oauth_claim` and `user_profile` accept only `/email`, `/phone_number`, and `/preferred_username`. Matching by email covers Google and most social providers; `/preferred_username` is useful for enterprise providers such as ADFS that identify users by username.
{% endhint %}

### What the user experiences

With the config above in place, here is the full flow for a user who already has a password account under `alice@example.com`:

1. On the signup page, the user clicks **Continue with Google** and completes Google's consent screen.
2. Authgear finds the existing account and shows an **Existing account found** page listing it with a masked identifier, such as `al***@example.com`.
3. The user selects the account and logs in with their existing method, in this case their password.
4. Authgear links the Google identity to the account. If your signup flow requires steps the account doesn't satisfy yet (for example, setting up two-factor authentication), the user completes them now; steps the account already satisfies are skipped.
5. The user is signed in. From now on, both the password and Google sign the user in to the same account.

## Linking email, phone, or username signups

Account linking also covers the reverse direction: a user who signed up with Google first, then tries to sign up with the same email address and a password. Configure it under `account_linking.login_id`:

```yaml
account_linking:
  login_id:
    - key: email
      user_profile:
        pointer: "/email"
      action: login_and_link
```

`key` names the login ID type (`email`, `phone`, or `username` by default). When a signup with that login ID matches an existing user, the user logs in to the existing account (in this case, through Google) and the new email login ID is added to it. Without this config, the conflicting signup fails with an error, as before.

## Advanced: different rules per signup flow

If you define [custom authentication flows](/authentication-and-access/authentication/custom-authentication-flow.md), you can override a linking rule inside a specific signup flow step. Give the rule a `name` in `account_linking`, then reference that name in the step to override its `action` or pick which login flow handles the login:

```yaml
account_linking:
  oauth:
    - name: google_linking
      alias: google
      oauth_claim:
        pointer: "/email"
      user_profile:
        pointer: "/email"
      action: error
authentication_flow:
  signup_flows:
    - name: customer_signup
      steps:
        - name: identify
          type: identify
          one_of:
            - identification: oauth
              account_linking:
                oauth:
                  - name: google_linking
                    action: login_and_link
                    login_flow: customer_login
```

Here Google linking fails with an error everywhere except the `customer_signup` flow, which allows it and runs the `customer_login` flow for the login step. When `login_flow` is not set, Authgear uses the login flow with the same name as the current signup flow.

## Account linking in Custom UI

If you build your own signup UI with the [Authentication Flow API](/customization/custom-ui/authentication-flow-api.md), account linking appears as an `identify` action whose `data.type` is `account_linking_identification_data`. The data contains the list of matched accounts with masked display names; your UI submits the index of the account the user picks, and the flow continues into the login steps. See the [Authentication Flow API reference](https://github.com/authgear/authgear-server/blob/main/docs/specs/authentication-flow-api-reference.md) for the exact schema.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.authgear.com/authentication-and-access/social-enterprise-login-providers/account-linking.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
