Corpland ID

Tokens

What is inside the access token, how a backend verifies it, and what the refresh token is.

Access token

A JWT signed with HS256 using JWT_ACCESS_SECRET, the same secret and the same { name, email, _id } payload every Corpland backend already checks. Tokens from the redirect flow add a few claims.

ClaimExampleMeaning
_id6aca9bf9b50f1fec97df56c0The Corpland ID user id. Use it as your user key.
nameAma MensahDisplay name at the time of sign in.
emailama@acme.comVerified email.
sid3f1c...The session family. Every refresh in one sign in shares it.
cidcorpland-contentThe client that asked for the token.
audcorpland-contentSame as cid, as a standard audience.
vid6aca9bfeb50f1fec97df56d6The venture picked at sign in. Missing when none was picked.
isshttps://...The ID API base address.
iat, expIssued and expiry times. exp is 15 minutes after iat.

Verifying on your backend

Existing backends need no change: jwt.verify(token, JWT_ACCESS_SECRET) still works. To reject tokens minted for another Corpland app, check the audience too.

const jwt = require("jsonwebtoken");

const verifyCorplandToken = (token) =>
  jwt.verify(token, process.env.JWT_ACCESS_SECRET, {
    audience: "corpland-content",
    clockTolerance: 60,
  });

Allow 60 seconds of clock leeway. Never trust vid alone for access to venture data: confirm the membership with the internal API, which is cached and fast.

The move to RS256 with a public JWKS is planned. When it lands, only the verify call changes.

Refresh token

An opaque random string, not a JWT. Corpland ID stores only its hash. Keep it where only your app can read it, and send it only to POST /oauth/token and POST /oauth/revoke.

RuleValue
RotationEvery use returns a new refresh token
Grace for parallel tabs10 seconds after rotation
Reuse after the graceThe whole family is revoked, error token_reused
Idle lifetime30 days
Absolute lifetime90 days from the first sign in
Bound toOne client. Another client id gets invalid_grant.

People can end any app's sessions from Connected apps in their account portal. Your next refresh then fails with invalid_grant, and you send them to sign in again.

On this page