Skip to main content

Claims from other services

The id service keeps who someone is.

Other services keep the rest, and can hand it to each other through the id service — with the person's say-so, and without the id service keeping a copy.

Owning a scope

A service names the scopes it supplies, and the claims in each:

FG_ID_SERVICE_MEMBERS_URL=https://members.example.com
FG_ID_SERVICE_MEMBERS_CLAIMS=membership            # scope:claim,claim — here, both "membership"

membership is now a scope any service can ask for. Nobody else may supply it, and nobody may supply a scope or claim the id service answers for itself.

A claims review

When someone is deciding whether to share membership with, say, events, and again whenever it is released to events, the id service POSTs a ClaimsReview to members at /api/v1alpha1/claimsreviews, much as Kubernetes sends an admission review:

{
  "apiVersion": "id.fairgarden.org/v1alpha1",
  "kind": "ClaimsReview",
  "request": {
    "uid": "4f0c…",
    "purpose": "Preview",
    "subject": "d4618cea-…",
    "client": { "id": "events", "name": "Events" },
    "scopes": ["membership"],
    "claims": ["membership"]
  }
}

and passes on what it answers:

{
  "apiVersion": "id.fairgarden.org/v1alpha1",
  "kind": "ClaimsReview",
  "response": {
    "uid": "4f0c…",
    "claims": { "membership": { "status": "active", "roles": [] } },
    "reasons": { "membership.roles": "Roles are only shared with Events." }
  }
}

purpose is Preview while the person decides — the answer is shown to them on the consent screen, reasons included — and Release when the claims go to the service. Only the claims the scope carries are passed on, whatever else comes back.

Trusting the request

Each review carries Authorization: Bearer <JWT>, signed with the id service's current token key. The service checks it against the id service's JWKS (from its discovery document), and that:

  • typ is fg-claims-review+jwt, so an ID token can never pass for one
  • iss is the id service, and aud its own client ID
  • jti is the request's uid, and sub its subject
  • it is at most a couple of minutes old

apps/members does exactly this, in lib/claims-reviews.ts.

When a service is down

Its claims are left out, and the sign-in carries on: a service being down should not stop people signing in to the others.