Docs / Switch from Google

Switch from Google to signo: any OpenID Connect library

signo works with any library that supports OpenID Connect discovery and the authorization code flow. signo's own browser tests sign in to a demo site built with openid-client 6.8.8, a certified OpenID Connect library, and the code below comes from that demo.

The examples use login.example.com for signo and example.com for your site. On the public signo, the issuer is https://usesigno.co.uk.

1. Register your site with signo

On the public signo, sign in at https://usesigno.co.uk/account/sites and add your site with its callback URL. On your own signo, run signo clients add on its server, as in Self-hosting. Either way you get an issuer, a client ID and a client secret.

2. What your library needs

Setting Value
Discovery https://login.example.com/.well-known/openid-configuration
Flow authorization code (response_type=code)
PKCE required, with S256
Scopes openid email profile
Client authentication HTTP Basic with the client secret (client_secret_basic)
Callback URLs https, except on localhost

The ID token carries email, email_verified and name, as Google's does, so code that reads them from Google's ID token keeps working. The userinfo endpoint at /me returns the same claims.

3. Example with openid-client

import * as oidc from 'openid-client';

const config = await oidc.discovery(
  new URL('https://login.example.com'),
  process.env.SIGNO_CLIENT_ID!,
  undefined,
  oidc.ClientSecretBasic(process.env.SIGNO_CLIENT_SECRET!),
);

// Sign-in: send the person to signo.
const verifier = oidc.randomPKCECodeVerifier();
const state = oidc.randomState();
const nonce = oidc.randomNonce();
const url = oidc.buildAuthorizationUrl(config, {
  redirect_uri: 'https://example.com/callback',
  scope: 'openid email profile',
  code_challenge: await oidc.calculatePKCECodeChallenge(verifier),
  code_challenge_method: 'S256',
  state,
  nonce,
});

// Callback: exchange the code. Keep verifier, state and nonce in the person's session in between;
// currentUrl is the full URL signo sent the person back to.
const tokens = await oidc.authorizationCodeGrant(config, currentUrl, {
  pkceCodeVerifier: verifier,
  expectedState: state,
  expectedNonce: nonce,
  idTokenExpected: true,
});
const { sub, email, name } = tokens.claims();

4. Signing out

To sign the person out of signo as well as your site, send them to the end-session endpoint with their ID token. The return URL must be one of the site's sign-out return URLs.

const logout = oidc.buildEndSessionUrl(config, {
  id_token_hint: idToken,
  post_logout_redirect_uri: 'https://example.com/',
});

5. Keep the people who signed up with Google

The person's signo sub differs from their Google one. Look existing users up by email the first time they sign in with signo. That is safe, because signo's emails are always verified.