Sign in with Bynli

OAuth 2.0 / OpenID Connect

Add a "Sign in with Bynli" button to your site or app. Bynli is a standards-compliant OAuth 2.0 / OpenID Connect provider — the same flow you use for Google, Apple, or Microsoft.

Issuer

All flows start at id.bynli.com — the dedicated auth domain. Bookmark the discovery document if your client supports auto-configuration:

OpenID configurationJSON
GET https://id.bynli.com/.well-known/openid-configuration

It advertises the canonical endpoints:

EndpointURL
Authorizationhttps://id.bynli.com/oauth/authorize
Tokenhttps://id.bynli.com/oauth/token
UserInfohttps://id.bynli.com/oauth/userinfo
JWKShttps://id.bynli.com/oauth/jwks.json

Tokens are signed RS256. Always validate iss equals https://id.bynli.com and aud equals your client_id before trusting the claims.

Register a client

Team admins register OAuth clients at /dash/sites/oauth. Each client is scoped to one team and gets a unique client_id.

Site-registered clients are public clients:

The flow (PKCE)

  1. Generate a high-entropy code_verifier (43–128 chars). Compute code_challenge = BASE64URL(SHA256(code_verifier)).
  2. Redirect the user to:
    Step 1 — AuthorizeGET
    https://id.bynli.com/oauth/authorize
      ?client_id=site_xxxxxxxxxxxx
      &redirect_uri=https://yoursite.com/auth/callback
      &response_type=code
      &scope=openid+profile+email
      &state=<random>
      &code_challenge=<S256-of-verifier>
      &code_challenge_method=S256
  3. The user signs in (if needed) and approves the scopes. Bynli redirects back to your redirect_uri with ?code=…&state=…. Verify state matches what you sent.
  4. Exchange the code for tokens:
    Step 2 — Token exchangePOST
    POST https://id.bynli.com/oauth/token
    Content-Type: application/x-www-form-urlencoded
    
    grant_type=authorization_code
    &code=<code>
    &redirect_uri=<same redirect_uri>
    &client_id=site_xxxxxxxxxxxx
    &code_verifier=<the verifier>
    Response (JSON): access_token, refresh_token, id_token (JWT), expires_in, token_type=Bearer, scope.
  5. Verify the id_token: signature against /oauth/jwks.json, iss == https://id.bynli.com, aud == your client_id, expiry.
  6. Call GET /oauth/userinfo with Authorization: Bearer <access_token> for profile claims (or just trust the id_token claims for openid + profile + email).

Silent sign-in

For returning users already signed into Bynli, pass prompt=none on the authorize call. The server either redirects back with a code immediately (no UI shown) or returns one of these errors so your client can fall back to manual sign-in:

ErrorMeaning
login_requiredUser has no active Bynli session — show the manual button.
consent_requiredUser is signed in but hasn't yet approved your scopes — start the normal flow.

Scopes

ScopeGrants
openidRequired. Identifies this as an OIDC request and authorizes an id_token.
profileName, username, profile picture.
emailEmail address + verification status.
phonePhone number + verification status. Available to first-party clients only at this time.

Additional scopes (teams:read, wallet:read, tasks:read, purchases:read, feeds:read) exist for first-party Bynli apps and aren't open to site-registered clients yet. Reach out if your use case needs one.

Subject identifier (sub)

The sub claim is a stable, opaque, per-issuer user identifier. Treat it as your primary key when storing per-user data on your side — never key on email (which can change) or display name. Two different Bynli users will never share a sub; the same user signing into two different clients gets the same sub.

Errors

Returned as standard OAuth error params on the redirect_uri or as JSON from the token endpoint:

Error codeWhen
invalid_requestMissing required parameter, bad redirect_uri, or missing PKCE.
invalid_clientclient_id is unknown, inactive, or doesn't match the redirect_uri.
invalid_grantcode expired (10-minute TTL), already used, or code_verifier doesn't match the original challenge.
invalid_scopeRequested a scope not allowed for this client.
access_deniedUser clicked Deny on the consent screen.
login_required / consent_requiredSilent (prompt=none) flow couldn't complete without UI.

Revocation

Users can revoke your client's access at /dash/me/apps. When revoked, the consent record is deleted and every outstanding access + refresh token is marked revoked. Your next call to /oauth/token with a refresh token will return invalid_grant; access tokens stop working immediately.

The browser kit (for static sites)

If your site is hosted by Bynli (*.site.bynefit.com or a verified custom domain), the auth module of the Bynli kit wraps the entire flow into one config block plus a couple of HTML attributes — no PKCE plumbing required. See the site-config guide.

CORS

/oauth/token, /oauth/userinfo, and /oauth/jwks.json respond with Access-Control-Allow-Origin: * so browser-based clients on any origin can call them. Credentials are never echoed — the flow's security comes from PKCE plus the redirect-URI allowlist on your client.