Swagger UI : authorization code with pkce flow not working
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Swagger UI : authorization code with pkce flow not working
I am not able to use Oauth Authorization code flow with pkce despite tried several methods as In my organization we have a customized implementation of swagger.
All other flows like password flow and client credentials flow is working fine but not the pkce flow.
Looking at the api-view-bundle.js there is support available for usePkceWithAuthorizationCodeGrant.
It would be really helpful if someone in the community can provide a sample implementation of oauth2-redirect.html file and authorization code with pkce implementation file;
Here's my current code:
"default.yaml" which contains path and security schemas:
components:
securitySchemes:
OAuth2_client_Credentials:
type: oauth2
flows:
clientCredentials:
tokenUrl: keycloak_url/realms/realm_name/protocol/openid-connect/token
scopes: {}
description: 'Use Client Credentials fetched from Client Api under Identities & Access/Client'
OAuth2_PKCE:
type: oauth2
flows:
authorizationCode:
authorizationUrl: http://localhost:8080/auth/realms/9e0830e8-efc7-11eb-97b6-a339bf7f4c8d/protocol/openid-connect/auth
tokenUrl: http://localhost:8080/auth/realms/9e0830e8-efc7-11eb-97b6-a339bf7f4c8d/protocol/openid-connect/token
scopes: {}
usePkceWithAuthorizationCodeGrant: true
And Here is the current "oauth-redirect.html"
<!doctype html>
<html lang="en-US">
<head>
<title>Swagger UI: OAuth2 Redirect</title>
</head>
<body>
<script>
'use strict';
function run() {
var oauth2 = window.opener.swaggerUIRedirectOauth2;
var sentState = oauth2.state;
var redirectUrl = oauth2.redirectUrl;
var isValid, qp, arr;
if (/code|token|error/.test(window.location.hash)) {
qp = window.location.hash.substring(1).replace('?', '&');
} else {
qp = location.search.substring(1);
}
arr = qp.split("&");
arr.forEach(function (v, i, _arr) {
_arr[i] = '"' + v.replace('=', '":"') + '"';
});
qp = qp ? JSON.parse('{' + arr.join() + '}',
function (key, value) {
return key === "" ? value : decodeURIComponent(value);
}
) : {};
isValid = qp.state === sentState;
if (!oauth2.auth.code) {
if (!isValid) {
oauth2.errCb({
authId: oauth2.auth.name,
source: "auth",
level: "warning",
message: "Authorization may be unsafe. The passed state was changed on the server. The passed state wasn't returned from the auth server."
});
}
if (qp.code) {
delete oauth2.state;
oauth2.auth.code = qp.code;
oauth2.callback({ auth: oauth2.auth, redirectUrl: redirectUrl });
} else {
let oauthErrorMsg;
if (qp.error) {
oauthErrorMsg = "[" + qp.error + "]: " +
(qp.error_description ? qp.error_description + ". " : "No accessCode received from the server. ") +
(qp.error_uri ? "More info: " + qp.error_uri : "");
}
oauth2.errCb({
authId: oauth2.auth.name,
source: "auth",
level: "error",
message: oauthErrorMsg || "[Authorization failed]: No accessCode received from the server"
});
}
} else {
oauth2.callback({ auth: oauth2.auth, token: qp, isValid: isValid, redirectUrl: redirectUrl });
}
window.close();
}
if (document.readyState !== 'loading') {
run();
} else {
document.addEventListener('DOMContentLoaded', function () {
run();
});
}
</script>
<script>
// Function to generate a random string
function generateRandomString(length) {
var charset = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
var result = '';
for (var i = 0; i < length; i++) {
var randomIndex = Math.floor(Math.random() * charset.length);
result += charset.charAt(randomIndex);
}
return result;
}
// Function to generate the code challenge from the code verifier
function generateCodeChallenge(codeVerifier) {
var encoder = new TextEncoder();
var data = encoder.encode(codeVerifier);
return crypto.subtle.digest('SHA-256', data)
.then(function (buffer) {
var byteArray = Array.from(new Uint8Array(buffer));
var codeChallenge = byteArray.map(function (byte) {
return ('0' + (byte & 0xFF).toString(16)).slice(-2);
}).join('');
return codeChallenge;
});
}
// Generate a random code verifier and code challenge
var codeVerifier = generateRandomString(128);
var codeChallengeMethod = 'S256'; // PKCE code challenge method
generateCodeChallenge(codeVerifier)
.then(function (codeChallenge) {
var authorizationUrl = 'http://localhost:8080/auth/realms/9e0830e8-efc7-11eb-97b6-a339af7f4c8c/protocol/openid-connect/auth';
var clientId = 'ems-scl-public-client';
var redirectUri = 'http://localhost:8081/emsWSReference/index.jsp';
var responseType = 'code';
var scope = 'openid';
var oauth2 = window.opener.swaggerUIRedirectOauth2;
oauth2.redirectUrl = redirectUri;
oauth2.state = generateRandomString(16); // Generate a random state value
var authorizationUrlWithParams = authorizationUrl +
'?client_id=' + encodeURIComponent(clientId) +
'&redirect_uri=' + encodeURIComponent(redirectUri) +
'&response_type=' + encodeURIComponent(responseType) +
'&scope=' + encodeURIComponent(scope) +
'&state=' + encodeURIComponent(oauth2.state) +
'&code_challenge_method=' + encodeURIComponent(codeChallengeMethod) +
'&code_challenge=' + encodeURIComponent(codeChallenge);
// Perform the redirect
console.log(authorizationUrlWithParams);
alert("url",authorizationUrlWithParams)
window.location.replace(authorizationUrlWithParams);
});
</script>
</body>
</html>
Please consider me a noob and provide me with a correct implementation.Thanks in advance
"name": "swagger-ui",
"version": "4.12.0",
https://swagger.io/docs/open-source-tools/swagger-ui/usage/oauth2/
