Skip to content

feat(auth): list the identities linked to the signed-in user - #606

Merged
Tr00d merged 1 commit into
masterfrom
feat/auth.identities.list_identities
Oct 29, 2026
Merged

Tr00d merged 1 commit into
masterfrom
feat/auth.identities.list_identities

Conversation

@Tr00d

@Tr00d Tr00d commented Oct 29, 2026

Copy link
Copy Markdown
Contributor

Summary

Callers can list the external identities linked to the signed-in user with a dedicated method. The data comes from the server, so identities linked or unlinked since sign-in show up, which the cached User.Identities cannot guarantee.

Capability: auth.identities.list_identities — List Identities. (No capability spec; contract from the GoTrue OpenAPI GET /user.)

Public API

// IGotrueClient<TUser, TSession>, next to UnlinkIdentity
Task<IReadOnlyList<UserIdentity>> GetUserIdentitiesAsync(CancellationToken cancellationToken = default);

New types: none (reuses UserIdentity).

var identities = await client.GetUserIdentitiesAsync();
var github = identities.FirstOrDefault(identity => identity.Provider == "github");
if (github != null)
{
    await client.UnlinkIdentity(github);
}

Behavior

  • Operation: GET /user with Authorization: Bearer <current session access token> and the client's apikey.
  • Inputs: none. Before the request: offline → GotrueException (Reason = Offline); no session or no access token → GotrueException (Reason = NoSessionFound), with no request sent.
  • Outputs: the identities array of the returned user, in server order. A null identities field or a null user body → empty list (never null).
  • Failures: any server rejection surfaces as GotrueException through the existing error mapping (e.g. an expired token → 403 error_code = bad_jwt).
  • State: none. No session/user update, no auth-state event.
  • Cancellation: the token reaches the HTTP call. Instrumentation: new gotrue.get_user_identities domain span parents the HTTP span.

Deviations from supabase-js

  • supabase-js returns { data: { identities }, error }. This returns the list and throws the typed GotrueException (v8 error model).
  • supabase-js goes through getUser() → getSession(), which refreshes an expired session first. This uses the current access token as is, consistent with LinkIdentity/UnlinkIdentity, and leaves refreshing to the background auto-refresh.

Tests

Tier Class Pins
E2E Identities/UserIdentitiesTests an email/password sign-up lists its single email identity for that user
Contract Identities/UserIdentitiesContractTests GET /user with bearer + apikey; identities mapped in order from the server (not the cached user); null identities / null body → empty; bad_jwt rejection; NoSessionFound (no session, no access token, nothing sent); Offline; cancellation; no deadlock on a blocking synchronization context
Contract Observability/ObservabilityContractTests the domain span parents the GET /user HTTP span

Changed-line coverage: 100% (33 lines). Mutation: 6/6 tested mutants on changed lines detected (5 killed, 1 timeout on ConfigureAwait(true)), 0 survivors.

Notes

  • [PartialCapability] removed from User.Identities; [ImplementedCapability] now sits on Client.GetUserIdentitiesAsync.
  • GotrueInstrumentation.cs changed from tabs to spaces because touching it pulls it into the changed-file format check; git diff -w shows only the one added span constant.
  • Adding a member to IGotrueClient<TUser, TSession> breaks only third-party implementers of the interface, so it gets no migration-guide entry.
  • bad_jwt still maps to FailureHint.Reason.AdminTokenRequired (existing mapping, unchanged here), which reads oddly for a user token. A possible follow-up.

@Tr00d
Tr00d marked this pull request as ready for review October 29, 2026 16:13
@Tr00d
Tr00d merged commit eba25d5 into master Oct 29, 2026
3 of 5 checks passed
@Tr00d
Tr00d deleted the feat/auth.identities.list_identities branch October 29, 2026 16:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant