# `Sigra.OAuth.Callback`
[🔗](https://github.com/sztheory/sigra/blob/v1.20.0/lib/sigra/oauth/callback.ex#L1)

Processes OAuth callback data and routes to the appropriate account action.

After successful token exchange, this module determines the correct path:

1. **Existing identity** -- identity found by `(provider, provider_uid)`.
   Updates identity fields (D-31) and logs user in.
2. **Email match** -- no identity, but a user with the same email exists.
   Returns `{:link_confirmation_required, ...}` for the controller to
   redirect to login (D-01, D-02).
3. **New user** -- no identity and no email match. Registers user with
   `confirmed_at` set if provider email is trusted (D-42). Creates identity
   and session in a single transaction (Pitfall 6: race condition safety).
4. **No email** -- provider didn't return email. Error (D-08).
5. **UID/email conflict** -- provider_uid maps to identity A but email
   matches user B. Blocked with generic error (D-09).

Identity lookups are always by `(provider, provider_uid)`, never by
email alone (D-32).

# `process_callback`
*since 0.5.0* 

```elixir
@spec process_callback(map(), atom(), map(), map()) ::
  {:ok, atom(), map(), map()}
  | {:link_confirmation_required, map()}
  | {:error,
     %Sigra.Error.OAuthError{
       __exception__: true,
       error_code: term(),
       message: term(),
       provider: term()
     }}
```

Processes an OAuth callback and routes to the appropriate account action.

## Parameters

- `config` - Sigra config map with `:repo`, `:user_schema`, `:identity_schema`, `:oauth`, `:session`
- `provider` - Provider atom (e.g., `:google`)
- `user_info` - Normalized user info map from the strategy wrapper
- `token` - Token map from the provider

## Returns

- `{:ok, :registered, user, session}` - new user registered
- `{:ok, :logged_in, user, session}` - existing identity login
- `{:link_confirmation_required, %{provider: p, email: e, provider_uid: uid}}` - email match
- `{:error, %OAuthError{error_code: :no_email}}` - provider returned no email
- `{:error, %OAuthError{error_code: :email_mismatch}}` - UID/email cross-account conflict

---

*Consult [api-reference.md](api-reference.md) for complete listing*
