1. Browser: selects configured Google or GitHub sign-in
  2. AnyOAuth: handles the provider-specific identity check
  3. Your backend: uses the same exchange and profile contract
The application contract stays consistent while the upstream identity mechanisms remain provider-specific.

Put two buttons beside the same callback route: “Continue with Google” and “Continue with GitHub.” Both can lead to the same backend exchange and user lookup. The database decision after that lookup is where the buttons stop being merely presentation. A Google account and a GitHub account are separate identities, even when a person uses both.

Before writing those buttons, check which providers are enabled. Current AnyOAuth support is Google and GitHub, and availability depends on configured service applications. A provider logo on a page is not an availability guarantee. Build the sign-in choices around the actual service configuration, not an assumed catalogue of every OAuth provider.

Standardize the application boundary, not the upstream protocol

One integration means one customer-facing contract, not identical provider responses. Google supplies OIDC identity evidence. AnyOAuth validates its signature, issuer, audience, lifetime, and transaction nonce. GitHub uses OAuth followed by fresh server-side profile and email lookup. GitHub’s own documentation recommends revalidating identity every time an access token is received.

Your backend doesn’t need to turn those two paths into two session implementations. It redirects through /authorize, redeems the returned AnyOAuth handoff code at /v1/token, and retrieves the normalized identity at /v1/profile. The OAuth versus OIDC reference explains the upstream distinction without suggesting that AnyOAuth itself is a general OIDC provider.

Integration concernShared by your appStill varies or stays separate
Customer credentialsProject client ID and backend secretIndependent apps can have separate projects
Callback protectionRegistered exact callback, state, S256 PKCEEach login has its own transaction
User lookupStable normalized subjectProject, provider, and provider subject define the identity
Display fieldsConsistent profile field namesNames, usernames, emails, and avatars may be null
Provider accessNo provider token handling in your appProvider-specific evidence stays inside the service

For a coding assistant, that table is a better constraint than “add social login.” It says which code should be shared and which facts must remain distinguishable. You can inspect a single callback handler while still preserving the provider field in your user-facing account information.

Equal email addresses must not collapse two users

Account matching belongs to the stable identity, not to an attractive-looking profile field. Google’s documentation explicitly warns against using email as the unique identifier. AnyOAuth extends the application’s boundary with project-scoped subjects, and it doesn’t automatically merge accounts by email.

  1. Google path: project A plus Google plus its provider subject resolves to one AnyOAuth subject. Its email is profile data.
  2. GitHub path: project A plus GitHub plus its provider subject resolves to another subject, even if the returned email matches.
  3. Application lookup: your backend finds users by stable subject. It must not silently attach the second identity to the first user through an email lookup.
Normalization changes the response shape, not account ownership. Matching email values do not establish a link between provider identities.

This means a person choosing a different provider can arrive as a different app user. Explain that consequence in account and recovery UI. AnyOAuth currently has no account-linking feature. If your product needs linking, specify proof of control and recovery behavior before adding an email-based shortcut; don’t let a generated database upsert invent that policy.

The one-profile note covers nullable fields, while project credentials explains why sharing an integration pattern doesn’t require sharing every app’s secret.

Provider consent branding is part of the login experience. Users see AnyOAuth’s provider application identity, not a separate provider registration created under your app’s name. Tell users what the service does where that explanation is useful. If your requirement is your own upstream consent identity, evaluate direct provider integration rather than assuming callback configuration changes branding.

Keep access requests equally clear. This is identity-only sign-in, not a request to import repositories or calendars. The opaque profile token lasts 15 minutes, has no refresh flow, and cannot call provider APIs. Your app creates and manages its own session after retrieving the profile.

AnyOAuth implementation choice

AnyOAuth, which we build, fits apps that want those two configured providers behind one profile handoff. Create a project, retain its client ID and backend secret, and register an exact callback. Redemption still requires the original verifier and client authentication; the two-minute handoff code is single-use.

The DIY alternative is separate Google and GitHub registrations with a maintained library handling their different validation paths. Choose that when provider-specific scopes or branding are part of the product. For a full session and account-management platform, evaluate a broader auth system such as Auth0 or Clerk against your requirements. AnyOAuth’s narrower contract doesn’t supply those features, OIDC discovery, or SAML federation.

Check both paths, including missing fields

Review Google and GitHub independently: an enabled button, a completed callback, a stable subject, and a usable screen when display fields are absent. Also review a denial and a second provider with the same email. Neither should bypass transaction checks or your account policy.

Then follow the redirect, exchange, profile trace to connect the shared integration to the app session. Privacy duties remain yours; a uniform profile format doesn’t establish automatic compliance.

Sources

Read or retrieved 2026-10-06: