Vacation Tracker Docs
OAuth2 Authorization

Endpoints

Complete reference for all OAuth2 endpoints.

All endpoints are served under https://api.app.vacationtracker.io/oauth.

GET /oauth/authorize

Initiates the authorization code flow. Redirect the user's browser to this endpoint.

Request parameters (query string)

ParameterRequiredDescription
client_idYesYour registered OAuth client ID
redirect_uriYesMust exactly match a registered redirect URI
stateYesOpaque value for CSRF protection, returned unchanged in the callback
scopeNoSpace-separated scopes. Defaults to openid
response_typeNoMust be code. Defaults to code

Success response

HTTP/1.1 302 Found
Location: https://app.vacationtracker.io/oauth/authorize?session={sessionId}
Cache-Control: no-store

The user is redirected to the Vacation Tracker login and consent page.

Error response (400)

{
  "error": "invalid_client | invalid_request | invalid_scope | unsupported_response_type",
  "error_description": "Human-readable description"
}
Error codeCause
invalid_clientUnknown client_id
invalid_requestMissing required parameter or redirect_uri not registered for this client
invalid_scopeRequested scope not allowed for this client
unsupported_response_typeresponse_type is not code

POST /oauth/token

Exchanges an authorization code for tokens, or refreshes an existing token.

Client authentication

Two methods are supported:

  1. Request body: Include client_id and client_secret as form fields
  2. HTTP Basic: Send Authorization: Basic base64(client_id:client_secret) header

Content types

  • application/x-www-form-urlencoded (standard)
  • application/json

Authorization code exchange

Request parameters

ParameterRequiredDescription
grant_typeYesauthorization_code
codeYesThe authorization code from the callback redirect
redirect_uriYesMust match the URI used in the authorization request
client_idYesVia body or Basic auth
client_secretYesVia body or Basic auth

Success response (200)

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

Token refresh

Request parameters

ParameterRequiredDescription
grant_typeYesrefresh_token
refresh_tokenYesThe refresh token from a previous token response
client_idYesVia body or Basic auth
client_secretYesVia body or Basic auth

Success response (200)

{
  "access_token": "eyJ...",
  "refresh_token": "eyJ...",
  "token_type": "Bearer",
  "expires_in": 3600
}

Note: The same refresh token is echoed back. No id_token is included in refresh responses.

Error response (400)

{
  "error": "invalid_client | invalid_grant | unsupported_grant_type | server_error",
  "error_description": "Human-readable description"
}
Error codeCause
invalid_clientUnknown client_id or incorrect client_secret
invalid_grantAuthorization code is invalid, expired, or already used. Or redirect_uri / client_id does not match. Or refresh token is invalid/expired.
unsupported_grant_typeOnly authorization_code and refresh_token are supported
server_errorUnexpected server-side error

Response headers

All token responses include:

Cache-Control: no-store
Pragma: no-cache

GET /oauth/me

Returns basic profile information for the authenticated user.

Authentication

Requires a valid access token in the Authorization header:

Authorization: Bearer {access_token}

The access token must be one obtained via the /oauth/token endpoint (from the Shadow User Pool).

Success response (200)

{
  "id": "vt-user-123",
  "name": "Jane Doe",
  "email": "jane.doe@example.com"
}
FieldTypeDescription
idstringVacation Tracker user ID
namestringUser's full name
emailstringUser's email address

Error responses

StatusError codeCause
401unauthorizedMissing or invalid Authorization header
401invalid_tokenToken is missing required claims

Token lifetimes

TokenLifetime
Access token60 minutes
ID token60 minutes
Refresh token365 days
Authorization code10 minutes (single-use)

On this page