Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added basic support for oauth2-password-flow #1574

Closed
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
139 changes: 96 additions & 43 deletions lib/swagger-oauth.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,26 +11,33 @@ var scopeSeparator;
function handleLogin() {
var scopes = [];

var auths = window.swaggerUi.api.authSchemes || window.swaggerUi.api.securityDefinitions;
var auths = window.swaggerUi.api.authSchemes || window.swaggerUi.api.securityDefinitions,
passwordFlow = false;

if(auths) {
var key;
var defs = auths;
for(key in defs) {
var auth = defs[key];
if(auth.type === 'oauth2' && auth.scopes) {
oauth2KeyName = key;
var scope;
if(Array.isArray(auth.scopes)) {
// 1.2 support
var i;
for(i = 0; i < auth.scopes.length; i++) {
scopes.push(auth.scopes[i]);
if(auth.type === 'oauth2') {
passwordFlow = auth.flow === 'password';

if (auth.scopes) {
oauth2KeyName = key;
var scope;

if(Array.isArray(auth.scopes)) {
// 1.2 support
var i;
for(i = 0; i < auth.scopes.length; i++) {
scopes.push(auth.scopes[i]);
}
}
}
else {
// 2.0 support
for(scope in auth.scopes) {
scopes.push({scope: scope, description: auth.scopes[scope]});
else {
// 2.0 support
for(scope in auth.scopes) {
scopes.push({scope: scope, description: auth.scopes[scope]});
}
}
}
}
Expand All @@ -42,22 +49,32 @@ function handleLogin() {
appName = window.swaggerUi.api.info.title;
}

$('.api-popup-dialog').remove();
popupDialog = $(
[
'<div class="api-popup-dialog">',
'<div class="api-popup-title">Select OAuth2.0 Scopes</div>',
'<div class="api-popup-content">',
'<p>Scopes are used to grant an application different levels of access to data on behalf of the end user. Each API may declare one or more scopes.',
'<a href="#">Learn how to use</a>',
'</p>',
'<p><strong>' + appName + '</strong> API requires the following scopes. Select which ones you want to grant to Swagger UI.</p>',
'<ul class="api-popup-scopes">',
'</ul>',
'<p class="error-msg"></p>',
'<div class="api-popup-actions"><button class="api-popup-authbtn api-button green" type="button">Authorize</button><button class="api-popup-cancel api-button gray" type="button">Cancel</button></div>',
'</div>',
'</div>'].join(''));
$('.api-popup-dialog').remove();

popupDialog = ['<div class="api-popup-dialog">'];

if (passwordFlow === true) {
popupDialog = popupDialog.concat([
'<div class="api-popup-title">Password Auth</div>',
'<p><label>Username: </label> <input type="text" id="username"> ',
'<label>Password: </label> <input type="password" id="password"></p>'
]);
}

popupDialog = $(popupDialog.concat([
'<div class="api-popup-title">Select OAuth2.0 Scopes</div>',
'<div class="api-popup-content">',
'<p>Scopes are used to grant an application different levels of access to data on behalf of the end user. Each API may declare one or more scopes.',
'<a href="#">Learn how to use</a>',
'</p>',
'<p><strong>' + appName + '</strong> API requires the following scopes. Select which ones you want to grant to Swagger UI.</p>',
'<ul class="api-popup-scopes">',
'</ul>',
'<p class="error-msg"></p>',
'<div class="api-popup-actions"><button class="api-popup-authbtn api-button green" type="button">Authorize</button><button class="api-popup-cancel api-button gray" type="button">Cancel</button></div>',
'</div>',
'</div>']).join(''));

$(document.body).append(popupDialog);

popup = popupDialog.find('ul.api-popup-scopes').empty();
Expand Down Expand Up @@ -98,21 +115,31 @@ function handleLogin() {
popupDialog.hide();

var authSchemes = window.swaggerUi.api.authSchemes;

var host = window.location;
var pathname = location.pathname.substring(0, location.pathname.lastIndexOf("/"));
var defaultRedirectUrl = host.protocol + '//' + host.host + pathname + '/o2c.html';
var redirectUrl = window.oAuthRedirectUrl || defaultRedirectUrl;
var url = null;
var passwordFlowDetails = null;

for (var key in authSchemes) {
if (authSchemes.hasOwnProperty(key)) {
var flow = authSchemes[key].flow;

if(authSchemes[key].type === 'oauth2' && flow && (flow === 'implicit' || flow === 'accessCode')) {
if (authSchemes[key].type === 'oauth2' && flow) {
var dets = authSchemes[key];
url = dets.authorizationUrl + '?response_type=' + (flow === 'implicit' ? 'token' : 'code');
window.swaggerUi.tokenName = dets.tokenName || 'access_token';
window.swaggerUi.tokenUrl = (flow === 'accessCode' ? dets.tokenUrl : null);

if (flow === 'password') {
passwordFlowDetails = dets;
window.swaggerUi.tokenUrl = dets.tokenUrl;

} else if (['implicit', 'accessCode'].indexOf(flow) !== -1) {

url = dets.authorizationUrl + '?response_type=' + (flow === 'implicit' ? 'token' : 'code');
window.swaggerUi.tokenUrl = (flow === 'accessCode' ? dets.tokenUrl : null);
}
}
else if(authSchemes[key].grantTypes) {
// 1.2 support
Expand Down Expand Up @@ -144,27 +171,53 @@ function handleLogin() {
scopes.push(scope);
}

// Implicit auth recommends a state parameter.
var state = Math.random ();
if (passwordFlowDetails !== null) {
handlePasswordFlow(passwordFlowDetails);

window.enabledScopes=scopes;
} else {
// Implicit auth recommends a state parameter.
var state = Math.random ();

redirect_uri = redirectUrl;
window.enabledScopes=scopes;

url += '&redirect_uri=' + encodeURIComponent(redirectUrl);
url += '&realm=' + encodeURIComponent(realm);
url += '&client_id=' + encodeURIComponent(clientId);
url += '&scope=' + encodeURIComponent(scopes.join(scopeSeparator));
url += '&state=' + encodeURIComponent(state);
redirect_uri = redirectUrl;

window.open(url);
url += '&redirect_uri=' + encodeURIComponent(redirectUrl);
url += '&realm=' + encodeURIComponent(realm);
url += '&client_id=' + encodeURIComponent(clientId);
url += '&scope=' + encodeURIComponent(scopes.join(scopeSeparator));
url += '&state=' + encodeURIComponent(state);

window.open(url);
}
});

popupMask.show();
popupDialog.show();
return;
}

function handlePasswordFlow(auth) {
var authParams = {
grant_type: 'password',
client_id: encodeURIComponent(clientId),
username: $('#username').val(),
password: encodeURIComponent($('#password').val()),
client_secret: encodeURIComponent(clientSecret)
};

$.ajax({
url: auth.tokenUrl,
type: 'post',
data: authParams,
success: function (data) {
onOAuthComplete(data);
},
error: function(data) {
onOAuthComplete("");
}
});
}

function handleLogout() {
for(key in window.swaggerUi.api.clientAuthorizations.authz){
Expand Down