跳转到内容

Rotate a refresh token and issue a new access token.

POST
/refresh
curl --request POST \
--url https://connect-api.sudomimus.com/refresh \
--header 'Content-Type: application/json' \
--data '{ "refreshToken": "example" }'

Issues a new access token AND a new refresh token, atomically invalidating the presented refresh token. The Connect service implements OAuth 2.1 BCP §4.14.2 strict refresh-token rotation: every successful /refresh rotates the refresh token, and any subsequent presentation of the parent token (the one just consumed) is treated as evidence of compromise.

On compromise, the entire refresh-token family that the replayed token belongs to is revoked in a single sweep and the caller must re-authenticate via the normal Connect inquiry flow (/establish/status-poll/redeem). The same outcome applies when a concurrent rotation race is lost — per BCP §4.14.2 a perfectly-timed retry is indistinguishable from an attacker racing the legitimate caller, so both paths count as compromise.

Media type application/json
object
refreshToken
required
string
Example generated
{
"refreshToken": "example"
}

New access token and rotated refresh token issued.

Media type application/json
object
claims
required

Per-claim view across the three shareable claims — why a claim is or is not present in the minted token (policy OFF, never asked, declined, or granted).

object
email
required

One shareable claim: what the application requests (requirement) joined with the user’s standing decision (state). UNKNOWN means the user was never asked; DENIED means the user explicitly declined.

object
requirement
required

The developer’s policy for the claim. SYNTHETIC guarantees the claim is present but permits a generated placeholder (a stand-in name, a proxy email) when the user has not shared real data — unlike REQUIRED it never blocks issuance or raises an errand.

string
Allowed values: OFF OPTIONAL REQUIRED SYNTHETIC
state
required
string
Allowed values: UNKNOWN GRANTED DENIED
firstName
required

One shareable claim: what the application requests (requirement) joined with the user’s standing decision (state). UNKNOWN means the user was never asked; DENIED means the user explicitly declined.

object
requirement
required

The developer’s policy for the claim. SYNTHETIC guarantees the claim is present but permits a generated placeholder (a stand-in name, a proxy email) when the user has not shared real data — unlike REQUIRED it never blocks issuance or raises an errand.

string
Allowed values: OFF OPTIONAL REQUIRED SYNTHETIC
state
required
string
Allowed values: UNKNOWN GRANTED DENIED
lastName
required

One shareable claim: what the application requests (requirement) joined with the user’s standing decision (state). UNKNOWN means the user was never asked; DENIED means the user explicitly declined.

object
requirement
required

The developer’s policy for the claim. SYNTHETIC guarantees the claim is present but permits a generated placeholder (a stand-in name, a proxy email) when the user has not shared real data — unlike REQUIRED it never blocks issuance or raises an errand.

string
Allowed values: OFF OPTIONAL REQUIRED SYNTHETIC
state
required
string
Allowed values: UNKNOWN GRANTED DENIED
accessToken
required

Short-lived access token (JWT). Decode its body to AccessTokenBody (see schema) — the application-visible user key is the subject (sector subject) claim.

string
refreshToken
required

Newly issued refresh token (JWT); body is RefreshTokenBody. The presented refresh token is invalidated atomically as part of the same call; re-presenting it is treated as compromise under OAuth 2.1 BCP §4.14.2 strict rotation.

string
Example
{
"claims": {
"email": {
"requirement": "OFF",
"state": "UNKNOWN"
},
"firstName": {
"requirement": "OFF",
"state": "UNKNOWN"
},
"lastName": {
"requirement": "OFF",
"state": "UNKNOWN"
}
}
}

Reason AccountNotFound — the account behind the refresh token could not be resolved.

Media type application/json

Error response body. The Connect service emits { "reason": "<SymbolDescription>" } for known failure modes. When the reason symbol’s description begins with PRIVATE, the body is empty (zero bytes) and only the HTTP status carries signal — both reason and the body itself are absent in that case.

object
reason

Stable machine-readable reason code.

string
Example generated
{
"reason": "example"
}

Refresh token rejected. The reason distinguishes:

  • RefreshTokenNotFound — token cannot be resolved (unknown jti, wrong signature, or otherwise invalid).
  • RefreshTokenSuspended — the refresh-token session is suspended.
  • RefreshTokenExpired — the token is past its exp.
  • RefreshTokenFamilyCompromised — the presented token had already been rotated; the whole family has now been revoked.
  • RefreshTokenRotationRaceLost — a concurrent rotation won the conditional write. Per OAuth 2.1 BCP §4.14.2 this is also treated as compromise and the family is revoked.
Media type application/json

Error response body. The Connect service emits { "reason": "<SymbolDescription>" } for known failure modes. When the reason symbol’s description begins with PRIVATE, the body is empty (zero bytes) and only the HTTP status carries signal — both reason and the body itself are absent in that case.

object
reason

Stable machine-readable reason code.

string
Example generated
{
"reason": "example"
}

The attempt was refused. The reason distinguishes:

  • AccountDisabled — the account behind the refresh token is disabled.
  • AccountDeleted — the account has been erased.
  • ClaimConsentRequired — a REQUIRED claim is no longer satisfied by a standing grant (e.g. the user revoked it); the grant must be re-established through an interactive browser login.
Media type application/json

Error response body. The Connect service emits { "reason": "<SymbolDescription>" } for known failure modes. When the reason symbol’s description begins with PRIVATE, the body is empty (zero bytes) and only the HTTP status carries signal — both reason and the body itself are absent in that case.

object
reason

Stable machine-readable reason code.

string
Example generated
{
"reason": "example"
}

Error response.

Media type application/json

Error response body. The Connect service emits { "reason": "<SymbolDescription>" } for known failure modes. When the reason symbol’s description begins with PRIVATE, the body is empty (zero bytes) and only the HTTP status carries signal — both reason and the body itself are absent in that case.

object
reason

Stable machine-readable reason code.

string
Example generated
{
"reason": "example"
}