Configure Swagger UI to Test OAuth2-Protected APIs with PKCE
Configure Swagger UI to handle OAuth2 Authorization Code flow with PKCE, removing the need for manual token entry during API testing.
02 Aug 2026, 23:47 UTC

The Problem: Testing Secure APIs Without Manual Tokens
Testing REST APIs protected by OAuth2 often requires developers to manually generate access tokens via curl or Postman and paste them into the Swagger UI header. This process is tedious and breaks the "Try it out" experience. By configuring the Authorization Code flow with Proof Key for Code Exchange (PKCE), Swagger UI can handle the entire authentication handshake, including the secure exchange of a code for a token, directly within the browser.
Prerequisites
- An OpenAPI 3.0 specification file.
- An Authorization Server supporting RFC 7636 (PKCE), such as Keycloak, Auth0, or Azure AD.
- Swagger UI version 3.24.0 or newer (earlier versions lack native PKCE support).
- A registered Public Client ID (no client secret should be used for browser-based flows).
- A registered Redirect URI that exactly matches the URL where Swagger UI is hosted.
Configuration Procedure
1. Define the Security Scheme in OpenAPI
Add the oauth2 security scheme to your components. The pkce: true and codeChallengeMethod: S256 properties tell Swagger UI to generate a code verifier and challenge instead of relying on a client secret.
components:
securitySchemes:
oauth2Pkce:
type: oauth2
flows:
authorizationCode:
authorizationUrl: https://auth.example.com/oauth2/authorize
tokenUrl: https://auth.example.com/oauth2/token
scopes:
read: "Read access to resources"
write: "Write access to resources"
pkce: true
codeChallengeMethod: S256
security:
- oauth2Pkce: [read, write]
2. Initialize Swagger UI with Client Credentials
When initializing Swagger UI (e.g., via swagger-ui-express in Node.js), you must provide the clientId and the oauth2RedirectUrl. The redirect URL is the endpoint the authorization server sends the user back to after login.
const swaggerUi = require('swagger-ui-express');
const options = {
oauth2RedirectUrl: 'https://api.example.com/oauth2-redirect.html',
config: {
clientId: 'your-public-client-id',
scopeSeparator: ' ',
useBasicAuthenticationWithAccessCodeGrant: false
}
};
app.use('/docs', swaggerUi.serve, swaggerUi.setup(swaggerDocument, options));
3. Implement the Redirect Handler
The oauth2RedirectUrl must point to a page that invokes the Swagger UI redirect handler. This handler extracts the authorization code from the URL and exchanges it for a token using the PKCE verifier stored in the browser session.
<!DOCTYPE html>
<html>
<body>
<script>
// This function is provided by the Swagger UI library
if (window.oauth2RedirectHandler) {
window.oauth2RedirectHandler();
}
</script>
</body>
</html>
Validation and Expected Results
- Trigger Auth: Click the Authorize button in the UI, select the required scopes, and click Authorize. You should be redirected to your identity provider's login page.
- Verify Token Exchange: Open the browser's Network tab. Look for a
POSTrequest to thetokenUrl. It must containcode_verifierandcode_challenge_method=S256in the request body. - Test Endpoint: Click Try it out on a protected endpoint and Execute. Verify the request header includes
Authorization: Bearer <token>and the server returns a200 OK.
Recovery and Rollback
If the authentication flow fails (e.g., due to a cached invalid token or a configuration change), use these steps to reset the state:
- Clear Session: Run
window.localStorage.removeItem('swagger-ui-oauth2-redirect')in the browser console to force a fresh login. - Revert Config: To disable OAuth2 testing, remove the
securitysection from the OpenAPI document and theclientIdfrom the UI initialization.
Limitations
- Public Clients Only: This flow is strictly for public clients. Never put a
clientSecretin the OpenAPI file or UI config, as it is visible to anyone viewing the page. - URI Sensitivity: The redirect URI must be an exact string match in both the Authorization Server and the Swagger configuration; a missing trailing slash will cause the server to reject the request.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.