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)
| Parameter | Required | Description |
|---|---|---|
client_id | Yes | Your registered OAuth client ID |
redirect_uri | Yes | Must exactly match a registered redirect URI |
state | Yes | Opaque value for CSRF protection, returned unchanged in the callback |
scope | No | Space-separated scopes. Defaults to openid |
response_type | No | Must be code. Defaults to code |
Success response
HTTP/1.1 302 Found
Location: https://app.vacationtracker.io/oauth/authorize?session={sessionId}
Cache-Control: no-storeThe 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 code | Cause |
|---|---|
invalid_client | Unknown client_id |
invalid_request | Missing required parameter or redirect_uri not registered for this client |
invalid_scope | Requested scope not allowed for this client |
unsupported_response_type | response_type is not code |
POST /oauth/token
Exchanges an authorization code for tokens, or refreshes an existing token.
Client authentication
Two methods are supported:
- Request body: Include
client_idandclient_secretas form fields - 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
| Parameter | Required | Description |
|---|---|---|
grant_type | Yes | authorization_code |
code | Yes | The authorization code from the callback redirect |
redirect_uri | Yes | Must match the URI used in the authorization request |
client_id | Yes | Via body or Basic auth |
client_secret | Yes | Via 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
| Parameter | Required | Description |
|---|---|---|
grant_type | Yes | refresh_token |
refresh_token | Yes | The refresh token from a previous token response |
client_id | Yes | Via body or Basic auth |
client_secret | Yes | Via 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 code | Cause |
|---|---|
invalid_client | Unknown client_id or incorrect client_secret |
invalid_grant | Authorization code is invalid, expired, or already used. Or redirect_uri / client_id does not match. Or refresh token is invalid/expired. |
unsupported_grant_type | Only authorization_code and refresh_token are supported |
server_error | Unexpected server-side error |
Response headers
All token responses include:
Cache-Control: no-store
Pragma: no-cacheGET /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"
}| Field | Type | Description |
|---|---|---|
id | string | Vacation Tracker user ID |
name | string | User's full name |
email | string | User's email address |
Error responses
| Status | Error code | Cause |
|---|---|---|
| 401 | unauthorized | Missing or invalid Authorization header |
| 401 | invalid_token | Token is missing required claims |
Token lifetimes
| Token | Lifetime |
|---|---|
| Access token | 60 minutes |
| ID token | 60 minutes |
| Refresh token | 365 days |
| Authorization code | 10 minutes (single-use) |