Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/ricardomb-tech/auth-service/llms.txt

Use this file to discover all available pages before exploring further.

After a successful OAuth2 social login flow, Auth Service redirects the user’s browser to your configured OAUTH2_SUCCESS_REDIRECT_URI with a short-lived, single-use code query parameter. This endpoint lets your frontend exchange that code for a real JWT access token and refresh token pair. The exchange code is single-use and stored in memory — it expires or is consumed on first use, whichever comes first, so your client should call this endpoint immediately upon landing on the success redirect page.

Endpoint

Method: POST
Path: /auth/oauth2/exchange
Auth: None required — the exchange code is the credential

Request body

{
  "code": "<one-time-code>"
}
code
string
required
The one-time exchange code received as the code query parameter in OAUTH2_SUCCESS_REDIRECT_URI?code=<one-time-code> after a successful OAuth2 social login. The code is single-use: submitting it a second time returns 401 Unauthorized.

Response — 200 OK

On success, returns the same token structure as POST /auth/login.
{
  "accessToken": "eyJhbGciOiJIUzI1NiJ9...",
  "refreshToken": "d4e5f6a7-b8c9-...",
  "tokenType": "Bearer",
  "expiresInSeconds": 900
}
accessToken
string
A signed JWT access token. Include this in the Authorization: Bearer <token> header for all protected endpoints. The default TTL is 15 minutes (900 seconds).
refreshToken
string
An opaque refresh token (UUID). Use it to obtain a new token pair via POST /auth/refresh before the access token expires. The default TTL is 7 days.
tokenType
string
Always "Bearer".
expiresInSeconds
number
Remaining lifetime of the access token in seconds at the time of issuance. Typically 900 (15 minutes).

Error responses

StatusWhen
400 Bad Requestcode field is missing or blank (application/problem+json).
401 UnauthorizedCode not found, already used, or expired (application/problem+json).
401 error body:
{
  "type": "about:blank",
  "title": "Unauthorized",
  "status": 401,
  "detail": "Código de intercambio inválido o expirado.",
  "instance": "/auth/oauth2/exchange"
}

Example

curl -X POST http://localhost:8080/auth/oauth2/exchange \
  -H 'Content-Type: application/json' \
  -d '{"code": "<one-time-code>"}'
Success response:
{
  "accessToken": "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhMWIyYzNkNC1lNWY2LTc4OTAtYWJjZC1lZjEyMzQ1Njc4OTAiLCJpYXQiOjE3MDUzMTI2MDAsImV4cCI6MTcwNTMxMzUwMH0.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c",
  "refreshToken": "d4e5f6a7-b8c9-4def-8012-3456789abcde",
  "tokenType": "Bearer",
  "expiresInSeconds": 900
}

Security rationale

The exchange-code pattern exists to prevent tokens from appearing in browser history, server access logs, proxy logs, or being leaked via the Referer header. If the access token and refresh token were placed directly in the OAuth2 success redirect URL (e.g. ...?accessToken=...&refreshToken=...), they would be visible in all of those places before the frontend JavaScript could read and remove them. By placing only a short-lived, opaque code in the redirect URL and requiring a separate POST to trade it for tokens, Auth Service ensures:
  • Tokens never appear in URLs. They are returned only in the JSON response body of this endpoint.
  • The code is useless if intercepted after use. Once exchanged, the code is deleted from the store and subsequent attempts return 401.
  • Expiry limits the interception window. The code expires quickly even if the frontend never exchanges it.
The exchange code store is implemented as InMemoryOAuth2ExchangeCodeStore. This means exchange codes are held in the JVM heap of a single server instance and are not shared across nodes. In a multi-instance production deployment you must replace this store with a distributed alternative (e.g. Redis) or ensure that the OAuth2 callback and the /auth/oauth2/exchange call are always routed to the same instance. For single-instance or development environments the in-memory implementation works without any additional configuration.

Build docs developers (and LLMs) love