Who Signed In, in Your Code
On every request, the platform hands the application the identity of who signed in, signed. The SDK checks it and returns the person; in another language, the check is the same and is described below.
TypeScript and Node
npm install @nnumbers/zero
import { NNumbers, UnauthenticatedError } from '@nnumbers/zero/app'
const nn = NNumbers.init() // reads the NNUMBERS_* variables
app.get('/api/me', async (req, res) => {
res.json({ user: await nn.auth.user(req) }) // the person, or null
})
app.get('/dashboard', async (req, res) => {
try {
const user = await nn.auth.requireUser(req, req.url)
res.send(`Hello, ${user.name ?? user.username}`)
} catch (e) {
if (e instanceof UnauthenticatedError) return res.redirect(e.loginPath)
throw e
}
})
| API | What it does |
|---|---|
NNumbers.init() | the application context: appId, org and auth |
nn.auth.user(req) | who signed in, or null |
nn.auth.requireUser(req, returnTo) | like user, but without a person it throws UnauthenticatedError with the loginPath that returns to returnTo |
nn.auth.loginPath(returnTo) | the sign-in path; a destination outside the application becomes / |
nn.auth.logoutPath | the sign-out path (POST) |
| Error | Code | When |
|---|---|---|
AppConfigurationError | ORGANIZATION_IAM_NOT_ENABLED | the application runs without the capability on, or outside Zero |
UnauthenticatedError | USER_SESSION_REQUIRED | the route requires someone and no one signed in |
IdentityAssertionError | IDENTITY_ASSERTION_INVALID | an identity arrived that does not check out — it never becomes a person |
user accepts the Node request, a fetch Request or a headers object. There is a complete example, without a framework, in examples/organization-iam in the SDK repository.
In Another Language
The identity arrives in the X-NNumbers-Identity header: a compact JWS, algorithm ES256, typ nn-identity+jwt. Check it always, on every request — a header whose signature was not checked proves nothing:
- The signature, with the public keys at the address in
NNUMBERS_IDENTITY_JWKS. Keep the keys for a few minutes and fetch them again when an unknownkidarrives. issequal toNNUMBERS_IDENTITY_ISSUER.audequal toNNUMBERS_APP_ID— an identity handed to another application is not valid here.orgequal toNNUMBERS_ORG_ID.expandnbf: the identity is valid for 5 minutes.
Without the header, the request is anonymous. With the header and any check failing, refuse it — never treat it as a person.
| Claim | What it is |
|---|---|
sub | the person's identifier in the organization's IAM |
org, org_slug | the organization |
iam | the address of the organization's IAM |
sid | the session reference |
name, email, email_verified, preferred_username | when the account has them |
iat, nbf, exp, jti | the validity and the identifier of this identity |
The Platform Variables
With the capability on, the deployment injects:
| Variable | What it is |
|---|---|
NNUMBERS_APP_ID | this application's id (svc_…) |
NNUMBERS_ORG_ID, NNUMBERS_ORG_SLUG | the project's organization |
NNUMBERS_IDENTITY_ISSUER | the identity issuer |
NNUMBERS_IDENTITY_JWKS | the address of the public keys — reachable only from inside the platform |
NNUMBERS_BROKER_URL | where the application asks for the person's credential for QueryMesh — reachable only from inside the platform |
The NNUMBERS_ prefix belongs to the platform: the service configuration does not accept a variable with it.
Next Steps
Was this page helpful?
Report a problem on this pageDo not send passwords, keys, tokens, or customer data.