Document your API auth in OpenAPI
Make OAuth2 / OIDC discoverable in your API spec
If you ship an API, OpenAPI (Swagger) spec documents it. Including auth scheme makes integration easy for consumers.
OAuth2 in OpenAPI
openapi: 3.0.3
info:
title: Your API
version: 1.0.0
components:
securitySchemes:
olympus_oauth2:
type: oauth2
flows:
authorizationCode:
authorizationUrl: https://ciam.your-domain.com/oauth2/auth
tokenUrl: https://ciam.your-domain.com/oauth2/token
refreshUrl: https://ciam.your-domain.com/oauth2/token
scopes:
"openid": "OpenID identification"
"offline_access": "Maintain refresh token"
"profile": "Basic profile info"
"email": "Email address"
"orders:read": "Read orders"
"orders:write": "Modify orders"
security:
- olympus_oauth2: [openid, email]
paths:
/orders:
get:
security:
- olympus_oauth2: [orders:read]
responses:
'200':
description: List of orders
post:
security:
- olympus_oauth2: [orders:write]
responses:
'201':
description: Order createdConsumers see required scopes per endpoint.
Swagger UI
Render OpenAPI with Swagger UI:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="https://unpkg.com/swagger-ui-dist@5/swagger-ui.css">
</head>
<body>
<div id="ui"></div>
<script src="https://unpkg.com/swagger-ui-dist@5/swagger-ui-bundle.js"></script>
<script>
SwaggerUIBundle({
url: "/openapi.yaml",
dom_id: "#ui",
oauth2RedirectUrl: window.location.origin + "/swagger-oauth2-redirect.html",
});
ui.initOAuth({
clientId: "swagger-ui-client",
scopes: "openid offline_access",
usePkceWithAuthorizationCodeGrant: true,
});
</script>
</body>
</html>Developers can "Try it out" with their own OAuth flow.
Bearer token (for service accounts)
components:
securitySchemes:
bearer:
type: http
scheme: bearer
bearerFormat: JWT # or opaque
paths:
/admin/...:
get:
security:
- bearer: []For server-to-server callers using client_credentials.
OIDC discovery
components:
securitySchemes:
olympus_oidc:
type: openIdConnect
openIdConnectUrl: https://ciam.your-domain.com/.well-known/openid-configurationAuto-discovery: tools fetch the well-known endpoint to learn flow URLs, scopes, etc.
Hosting
Generate from your code:
// Generated from JSDoc / TypeScript types
import { OpenAPIObject } from "@asteasolutions/zod-to-openapi";
const spec: OpenAPIObject = generateOpenAPI();Tools per language:
- TypeScript: zod-to-openapi, drizzle-zod-to-openapi.
- Python: FastAPI auto-generates.
- Go: swag.
- Rust: utoipa.
Serve at /openapi.json and /openapi.yaml.
Per-endpoint scopes documentation
For each endpoint:
paths:
/orders/{id}:
delete:
summary: Cancel an order
security:
- olympus_oauth2: [orders:write]
parameters:
- name: id
in: path
required: true
responses:
'204':
description: Order cancelled
'403':
description: |
Missing required scope: `orders:write`
Or: caller is not the order owner / admin.Document not only scope but also custom authz.
Documenting custom claims
If your API uses custom claims:
components:
schemas:
AccessTokenClaims:
type: object
properties:
sub:
type: string
description: User UUID
scope:
type: string
description: Space-separated scopes
tenant_id:
type: string
description: |
Custom Olympus claim, identifies which tenant the user belongs to.
Use to scope queries.Helpful for API consumers writing their own validation.
Reusable security scheme refs
In multiple endpoints, refer to one scheme:
paths:
/orders:
get:
security:
- $ref: '#/components/securitySchemes/olympus_oauth2'
scopes: [orders:read]Centralized definition; reused everywhere.
Validating requests
OpenAPI middleware validates incoming requests against spec:
import { OpenAPIBackend } from "openapi-backend";
const api = new OpenAPIBackend({ definition: "openapi.yaml" });
api.register({
validationFail: (c, req, res) => res.status(400).json({ error: c.validation.errors }),
notImplemented: (c, req, res) => res.status(501),
notFound: (c, req, res) => res.status(404),
});
app.use(api.handler);Type mismatch / missing scope → automatic rejection.
Versioning the spec
info:
version: 1.4.0
description: |
See [changelog](/docs/changelog) for version history.When you ship a new API version (v2), new spec file (openapi-v2.yaml).
Client generation
Consumers can generate client libraries:
openapi-generator-cli generate -i https://your-domain.com/openapi.yaml -g typescript-axios -o ./your-api-clientGet a typed client for free. Updates with each spec change.