RoadOpsDeveloper

Authorization Code with PKCE

Start authorization, validate the callback, exchange the code, and call the Developer API.

Use Authorization Code with mandatory PKCE S256. Generate a fresh cryptographically random state, code_verifier, and SHA-256 code_challenge for every attempt. Store state and the verifier only for the short-lived transaction.

Start authorization

https://auth.roadops.app/authorize
  ?response_type=code
  &client_id=tpc_your_client_id
  &redirect_uri=https%3A%2F%2Fapp.example.com%2Foauth%2Fcallback
  &audience=https%3A%2F%2Fapi.roadops.app%2Fv1
  &scope=team%3Aread%20day%3Aread
  &state=RANDOM_STATE
  &code_challenge=BASE64URL_SHA256_VERIFIER
  &code_challenge_method=S256

The redirect URI must exactly match a registered callback. Validate state before exchanging the returned code. Authorization codes are short-lived and single-use.

The registered app scopes are an upper limit. The scope parameter controls what a particular authorization requests. If you add scopes to the app later, update this parameter and send the user through a new authorization flow. Existing access tokens keep their original scopes until they expire, and refresh tokens cannot expand them.

Include offline_access in scope only when offline access is enabled for the registered app and the app needs a refresh token. Enabling offline access does not add it to authorization requests automatically.

Exchange the code

Public SPA and native clients send client_id, code_verifier, and no secret:

POST https://auth.roadops.app/oauth/token
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code&client_id=tpc_your_client_id&code=CODE&redirect_uri=CALLBACK&code_verifier=VERIFIER

Regular web apps send the same form fields but authenticate with Authorization: Basic base64(client_id:client_secret). Never put a confidential client secret in browser or mobile code.

Call the API

GET https://api.roadops.app/v1/teams
Authorization: Bearer ACCESS_TOKEN

RoadOps validates the RS256 signature, issuer, audience, registered active app in azp, token scope, and the user's current RoadOps permissions on every request.