Gallimore Auth

API docs

Base URL https://auth.gallimoresoftware.com. Everything below is standard OpenID Connect with PKCE - any compliant client library works. Responses are JSON unless noted.

How sign-in works

Gallimore Auth is a public OIDC client setup: no client secrets, PKCE (S256) is required on every flow.

  • Your app redirects the user to GET /authorize with its client_id, an exact-match redirect_uri, and a PKCE code_challenge.
  • We validate the request and redirect to Microsoft Entra for sign-in.
  • Entra returns to us; we check the tenant, the app allowlist, and the required roles, then redirect back to your redirect_uri with a single-use authorization code (60 second lifetime).
  • Your backend exchanges the code at POST /token with the PKCE code_verifier and receives an ID token plus an access token (both expire in 15 minutes).
  • Call GET /userinfo with the access token to fetch the signed-in profile.

Discovery document

GETGET /.well-known/openid-configuration

Standard OpenID Provider Metadata. Point any OIDC client library at this URL and it configures itself.

Example response

{
  "issuer": "https://auth.gallimoresoftware.com",
  "authorization_endpoint": "https://auth.gallimoresoftware.com/authorize",
  "token_endpoint": "https://auth.gallimoresoftware.com/token",
  "userinfo_endpoint": "https://auth.gallimoresoftware.com/userinfo",
  "jwks_uri": "https://auth.gallimoresoftware.com/jwks.json",
  "end_session_endpoint": "https://auth.gallimoresoftware.com/logout",
  "revocation_endpoint": "https://auth.gallimoresoftware.com/revoke",
  "response_types_supported": ["code"],
  "code_challenge_methods_supported": ["S256"],
  "token_endpoint_auth_methods_supported": ["none"],
  "identity_providers_supported": ["microsoft"]
}

JSON Web Key Set

GETGET /jwks.json

The RS256 public signing key. Use it to verify ID token and access token signatures locally.

Example response

{
  "keys": [
    { "kty": "RSA", "use": "sig", "alg": "RS256", "kid": "…", "n": "…", "e": "AQAB" }
  ]
}
  • The private half is never published. Keys are rotated by the service; always match on kid.

Start sign-in

GETGET /authorize

Validates the request, then redirects (303) to Microsoft Entra. On validation failure the user is sent back to your redirect_uri with OAuth error parameters instead.

ParameterInRequiredDescription
client_id query yes Your registered application id.
redirect_uri query yes Must exactly match a URI registered for the client. No wildcards, no prefixes.
response_type query yes Must be code.
scope query yes Space-separated scopes. Must include openid. profile and email are also supported.
state query yes Opaque value returned to you unchanged. Use it for CSRF protection.
nonce query no Returned inside the ID token so you can bind it to the session.
code_challenge query yes PKCE challenge: base64url(sha256(code_verifier)).
code_challenge_method query yes Must be S256.

Example request

GET /authorize?client_id=your-app&redirect_uri=https%3A%2F%2Fapp.example.com%2Fauth%2Fcallback&response_type=code&scope=openid%20profile%20email&state=xyz&code_challenge=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM&code_challenge_method=S256
  • Unknown client_id or a non-matching redirect_uri returns an error page (400) instead of redirecting anywhere.
  • Other validation errors redirect to your redirect_uri with error=invalid_request and an error_description.
  • Success is a 303 redirect to login.microsoftonline.com. The upstream state is ours; your state comes back with the code.

Microsoft return

GETGET /callback/microsoft

Where Microsoft Entra sends the browser after sign-in. You never call it yourself - it finishes what /authorize started.

  • We exchange the Entra code, validate the ID token, then enforce the tenant boundary, the app email allowlist, and the required Entra roles.
  • A failed or expired sign-in (attempts expire after 10 minutes) returns an error page here instead of your redirect URI.
  • On success we redirect to your redirect_uri with code and state, exactly as documented under Start sign-in.

Exchange the code

POSTPOST /token

Redeems a single-use authorization code for tokens. Accepts application/x-www-form-urlencoded or JSON. No client secret: authentication is the PKCE verifier.

ParameterInRequiredDescription
grant_type body yes Must be authorization_code.
code body yes The code from the authorize redirect. Single use, expires after 60 seconds.
client_id body yes Must match the client the code was issued to.
redirect_uri body yes Must match the redirect_uri from the authorize request.
code_verifier body yes The original PKCE verifier, 43 to 128 characters.

Example request

POST /token
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code&code=SPLIT…&client_id=your-app&redirect_uri=https%3A%2F%2Fapp.example.com%2Fauth%2Fcallback&code_verifier=dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk

Example response

{
  "token_type": "Bearer",
  "expires_in": 900,
  "id_token": "eyJhbGciOi…",
  "access_token": "eyJhbGciOi…",
  "scope": "openid profile email"
}
  • The access token is a JWT too: verify its RS256 signature against /jwks.json and call /userinfo with it.
  • Reusing a code, or presenting it after the session was revoked, returns invalid_grant.

User profile

GETGET /userinfo

Returns the signed-in profile for a valid access token.

ParameterInRequiredDescription
Authorization header yes Bearer <access_token>.

Example request

GET /userinfo
Authorization: Bearer eyJhbGciOi…

Example response

{
  "sub": "a-stable-user-id",
  "email": "person@example.com",
  "email_verified": true,
  "name": "Person Name",
  "provider": "microsoft",
  "tenant_id": "…",
  "roles": ["app-role"],
  "session_id": "…"
}
  • Tokens are rejected (401 invalid_token) when the signature, issuer, expiry, or session check fails.

Revoke a session

POSTPOST /revoke

Ends a session immediately. Tokens already issued for it stop validating at /userinfo and /token.

ParameterInRequiredDescription
session_id body yes The session_id from the ID token or userinfo.

Example request

POST /revoke
Content-Type: application/json

{ "session_id": "…" }

Example response

{ "revoked": true }

Sign out

GETGET /logout

Ends the session and optionally returns the user to your app.

ParameterInRequiredDescription
session_id query no Revoked when present.
client_id query no Used to validate the post-logout redirect.
post_logout_redirect_uri query no Must exactly match a URI registered for the client, otherwise a signed-out page is shown.

Example request

GET /logout?session_id=…&client_id=your-app&post_logout_redirect_uri=https%3A%2F%2Fapp.example.com%2Fsigned-out

Service health

GETGET /health

Liveness and provider state. Contains no secrets.

Example response

{
  "ok": true,
  "issuer": "https://auth.gallimoresoftware.com",
  "clientCount": 9,
  "signingKeyId": "…",
  "providers": [
    { "id": "microsoft", "enabled": true },
    { "id": "google", "enabled": false }
  ]
}

Registering your app

There is no self-service registration endpoint. Apps are registered in server configuration.

  • Each client declares an id, an application class, one or more exact-match redirect URIs (https only), and optional post-logout redirect URIs.
  • Application classes set the authorization boundary: internal staff tools require the Gallimore tenant plus an Entra app role; other classes add their own tenant or allowlist rules.
  • A client may also declare an email allowlist and required Entra roles. Sign-in succeeds only when all of them pass.
  • To onboard an app, ask the platform team to register it with its redirect URIs.