Skip to main content

OAuth 2.0 Endpoints

This page provides the complete reference for all OAuth 2.0 and OpenID Connect endpoints exposed by Rampart. These endpoints implement RFC 6749 (OAuth 2.0), RFC 7636 (PKCE), RFC 7009 (Token Revocation), and OpenID Connect Core 1.0.

Endpoint Summary

MethodEndpointDescription
GET/POST/oauth/authorizeAuthorization endpoint -- initiates user authentication
POST/oauth/consentConsent endpoint -- user approves/denies scope requests
POST/oauth/tokenToken endpoint -- exchanges authorization codes and refresh tokens
POST/oauth/revokeRevocation endpoint -- invalidates refresh tokens (RFC 7009)
GET/oauth/social/{provider}Initiate social login (redirect to provider)
GET/POST/oauth/social/{provider}/callbackSocial login callback
GET/.well-known/openid-configurationOIDC discovery document
GET/.well-known/jwks.jsonJSON Web Key Set for token verification

Authorization Endpoint

GET /oauth/authorize

POST /oauth/authorize

Initiates the OAuth 2.0 authorization flow. The client redirects the user's browser to this endpoint. Rampart authenticates the user, obtains consent, and redirects back with an authorization code.

This is a browser-based redirect endpoint, not a JSON API. Both GET and POST methods are supported.

Parameters:

ParameterTypeRequiredDescription
response_typestringYesMust be code
client_idstringYesRegistered OAuth client identifier
redirect_uristringYesMust exactly match a registered redirect URI
scopestringNoSpace-separated scopes (default: openid)
statestringRecommendedOpaque CSRF protection value, returned unchanged
noncestringNoValue included in the ID token to prevent replay attacks
code_challengestringYesBase64url-encoded SHA-256 hash of the code verifier (PKCE required)
code_challenge_methodstringYesMust be S256
promptstringNonone, login, consent, or select_account
login_hintstringNoPre-fills the username/email field
organization_idstringNoRestricts login to a specific organization
max_ageintegerNoMaximum authentication age in seconds
ui_localesstringNoPreferred UI locales (space-separated BCP 47 tags)
acr_valuesstringNoRequested authentication context class references

Example request URL:

https://your-rampart-instance/oauth/authorize
?response_type=code
&client_id=my-spa
&redirect_uri=https%3A%2F%2Fapp.example.com%2Fcallback
&scope=openid%20profile%20email
&state=af0ifjsldkj
&nonce=n-0S6_WzA2Mj
&code_challenge=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM
&code_challenge_method=S256

Successful redirect:

HTTP/1.1 302 Found
Location: https://app.example.com/callback?code=SplxlOBeZQQYbYS6WxSbIA&state=af0ifjsldkj

Error redirect:

HTTP/1.1 302 Found
Location: https://app.example.com/callback?error=access_denied&error_description=The+user+denied+the+request&state=af0ifjsldkj

Error codes:

ErrorDescription
invalid_requestMissing or invalid parameter
unauthorized_clientClient is not authorized for this flow
access_deniedUser denied consent
unsupported_response_typeOnly code is supported
invalid_scopeRequested scope is not allowed
server_errorInternal error
login_requiredprompt=none was used but the user is not authenticated
consent_requiredprompt=none was used but consent has not been granted
interaction_requiredprompt=none was used but user interaction is needed (e.g., MFA)

Prompt Behavior

ValueBehavior
noneNo UI is shown. Fails with login_required or consent_required if interaction is needed. Used for silent session checks.
loginForces re-authentication even if the user has an active session.
consentForces the consent screen even if previously consented.
select_accountShows an account picker if the user has multiple sessions.

POST /oauth/consent

Handles the user's consent decision (approve or deny) for the requested scopes. This endpoint is called by the consent form rendered during the authorization flow -- it is not called directly by clients.

Content-Type: application/x-www-form-urlencoded

Parameters (form body):

ParameterTypeRequiredDescription
decisionstringYesapprove or deny
client_idstringYesThe OAuth client ID
scopestringYesThe requested scopes
statestringYesThe state value from the authorization request
code_challengestringYesThe PKCE code challenge
noncestringNoThe nonce from the authorization request
redirect_uristringYesThe redirect URI
csrf_tokenstringYesCSRF protection token

Behavior:

  • If decision=approve: generates an authorization code and redirects to the client's redirect_uri with code and state parameters.
  • If decision=deny: redirects to the client's redirect_uri with error=access_denied.

Token Endpoint

POST /oauth/token

Issues access tokens, refresh tokens, and (optionally) ID tokens. Supports authorization_code and refresh_token grant types.

Content-Type: application/x-www-form-urlencoded

Authorization Code Grant

Exchanges an authorization code for tokens after the user completes the authorization flow.

Parameters:

ParameterTypeRequiredDescription
grant_typestringYesMust be authorization_code
codestringYesThe authorization code received from the authorize endpoint
redirect_uristringYesMust match the redirect URI used in the authorization request
client_idstringYesThe client identifier
client_secretstringConditionalRequired for confidential clients
code_verifierstringYesPKCE code verifier (required for all clients)

Request (public client with PKCE):

curl -X POST https://your-rampart-instance/oauth/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=authorization_code" \
-d "code=SplxlOBeZQQYbYS6WxSbIA" \
-d "redirect_uri=https://app.example.com/callback" \
-d "client_id=my-spa" \
-d "code_verifier=dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk"

Request (confidential client):

curl -X POST https://your-rampart-instance/oauth/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=authorization_code" \
-d "code=SplxlOBeZQQYbYS6WxSbIA" \
-d "redirect_uri=https://app.example.com/callback" \
-d "client_id=my-web-app" \
-d "client_secret=my-client-secret" \
-d "code_verifier=dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk"

Response (200 OK):

{
"access_token": "eyJhbGciOiJSUzI1NiIs...",
"refresh_token": "dGhpcyBpcyBhIHJlZnJlc2ggdG9rZW4gZXhhbXBsZQ",
"id_token": "eyJhbGciOiJSUzI1NiIs...",
"token_type": "Bearer",
"expires_in": 3600
}

The id_token is included only when the openid scope was requested. The response includes Cache-Control: no-store and Pragma: no-cache headers.

Notes:

  • PKCE (code_verifier) is required for all clients, not just public clients.
  • Confidential clients must also provide client_secret.

Refresh Token Grant

Exchanges a refresh token for a new access token and refresh token.

Parameters:

ParameterTypeRequiredDescription
grant_typestringYesMust be refresh_token
refresh_tokenstringYesThe refresh token issued during the original token request
client_idstringConditionalRequired if the original token was issued to a specific client
client_secretstringConditionalRequired for confidential clients

Request:

curl -X POST https://your-rampart-instance/oauth/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=refresh_token" \
-d "refresh_token=dGhpcyBpcyBhIHJlZnJlc2ggdG9rZW4gZXhhbXBsZQ" \
-d "client_id=my-spa"

Response (200 OK):

{
"access_token": "eyJhbGciOiJSUzI1NiIs...new-access-token",
"refresh_token": "bmV3LXJlZnJlc2gtdG9rZW4tZXhhbXBsZQ",
"token_type": "Bearer",
"expires_in": 3600
}

Notes:

  • Refresh token rotation is enforced: each use issues a new refresh token and invalidates the old one.
  • If a previously used refresh token is presented, Rampart treats it as potential token theft and the session may be invalidated (replay detection).
  • The client_id on refresh must match the client that originally obtained the authorization code. Confidential clients must re-authenticate with client_secret.

Supported Grant Types

Grant Typegrant_type ValueUse Case
Authorization Codeauthorization_codeWeb apps, SPAs, mobile apps
Refresh Tokenrefresh_tokenRenewing expired access tokens

Token Error Responses

All grant types may return the following errors:

ErrorHTTP StatusDescription
invalid_request400Missing required parameter or malformed request
invalid_client401Client authentication failed
invalid_grant400Code, refresh token, or credentials are invalid or expired
unauthorized_client400Client is not authorized for this grant type
unsupported_grant_type400Only authorization_code and refresh_token are supported

Error responses include additional fields for consistency:

{
"error": "invalid_grant",
"error_description": "Invalid, expired, or already-used authorization code.",
"status": 400,
"request_id": "req_abc123def456"
}

Access Token Claims

Rampart issues JWTs as access tokens with the following standard claims:

{
"iss": "https://your-rampart-instance",
"sub": "550e8400-e29b-41d4-a716-446655440000",
"aud": "my-web-app",
"exp": 1709514000,
"iat": 1709510400,
"nbf": 1709510400,
"jti": "tok_abc123def456",
"scope": "openid profile email",
"org_id": "770e8400-e29b-41d4-a716-446655440001",
"preferred_username": "jane.doe",
"email": "jane@example.com",
"email_verified": true,
"given_name": "Jane",
"family_name": "Doe",
"roles": ["user", "editor"]
}
ClaimTypeDescription
issstringIssuer -- your Rampart instance URL
substringSubject -- user ID (UUID)
audstringAudience -- the client_id this token was issued for
expintegerExpiration time (Unix timestamp)
iatintegerIssued-at time (Unix timestamp)
nbfintegerNot-before time (Unix timestamp)
jtistringUnique token identifier
scopestringSpace-separated granted scopes
org_idstringOrganization ID (UUID)
preferred_usernamestringThe user's username
emailstringThe user's email address
email_verifiedbooleanWhether the email is verified
given_namestringUser's first name
family_namestringUser's last name
rolesarrayUser's effective roles (direct + group-inherited)

ID Token Claims

When the openid scope is requested, an ID token is returned with identity claims:

{
"iss": "https://your-rampart-instance",
"sub": "550e8400-e29b-41d4-a716-446655440000",
"aud": "my-web-app",
"exp": 1709514000,
"iat": 1709510400,
"nonce": "n-0S6_WzA2Mj",
"auth_time": 1709510300,
"at_hash": "MTIzNDU2Nzg5MA",
"org_id": "770e8400-e29b-41d4-a716-446655440001",
"preferred_username": "jane.doe",
"email": "jane@example.com",
"email_verified": true,
"given_name": "Jane",
"family_name": "Doe"
}

Revocation Endpoint

POST /oauth/revoke

Invalidates a refresh token and its associated session. Implements RFC 7009.

Content-Type: application/x-www-form-urlencoded

Parameters:

ParameterTypeRequiredDescription
tokenstringYesThe token to revoke (refresh token)
token_type_hintstringNoOptional hint (currently only refresh tokens can be revoked)

Request:

curl -X POST https://your-rampart-instance/oauth/revoke \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "token=dGhpcyBpcyBhIHJlZnJlc2ggdG9rZW4"

Response:

Always returns HTTP 200 OK with an empty body, regardless of whether the token was valid. This prevents token fishing (per RFC 7009).

HTTP/1.1 200 OK

Notes:

  • Revoking a refresh token deletes the associated session, effectively invalidating the access token as well.
  • Access tokens are short-lived JWTs and cannot be individually revoked server-side. They remain valid until they expire.

Social Login Endpoints

GET /oauth/social/{provider}

Initiates social login by redirecting the user to the external identity provider (e.g., Google, GitHub, Apple).

Path parameters:

ParameterDescription
providerSocial provider name (e.g., google, github, apple)

Example:

GET https://your-rampart-instance/oauth/social/google

Redirects the user to Google's OAuth 2.0 authorization endpoint.

GET /oauth/social/{provider}/callback

POST /oauth/social/{provider}/callback

Handles the callback from the social identity provider after authentication. Both GET and POST methods are supported because some providers (e.g., Apple Sign In) use response_mode=form_post which delivers the code and state via a POST request.

After successful authentication, the user is redirected to the original client application with an authorization code.


SAML Endpoints

GET /saml/providers

List configured SAML identity providers.

Auth required: No

Response (200 OK): Returns the list of available SAML providers.

GET /saml/{providerID}/metadata

Returns the SAML SP metadata XML for the specified provider. This is used to configure the SAML identity provider.

Content-Type: application/xml

Example:

curl -X GET https://your-rampart-instance/saml/my-idp/metadata

GET /saml/{providerID}/login

Initiates SAML SSO login by redirecting the user to the configured identity provider.

Example:

GET https://your-rampart-instance/saml/my-idp/login

Redirects the user to the SAML IdP with a SAML AuthnRequest.

POST /saml/{providerID}/acs

The Assertion Consumer Service (ACS) endpoint. Receives the SAML response from the identity provider after authentication.

Content-Type: application/x-www-form-urlencoded

This endpoint processes the SAML assertion, creates or links the user account, and redirects back to the client application.


Complete PKCE Flow Example

Here is a complete Authorization Code with PKCE flow from start to finish, using JavaScript.

Step 1: Generate PKCE Values

// Generate a cryptographically random code verifier
function generateCodeVerifier() {
const array = new Uint8Array(32);
crypto.getRandomValues(array);
return base64urlEncode(array);
}

// Generate the code challenge from the verifier
async function generateCodeChallenge(verifier) {
const encoder = new TextEncoder();
const data = encoder.encode(verifier);
const digest = await crypto.subtle.digest("SHA-256", data);
return base64urlEncode(new Uint8Array(digest));
}

function base64urlEncode(buffer) {
return btoa(String.fromCharCode(...buffer))
.replace(/\+/g, "-")
.replace(/\//g, "_")
.replace(/=+$/, "");
}

const codeVerifier = generateCodeVerifier();
const codeChallenge = await generateCodeChallenge(codeVerifier);

// Store the verifier securely (e.g., sessionStorage)
sessionStorage.setItem("pkce_verifier", codeVerifier);

Step 2: Redirect to Authorization Endpoint

const state = crypto.randomUUID();
sessionStorage.setItem("oauth_state", state);

const params = new URLSearchParams({
response_type: "code",
client_id: "my-spa",
redirect_uri: "https://app.example.com/callback",
scope: "openid profile email",
state: state,
code_challenge: codeChallenge,
code_challenge_method: "S256",
});

window.location.href =
`https://your-rampart-instance/oauth/authorize?${params}`;

Step 3: Handle the Callback

// On your callback page (https://app.example.com/callback)
const params = new URLSearchParams(window.location.search);
const code = params.get("code");
const returnedState = params.get("state");

// Verify state matches
const savedState = sessionStorage.getItem("oauth_state");
if (returnedState !== savedState) {
throw new Error("State mismatch -- possible CSRF attack");
}

// Retrieve the code verifier
const codeVerifier = sessionStorage.getItem("pkce_verifier");

Step 4: Exchange Code for Tokens

const tokenResponse = await fetch(
"https://your-rampart-instance/oauth/token",
{
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
body: new URLSearchParams({
grant_type: "authorization_code",
code: code,
redirect_uri: "https://app.example.com/callback",
client_id: "my-spa",
code_verifier: codeVerifier,
}),
}
);

const tokens = await tokenResponse.json();
// tokens.access_token -- use for API calls
// tokens.id_token -- user identity claims (if openid scope requested)
// tokens.refresh_token -- use to get new access tokens

Step 5: Use the Access Token

const apiResponse = await fetch("https://api.example.com/data", {
headers: {
Authorization: `Bearer ${tokens.access_token}`,
},
});

Step 6: Refresh When Expired

const refreshResponse = await fetch(
"https://your-rampart-instance/oauth/token",
{
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
body: new URLSearchParams({
grant_type: "refresh_token",
refresh_token: tokens.refresh_token,
client_id: "my-spa",
}),
}
);

const newTokens = await refreshResponse.json();
// Update stored tokens with newTokens

Endpoint Authentication Summary

EndpointAuthentication RequiredMethod
GET/POST /oauth/authorizeNone (user authenticates interactively)--
POST /oauth/consentNone (uses consent cookie set during authorize)Cookie
POST /oauth/tokenConfidential clients onlyPOST body (client_secret)
POST /oauth/revokeNone--
GET /oauth/social/{provider}None--
GET/POST /oauth/social/{provider}/callbackNone--
GET /saml/providersNone--
GET /saml/{providerID}/metadataNone--
GET /saml/{providerID}/loginNone--
POST /saml/{providerID}/acsNone--