Swagger’s OAuth 2.0 definition is surprisingly flexible, often leading people to believe they’re configuring a single thing when they’re actually setting up two distinct authorization flows for different use cases.
Let’s see how this plays out in a real Swagger/OpenAPI definition. Imagine we have an API that needs to protect its endpoints. We’ll define the security schemes for two common OAuth 2.0 flows: Authorization Code and Client Credentials.
openapi: 3.0.0
info:
title: My Protected API
version: 1.0.0
paths:
/users:
get:
summary: Get a list of users
security:
- bearerAuth: [] # This security scheme is not defined below, but illustrates a common pattern
- oauth2_auth_code: []
responses:
'200':
description: A list of users
/internal/data:
get:
summary: Get internal sensitive data
security:
- oauth2_client_creds: []
responses:
'200':
description: Internal data
components:
securitySchemes:
oauth2_auth_code:
type: oauth2
description: OAuth 2.0 Authorization Code flow for user delegation.
flows:
authorizationCode:
authorizationUrl: https://auth.example.com/oauth2/authorize
tokenUrl: https://auth.example.com/oauth2/token
scopes:
read:Users: Grants read access to user data.
write:Users: Grants write access to user data.
oauth2_client_creds:
type: oauth2
description: OAuth 2.0 Client Credentials flow for machine-to-machine authentication.
flows:
clientCredentials:
tokenUrl: https://auth.example.com/oauth2/token
scopes:
read:InternalData: Grants read access to internal data.
write:InternalData: Grants write access to internal data.
In this definition, oauth2_auth_code is configured for the Authorization Code flow. This is the standard flow for user-interactive applications (like web apps or mobile apps) where a user logs in to grant an application permission to access their data on their behalf. The authorizationUrl is where the user is redirected to authenticate and consent, and the tokenUrl is where the application exchanges an authorization code for an access token. The scopes here are granular, reflecting actions a user might permit.
oauth2_client_creds is configured for the Client Credentials flow. This is for non-user-facing applications, like background services or scripts, that need to access resources directly using their own identity. There’s no user involved. The tokenUrl is used to obtain an access token, and the scopes typically represent permissions the application itself has. Notice how authorizationUrl is absent here because there’s no user redirection.
The key difference in the Swagger/OpenAPI definition lies within the flows object. For Authorization Code, you’ll see authorizationCode defined, requiring both authorizationUrl and tokenUrl. For Client Credentials, you’ll see clientCredentials defined, usually only requiring tokenUrl (though some providers might have custom extensions).
When you see type: oauth2 in a security scheme, it’s a broad category. The real distinction for how it functions comes from which flow type (authorizationCode, clientCredentials, implicit, password) is specified within the flows object. The tool consuming this OpenAPI definition (like Swagger UI or a code generator) will use this information to present the correct authentication mechanism to the developer or user.
Many developers overlook that the scopes object under authorizationCode is meant to represent permissions granted by a user, while scopes under clientCredentials represent permissions held by the client application. This distinction is crucial for correctly modeling your API’s security and for the authorization server to issue tokens with appropriate audience and privilege.
The next step after defining these security schemes is to apply them to your paths and operations, and then ensure your authorization server is correctly configured to issue tokens that satisfy these defined flows and scopes.