---
title: "Exchange a live platform session for an authorize continuation"
method: POST
path: "/oauth/session/continue"
tags: ["OAuth"]
---

# Exchange a live platform session for an authorize continuation

`POST /oauth/session/continue`

Rung 1 of the /authorize identity ladder: reuse the platform session.

The login page's script posts the pending authorize state (the ``ls``
carry-through token) with the SPA's bearer token in the Authorization
header — no cookies, no ambient credentials, so a cross-site form cannot
drive it (same CSRF posture as the consent POST and the inline approval
decision). The platform token is validated by the standard auth
dependency (users only), and the ``active`` / ``must_change_password``
fences are re-checked with a LIVE user-row read — not the token's baked
claims — matching rung 3's ``password_rotation_required`` posture, so an
admin-forced reset fences the exchange immediately even while pre-reset
SPA tokens are still in flight. The D7 client gate is re-checked, and on
success the response carries a relative ``/authorize`` resume URL bearing
a short-TTL, ``session``-purpose continuation blob that pins THIS
caller's ``user_id`` — the identity is fixed at exchange time, before the
consent page renders it with its "Not you?" escape.

Every failure after authentication is the same generic 400: an invalid
blob must not let the caller learn anything about the client or the flow.

## Request body

- OAuthSessionContinueRequest — Front-channel session-continue exchange posted from the login page. ``state`` is the signed ``login``-purpose carry-through token (``ls``) minted by rung 3 of ``flow.resolve_identity_gate`` for this exact authorize request — the exchange never accepts bare flow parameters, so a caller cannot probe arbitrary client ids through it. ``state`` is deliberately NOT marked x-sensitive, for the same reason as ``OAuthApprovalDecisionRequest.state``: the CLI's redaction backstop unions bare field names globally, and the blob is not a lasting bearer credential (HMAC-signed, purpose-discriminated, TTL'd; the endpoint additionally requires an authenticated platform user).
  - `state` string, required

## Response `200`

Successful Response

- OAuthSessionContinueResponse — The resume leg for a successful session-continue exchange. ``redirect_url`` is a same-origin, relative ``/authorize`` URL re-running the ORIGINAL authorize request plus the short-TTL ``session``-purpose continuation blob (``sc``) pinning the platform user at exchange time. Relative by design (mirrors the approval-pending page's resume URL): the page script navigates within its own origin, never to a caller-influenced absolute URL.
  - `redirect_url` string, required

## Other responses

- `400` — Malformed, tampered, expired, or otherwise unusable authorize state — one generic rejection, never a reason.
- `401` — Unauthorized
- `403` — Forbidden
- `404` — Local-account login is unavailable (`auth.local_login.enabled=false`, or an external IdP is configured — `auth.idp.enabled=true` — which always wins): the route answers the framework's plain route-not-found 404, so the gate state is unobservable.
- `422` — Unprocessable Entity
- `500` — Internal Server Error
- `503` — Service Unavailable

## Changes

- **2026-09-08** `1a82635b6357` — 1 info
  - endpoint added

[Change history](https://skmtc.dev/jentic/apis/jentic-control-plane-api/changes/oauth/session/continue/post.md)

---

[API](https://skmtc.dev/jentic/apis/jentic-control-plane-api.md) · [All operations](https://skmtc.dev/jentic/apis/jentic-control-plane-api/llms.txt) · [OpenAPI document](https://skmtc.dev/jentic/apis/jentic-control-plane-api/revisions/e4688b93dfc7?raw)
