MyAddress IDid.myaddress.cc

MyAddress ID · implementation guide

Implement MyAddress ID sign-in

MyAddress ID is a standard OpenID Connect provider for server applications. This guide gives a minimal pattern using openid-client; another standards-compliant server library is equally suitable.

1. Register the application

Sign in and register an application. Supply a public homepage and each callback URI, one per line. Keep one callback host per registration. HTTPS is required in production; HTTP is accepted only for localhost, 127.0.0.1, or [::1] during local development.

Registration returns a client ID and shows the client secret once. MyAddress ID supports server applications: keep both values in server-side configuration in every environment. The localhost callback exception does not change that requirement. Rotating the secret immediately invalidates the previous value.

2. Use the standard authorization-code pattern

Configure from OpenID Connect discovery. Requests use openid email; both scopes are required and additional scopes are rejected. The following pattern keeps the provider-specific configuration and the complete browser flow together.

import * as oidc from 'openid-client';

const issuer = 'https://id.myaddress.cc';
const clientId = process.env.MYADDRESS_OIDC_CLIENT_ID!;
const clientSecret = process.env.MYADDRESS_OIDC_CLIENT_SECRET!;

const config = await oidc.discovery(
  new URL(issuer),
  clientId,
  {
    client_secret: clientSecret,
    token_endpoint_auth_method: 'client_secret_basic',
    id_token_signed_response_alg: 'ES256',
  },
  oidc.ClientSecretBasic(clientSecret),
);

type PendingSignIn = {
  state: string;
  nonce: string;
  verifier: string;
};

export async function startSignIn(redirectUri: string) {
  const state = oidc.randomState();
  const nonce = oidc.randomNonce();
  const verifier = oidc.randomPKCECodeVerifier();
  const challenge = await oidc.calculatePKCECodeChallenge(verifier);

  // Save before redirecting; use once at the callback.
  const pending: PendingSignIn = { state, nonce, verifier };
  const redirectTo = oidc.buildAuthorizationUrl(config, {
    response_type: 'code',
    redirect_uri: redirectUri,
    scope: 'openid email',
    state,
    nonce,
    code_challenge: challenge,
    code_challenge_method: 'S256',
  });
  return { redirectTo, pending };
}

export async function finishSignIn(callbackUrl: URL, pending: PendingSignIn) {
  // This one call exchanges the code and validates the ID token.
  const tokens = await oidc.authorizationCodeGrant(config, callbackUrl, {
    expectedState: pending.state,
    expectedNonce: pending.nonce,
    pkceCodeVerifier: pending.verifier,
  });
  const claims = tokens.claims();
  // MyAddress claims: { sub: string, email: string, email_verified: true }.
  return claims;
}

Store pending before redirecting, then pass the complete callback URL—its query parameters included—to finishSignIn; do not reconstruct it, because that discards code, state, and MyAddress's iss parameter. If MyAddress returns an error, the state does not match, or validation fails, do not create an application session.

3. Create the local session

finishSignIn returns the verified ID-token data your application needs. Read claims.sub and claims.email, find or create the local account using issuer + claims.sub, then create your own application session. Do not use the short-lived ID token as a browser session.

subject
The pairwise MyAddress identifier for this application connection.
email
The generated MyAddress address for this connection, never the private sign-in address.
email_verified
true confirms that MyAddress has verified the generated address. You may treat it as a verified contact address for this connection; it says nothing about the undisclosed private sign-in address.

Connection and session lifecycle

The person explicitly approves the connection. They can later disable or remove it, after which it cannot complete a new authorization or receive new mail. MyAddress ID does not send back-channel logout requests, so choose an application session duration and reauthentication policy that suits your product.

This profile supports server-side Authorization Code Flow only. It does not issue refresh tokens or support browser-only, native, device, or machine-to-machine clients.

Send messages

See the separate message API guide to send from one of your MyAddress mailboxes to active application connections.

Discovery provides the current endpoints and public signing keys: https://id.myaddress.cc/.well-known/openid-configuration.