Skip to main content
Linking reuses the same redirect/callback machinery as Authentication — but it uses a separate set of endpoints from sign-in. Do not use authStart() to link.
This page is about linking multiple auth providers to one AGG account. If you need to link an AGG user to your own partner-side user ID, use Partner External ID Linking.
A user who is already signed in (e.g. with a wallet) can attach more providers — Google, Twitter, Apple, or email — to the same account. Because the caller is already authenticated, linking is a distinct flow from sign-in: it runs against POST /users/me/link-account/* and finishes with a short-lived confirm token, so the new provider is bound to the current principal.

The flow

Use linkAccount(), not authStart(). authStart() starts a fresh sign-in and cannot attach a provider to the signed-in principal — pointing it at an authenticated session produces a competing redirect, not a link.
After the provider callback, the browser lands back on your redirectUrl with a link_confirm_token query param. Exchange it for the linked account:

React: this is handled for you

If your app is wrapped in <AggAuthProvider> from @agg-build/auth, the confirm step runs automatically. On mount it reads link_confirm_token from the URL, calls linkAccountConfirm(), refreshes the user, and strips the token from the address bar — the same handler that finishes sign-in callbacks.
The page your redirectUrl lands on must have <AggAuthProvider> mounted (or call useAggAuthCallback() on a dedicated callback route). This is the same requirement as sign-in OAuth — if the auth provider isn’t mounted where the redirect returns, nothing consumes link_confirm_token and the link silently never completes.

Email linking

Email uses a magic link instead of an OAuth redirect. The result of linkAccount is a magic_link acknowledgement, not a redirect — tell the user to check their inbox:
When the user clicks the emailed link, AGG redirects them to your redirectUrl with a link_confirm_token, and the same confirm step above completes the link. The confirm call is bound to the signed-in bearer, so the link must be opened in the browser where the user is still authenticated.

Collisions

linkAccountConfirm() resolves to { status: "linked" } on first link and { status: "already_linked_same" } if that identity was already attached to the same user (idempotent — safe to retry). If the provider identity already belongs to a different AGG user, the confirm call rejects with HTTP 409 — catch it and tell the user the account is already in use elsewhere.

Auto-linking by email

If a user signs in with a provider that carries a verified email (e.g. Google) and another account already exists with that email, the accounts are linked automatically during sign-in — no explicit link step needed.

Viewing linked accounts

Wallet-to-wallet linking (SIWE/SIWS) is not supported yet — the signature protocol needs a principal-binding step before it can be done safely. Only Google, Twitter, Apple, and email can be linked today.