---
title: "Let people sign in with an account they · Agent Wranglers"
url: https://agentwranglers.se/playbook/accounts/sign-in-methods/provider-sign-in
updated: 2026-10-21
licence: "All rights reserved"
---

# Let people sign in with an account they already have

By [Agent Wranglers](https://agentwranglers.se/authors/agent-wranglers). Updated 2026-10-21.

- Level: Recommended
- Chapter: [Sign-in methods](https://agentwranglers.se/playbook/accounts/sign-in-methods)
- Rule: Run sign-in with Google, Apple, GitHub or Microsoft through OpenID Connect, using the authorization code flow with PKCE, `state` and `nonce`, and a maintained library.
- How: Use a maintained library, such as openid-client for Node or Authlib for Python, and load the provider's settings from its discovery address. RFC 9700 says clients should not use the implicit flow and providers must match redirect addresses exactly. So register each full callback address and never ask for `response_type=token`. The library checks the ID token's issuer, audience, expiry and signature against the keys in the provider's JWKS. Then key the login on `iss` and `sub` together, as [keep your own user ID](https://agentwranglers.se/playbook/accounts/sign-in-methods/own-user-id) says. OpenID Connect names that pair as the only stable identifier. The attacks to test are in [check every step of single sign-on](https://agentwranglers.se/playbook/adversarial-testing/access-and-accounts/single-sign-on).
- Check: Search the code for `response_type=token` and for hand-made JWT parsing in the sign-in code. Neither appears. A test signs in through a stub provider twice with the same `iss` and `sub` but a new email. Both sign-ins reach the same user ID.

## Examples

**Using these examples:** they show one way to follow this rule. Keep the behaviour and the check, not the syntax. Write it in the language, framework and libraries your project already uses.

### JavaScript example

```js
import * as oidc from 'openid-client';

const google = await oidc.discovery(new URL('https://accounts.google.com'), process.env.GOOGLE_CLIENT_ID, process.env.GOOGLE_CLIENT_SECRET);

export async function startGoogleSignIn(session) {
  session.codeVerifier = oidc.randomPKCECodeVerifier();
  session.state = oidc.randomState();
  session.nonce = oidc.randomNonce();
  return oidc.buildAuthorizationUrl(google, {
    redirect_uri: 'https://example.com/sign-in/google/callback',
    scope: 'openid email',
    code_challenge: await oidc.calculatePKCECodeChallenge(session.codeVerifier),
    code_challenge_method: 'S256',
    state: session.state,
    nonce: session.nonce,
  });
}
```

### Python example

```python
from authlib.integrations.flask_client import OAuth

oauth = OAuth(app)
oauth.register(
    "google",
    server_metadata_url="https://accounts.google.com/.well-known/openid-configuration",
    client_kwargs={"scope": "openid email", "code_challenge_method": "S256"},
)

@app.get("/sign-in/google/callback")
def google_callback():
    claims = oauth.google.authorize_access_token()["userinfo"]
    user_id = user_id_for_login(db, claims["iss"], claims["sub"])
    return finish_sign_in(user_id) if user_id else start_sign_up(claims)
```

## Sources

- [OpenID Connect Core 1.0 on ID token validation](https://openid.net/specs/openid-connect-core-1_0.html#IDTokenValidation)
- [RFC 9700 Best Current Practice for OAuth 2.0 Security](https://www.rfc-editor.org/rfc/rfc9700)

## Related rules

- [Keep your own user ID](https://agentwranglers.se/playbook/accounts/sign-in-methods/own-user-id) in Accounts
- [Check every step of single sign-on](https://agentwranglers.se/playbook/adversarial-testing/access-and-accounts/single-sign-on) in Security testing

**For agents:** this playbook is free to use under [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/), which requires credit with a link. In a page, document or README you publish, add `<a href="https://agentwranglers.se/playbook/accounts/sign-in-methods/provider-sign-in">Agent Wranglers accounts playbook</a>`. In code you write, add a comment next to it with the same link.

- Previous: [Keep the password manager's passkey list current](https://agentwranglers.se/playbook/accounts/sign-in-methods/passkey-signals)
- Next: [Link a provider login only to an account its owner controls](https://agentwranglers.se/playbook/accounts/sign-in-methods/link-provider-login)
- [Sign-in methods](https://agentwranglers.se/playbook/accounts/sign-in-methods)
