Skip to content

OAuth API

The OAuth API is the OAuth 2.0 surface for token issuance, refresh, and introspection. The authorization endpoint lives on the auth service; the token and refresh endpoints live here on public-api.

For the conceptual overview of how OAuth fits into Skynet — grant types, scopes, client registration, personal token semantics — see Auth. This page covers the endpoints themselves.

Endpoints at a glance

Endpoint Purpose
POST /oauth/token Exchange an authorization code for access + refresh tokens (auth code grant only)
POST /oauth/token/refresh Exchange a refresh token for a new access (and refresh) token
POST /oauth/token/introspect Inspect a token's validity and metadata (admin / first-party clients only)
POST /oauth/token/revoke Revoke an active token

The authorization endpoint (/oauth/authorize) is served by apps/auth/, not by this router.

Supported flows

  • Authorization code with PKCE. The only grant type supported for new code exchange. The authorization endpoint accepts a code_challenge; the token endpoint verifies it.
  • Refresh token rotation. Calling /oauth/token/refresh returns a new refresh token; the old one is invalidated. Always replace the stored refresh token with the new one.

There is no client_credentials, password, or implicit grant. See Auth — Grant types.

Client identifiers

Every token-endpoint call carries client_id and (for confidential clients) client_secret. Confidential clients send the secret in the request body; public clients omit it and rely on PKCE for authorization-code verification.

Common pitfalls

  • Missing PKCE on the authorize step. The token endpoint will reject the code exchange if the authorize step didn't include a code challenge.
  • Reusing an authorization code. Codes are single-use; trying to reuse one returns an error.
  • Refresh token rotation. When refresh returns a new refresh token, replace the stored copy immediately or you'll be locked out at the next refresh.

Reference

OAuth API 2.0.0

Endpoints for managing OAuth authentication and authorization.


OAuth


GET /oauth/clients

Get Oauth Clients

Description

Return all registered OAuth clients.

Responses

[
    {
        "allowedScopes": null,
        "clientId": "string",
        "createdAt": null,
        "description": null,
        "logoUrl": null,
        "name": "string",
        "redirectUris": [
            "string"
        ]
    }
]
⚠️ This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.

Schema of the response body
{
    "items": {
        "$ref": "#/components/schemas/OAuthClient"
    },
    "title": "Response Get Oauth Clients Oauth Clients Get",
    "type": "array"
}

GET /oauth/clients/{client_id}

Get Oauth Client

Description

Return a specific registered OAuth client.

Input parameters

Parameter In Type Default Nullable Description
client_id path string No

Responses

{
    "allowedScopes": null,
    "clientId": "string",
    "createdAt": null,
    "description": null,
    "logoUrl": null,
    "name": "string",
    "redirectUris": [
        "string"
    ]
}
⚠️ This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.

Schema of the response body
{
    "properties": {
        "allowedScopes": {
            "anyOf": [
                {
                    "items": {
                        "type": "string"
                    },
                    "type": "array"
                },
                {
                    "type": "null"
                }
            ],
            "description": "Allowed scopes"
        },
        "clientId": {
            "description": "Unique client identifier",
            "type": "string"
        },
        "createdAt": {
            "anyOf": [
                {
                    "type": "string"
                },
                {
                    "type": "null"
                }
            ],
            "description": "Creation timestamp"
        },
        "description": {
            "anyOf": [
                {
                    "type": "string"
                },
                {
                    "type": "null"
                }
            ],
            "description": "Description of the client"
        },
        "logoUrl": {
            "anyOf": [
                {
                    "type": "string"
                },
                {
                    "type": "null"
                }
            ],
            "description": "Logo URL"
        },
        "name": {
            "description": "Name of the client",
            "type": "string"
        },
        "redirectUris": {
            "description": "Allowed redirect URIs",
            "items": {
                "type": "string"
            },
            "type": "array"
        }
    },
    "required": [
        "clientId",
        "redirectUris",
        "name"
    ],
    "title": "OAuthClient",
    "type": "object"
}

{
    "detail": [
        {
            "ctx": {},
            "input": null,
            "loc": [
                null
            ],
            "msg": "string",
            "type": "string"
        }
    ]
}
⚠️ This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.

Schema of the response body
{
    "properties": {
        "detail": {
            "items": {
                "$ref": "#/components/schemas/ValidationError"
            },
            "title": "Detail",
            "type": "array"
        }
    },
    "title": "HTTPValidationError",
    "type": "object"
}

POST /oauth/sign-out

Sign Out Post

Input parameters

Parameter In Type Default Nullable Description
token query No

Responses

{
    "detail": [
        {
            "ctx": {},
            "input": null,
            "loc": [
                null
            ],
            "msg": "string",
            "type": "string"
        }
    ]
}
⚠️ This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.

Schema of the response body
{
    "properties": {
        "detail": {
            "items": {
                "$ref": "#/components/schemas/ValidationError"
            },
            "title": "Detail",
            "type": "array"
        }
    },
    "title": "HTTPValidationError",
    "type": "object"
}

POST /oauth/token

Token

Description

Exchange an authorization code for an access token using PKCE.

Request body

{
    "clientId": "string",
    "code": "string",
    "codeVerifier": null,
    "grantType": "string",
    "redirectUri": "string"
}
⚠️ This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.

Schema of the request body
{
    "description": "Request model for token exchange.",
    "properties": {
        "clientId": {
            "description": "The client ID of the application making the request",
            "type": "string"
        },
        "code": {
            "description": "The authorization code received from the authorization server",
            "type": "string"
        },
        "codeVerifier": {
            "anyOf": [
                {
                    "type": "string"
                },
                {
                    "type": "null"
                }
            ],
            "description": "The code verifier used in PKCE (Proof Key for Code Exchange)"
        },
        "grantType": {
            "description": "The type of grant being requested",
            "type": "string"
        },
        "redirectUri": {
            "description": "The URI to redirect to after the token exchange",
            "type": "string"
        }
    },
    "required": [
        "grantType",
        "code",
        "redirectUri",
        "clientId"
    ],
    "title": "TokenRequest",
    "type": "object"
}

Responses

{
    "accessToken": "string",
    "expiresIn": 10.12,
    "issuedAt": 10.12,
    "refreshToken": null,
    "tokenType": "string"
}
⚠️ This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.

Schema of the response body
{
    "description": "Response model for token exchange.",
    "properties": {
        "accessToken": {
            "description": "Access token issued by the authorization server",
            "type": "string"
        },
        "expiresIn": {
            "description": "Duration in seconds until the token expires",
            "type": "number"
        },
        "issuedAt": {
            "description": "Timestamp when the token was issued (UNIX timestamp)",
            "type": "number"
        },
        "refreshToken": {
            "anyOf": [
                {
                    "type": "string"
                },
                {
                    "type": "null"
                }
            ],
            "description": "Refresh token issued by the authorization server"
        },
        "tokenType": {
            "default": "Bearer",
            "description": "Type of the token issued, typically 'Bearer'",
            "type": "string"
        }
    },
    "required": [
        "accessToken",
        "expiresIn",
        "issuedAt"
    ],
    "title": "TokenResponse",
    "type": "object"
}

{
    "detail": [
        {
            "ctx": {},
            "input": null,
            "loc": [
                null
            ],
            "msg": "string",
            "type": "string"
        }
    ]
}
⚠️ This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.

Schema of the response body
{
    "properties": {
        "detail": {
            "items": {
                "$ref": "#/components/schemas/ValidationError"
            },
            "title": "Detail",
            "type": "array"
        }
    },
    "title": "HTTPValidationError",
    "type": "object"
}

POST /oauth/token/refresh

Refresh Token Post

Input parameters

Parameter In Type Default Nullable Description
token query No

Request body

{
    "refresh_token": null
}
⚠️ This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.

Schema of the request body
{
    "properties": {
        "refresh_token": {
            "anyOf": [
                {
                    "type": "string"
                },
                {
                    "type": "null"
                }
            ],
            "title": "Refresh Token"
        }
    },
    "title": "Body_refresh_token_post_oauth_token_refresh_post",
    "type": "object"
}

Responses

{
    "accessToken": "string",
    "expiresIn": 10.12,
    "issuedAt": 10.12,
    "refreshToken": null,
    "tokenType": "string"
}
⚠️ This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.

Schema of the response body
{
    "description": "Response model for token exchange.",
    "properties": {
        "accessToken": {
            "description": "Access token issued by the authorization server",
            "type": "string"
        },
        "expiresIn": {
            "description": "Duration in seconds until the token expires",
            "type": "number"
        },
        "issuedAt": {
            "description": "Timestamp when the token was issued (UNIX timestamp)",
            "type": "number"
        },
        "refreshToken": {
            "anyOf": [
                {
                    "type": "string"
                },
                {
                    "type": "null"
                }
            ],
            "description": "Refresh token issued by the authorization server"
        },
        "tokenType": {
            "default": "Bearer",
            "description": "Type of the token issued, typically 'Bearer'",
            "type": "string"
        }
    },
    "required": [
        "accessToken",
        "expiresIn",
        "issuedAt"
    ],
    "title": "TokenResponse",
    "type": "object"
}

{
    "detail": [
        {
            "ctx": {},
            "input": null,
            "loc": [
                null
            ],
            "msg": "string",
            "type": "string"
        }
    ]
}
⚠️ This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.

Schema of the response body
{
    "properties": {
        "detail": {
            "items": {
                "$ref": "#/components/schemas/ValidationError"
            },
            "title": "Detail",
            "type": "array"
        }
    },
    "title": "HTTPValidationError",
    "type": "object"
}

Schemas

Body_refresh_token_post_oauth_token_refresh_post

Name Type Description
refresh_token

HTTPValidationError

Name Type Description
detail Array<ValidationError>

OAuthClient

Name Type Description
allowedScopes Allowed scopes
clientId string Unique client identifier
createdAt Creation timestamp
description Description of the client
logoUrl Logo URL
name string Name of the client
redirectUris Array<string> Allowed redirect URIs

TokenRequest

Name Type Description
clientId string The client ID of the application making the request
code string The authorization code received from the authorization server
codeVerifier The code verifier used in PKCE (Proof Key for Code Exchange)
grantType string The type of grant being requested
redirectUri string The URI to redirect to after the token exchange

TokenResponse

Name Type Description
accessToken string Access token issued by the authorization server
expiresIn number Duration in seconds until the token expires
issuedAt number Timestamp when the token was issued (UNIX timestamp)
refreshToken Refresh token issued by the authorization server
tokenType string Type of the token issued, typically 'Bearer'

ValidationError

Name Type Description
ctx
input
loc Array<>
msg string
type string