Added support for OAuth client credentials (application) flow
Added support for multiple authentication schemes
To use the client credentials, index.html needs to have
1. input boxes to recieve client id and client secret
2. handlers that intitialse OAuth correctly on change.
For example, you could replace the explore and apikey inputs in the header with:
<div class='input'><input placeholder="client id" id="input_clientId" name="clientId" type="text" autocomplete="off"/></div>
<div class='input'><input placeholder="client secret" id="input_clientSecret" name="clientSecret" type="text" autocomplete="off"/></div>
and add the following javascrip to handle updates within the initialisation block (replacing the apikey javascript):
function updateOauth(){
initOAuth({
clientId: $('#input_clientId')[0].value,
clientSecret: $('#input_clientSecret')[0].value,
realm: "blank",
appName: "blank"
});
}
$('#input_clientId').change(updateOauth);
$('#input_clientSecret').change(updateOauth);
This commit is contained in:
@@ -3,7 +3,6 @@ var popupMask;
|
|||||||
var popupDialog;
|
var popupDialog;
|
||||||
var clientId;
|
var clientId;
|
||||||
var realm;
|
var realm;
|
||||||
var oauth2KeyName;
|
|
||||||
var redirect_uri;
|
var redirect_uri;
|
||||||
var clientSecret;
|
var clientSecret;
|
||||||
var scopeSeparator;
|
var scopeSeparator;
|
||||||
@@ -19,7 +18,7 @@ function handleLogin() {
|
|||||||
for(key in defs) {
|
for(key in defs) {
|
||||||
var auth = defs[key];
|
var auth = defs[key];
|
||||||
if(auth.type === 'oauth2' && auth.scopes) {
|
if(auth.type === 'oauth2' && auth.scopes) {
|
||||||
oauth2KeyName = key;
|
//oauth2KeyName = key;
|
||||||
var scope;
|
var scope;
|
||||||
if(Array.isArray(auth.scopes)) {
|
if(Array.isArray(auth.scopes)) {
|
||||||
// 1.2 support
|
// 1.2 support
|
||||||
@@ -31,7 +30,7 @@ function handleLogin() {
|
|||||||
else {
|
else {
|
||||||
// 2.0 support
|
// 2.0 support
|
||||||
for(scope in auth.scopes) {
|
for(scope in auth.scopes) {
|
||||||
scopes.push({scope: scope, description: auth.scopes[scope]});
|
scopes.push({scope: scope, description: auth.scopes[scope], OAuthSchemeKey: key});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -61,11 +60,15 @@ function handleLogin() {
|
|||||||
'</div>'].join(''));
|
'</div>'].join(''));
|
||||||
$(document.body).append(popupDialog);
|
$(document.body).append(popupDialog);
|
||||||
|
|
||||||
|
//TODO: only display applicable scopes (will need to pass them into handleLogin)
|
||||||
popup = popupDialog.find('ul.api-popup-scopes').empty();
|
popup = popupDialog.find('ul.api-popup-scopes').empty();
|
||||||
for (i = 0; i < scopes.length; i ++) {
|
for (i = 0; i < scopes.length; i ++) {
|
||||||
scope = scopes[i];
|
scope = scopes[i];
|
||||||
str = '<li><input type="checkbox" id="scope_' + i + '" scope="' + scope.scope + '"/>' + '<label for="scope_' + i + '">' + scope.scope;
|
str = '<li><input type="checkbox" id="scope_' + i + '" scope="' + scope.scope + '"' +'" oauthtype="' + scope.OAuthSchemeKey +'"/>' + '<label for="scope_' + i + '">' + scope.scope ;
|
||||||
if (scope.description) {
|
if (scope.description) {
|
||||||
|
if (auths.length > 1)
|
||||||
|
str += '<br/><span class="api-scope-desc">' + scope.description + ' ('+ scope.OAuthSchemeKey+')' +'</span>';
|
||||||
|
else
|
||||||
str += '<br/><span class="api-scope-desc">' + scope.description + '</span>';
|
str += '<br/><span class="api-scope-desc">' + scope.description + '</span>';
|
||||||
}
|
}
|
||||||
str += '</label></li>';
|
str += '</label></li>';
|
||||||
@@ -104,9 +107,25 @@ function handleLogin() {
|
|||||||
var defaultRedirectUrl = host.protocol + '//' + host.host + pathname + '/o2c.html';
|
var defaultRedirectUrl = host.protocol + '//' + host.host + pathname + '/o2c.html';
|
||||||
var redirectUrl = window.oAuthRedirectUrl || defaultRedirectUrl;
|
var redirectUrl = window.oAuthRedirectUrl || defaultRedirectUrl;
|
||||||
var url = null;
|
var url = null;
|
||||||
|
var scopes = []
|
||||||
|
var o = popup.find('input:checked');
|
||||||
|
var OAuthSchemeKeys = [];
|
||||||
|
var state;
|
||||||
|
for(k =0; k < o.length; k++) {
|
||||||
|
var scope = $(o[k]).attr('scope');
|
||||||
|
if (scopes.indexOf(scope) === -1)
|
||||||
|
scopes.push(scope);
|
||||||
|
var OAuthSchemeKey = $(o[k]).attr('oauthtype');
|
||||||
|
if (OAuthSchemeKeys.indexOf(OAuthSchemeKey) === -1)
|
||||||
|
OAuthSchemeKeys.push(OAuthSchemeKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: merge not replace if scheme is different from any existing
|
||||||
|
//(needs to be aware of schemes to do so correctly)
|
||||||
|
window.enabledScopes=scopes;
|
||||||
|
|
||||||
for (var key in authSchemes) {
|
for (var key in authSchemes) {
|
||||||
if (authSchemes.hasOwnProperty(key)) {
|
if (authSchemes.hasOwnProperty(key) && OAuthSchemeKeys.indexOf(key) != -1) { //only look at keys that match this scope.
|
||||||
var flow = authSchemes[key].flow;
|
var flow = authSchemes[key].flow;
|
||||||
|
|
||||||
if(authSchemes[key].type === 'oauth2' && flow && (flow === 'implicit' || flow === 'accessCode')) {
|
if(authSchemes[key].type === 'oauth2' && flow && (flow === 'implicit' || flow === 'accessCode')) {
|
||||||
@@ -114,6 +133,13 @@ function handleLogin() {
|
|||||||
url = dets.authorizationUrl + '?response_type=' + (flow === 'implicit' ? 'token' : 'code');
|
url = dets.authorizationUrl + '?response_type=' + (flow === 'implicit' ? 'token' : 'code');
|
||||||
window.swaggerUi.tokenName = dets.tokenName || 'access_token';
|
window.swaggerUi.tokenName = dets.tokenName || 'access_token';
|
||||||
window.swaggerUi.tokenUrl = (flow === 'accessCode' ? dets.tokenUrl : null);
|
window.swaggerUi.tokenUrl = (flow === 'accessCode' ? dets.tokenUrl : null);
|
||||||
|
state = key;
|
||||||
|
}
|
||||||
|
else if(authSchemes[key].type === 'oauth2' && flow && (flow === 'application')) {
|
||||||
|
var dets = authSchemes[key];
|
||||||
|
window.swaggerUi.tokenName = dets.tokenName || 'access_token';
|
||||||
|
clientCredentialsFlow(scopes, dets.tokenUrl, key);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
else if(authSchemes[key].grantTypes) {
|
else if(authSchemes[key].grantTypes) {
|
||||||
// 1.2 support
|
// 1.2 support
|
||||||
@@ -135,20 +161,6 @@ function handleLogin() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var scopes = []
|
|
||||||
var o = $('.api-popup-scopes').find('input:checked');
|
|
||||||
|
|
||||||
for(k =0; k < o.length; k++) {
|
|
||||||
var scope = $(o[k]).attr('scope');
|
|
||||||
|
|
||||||
if (scopes.indexOf(scope) === -1)
|
|
||||||
scopes.push(scope);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Implicit auth recommends a state parameter.
|
|
||||||
var state = Math.random ();
|
|
||||||
|
|
||||||
window.enabledScopes=scopes;
|
|
||||||
|
|
||||||
redirect_uri = redirectUrl;
|
redirect_uri = redirectUrl;
|
||||||
|
|
||||||
@@ -213,7 +225,32 @@ function initOAuth(opts) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function clientCredentialsFlow(scopes, tokenUrl, OAuthSchemeKey) {
|
||||||
|
var params = {
|
||||||
|
'client_id': clientId,
|
||||||
|
'client_secret': clientSecret,
|
||||||
|
'scope': scopes.join(' '),
|
||||||
|
'grant_type': 'client_credentials'
|
||||||
|
}
|
||||||
|
$.ajax(
|
||||||
|
{
|
||||||
|
url : tokenUrl,
|
||||||
|
type: "POST",
|
||||||
|
data: params,
|
||||||
|
success:function(data, textStatus, jqXHR)
|
||||||
|
{
|
||||||
|
onOAuthComplete(data,OAuthSchemeKey);
|
||||||
|
},
|
||||||
|
error: function(jqXHR, textStatus, errorThrown)
|
||||||
|
{
|
||||||
|
onOAuthComplete("");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
window.processOAuthCode = function processOAuthCode(data) {
|
window.processOAuthCode = function processOAuthCode(data) {
|
||||||
|
var OAuthSchemeKey = data.state;
|
||||||
var params = {
|
var params = {
|
||||||
'client_id': clientId,
|
'client_id': clientId,
|
||||||
'code': data.code,
|
'code': data.code,
|
||||||
@@ -232,7 +269,7 @@ window.processOAuthCode = function processOAuthCode(data) {
|
|||||||
data: params,
|
data: params,
|
||||||
success:function(data, textStatus, jqXHR)
|
success:function(data, textStatus, jqXHR)
|
||||||
{
|
{
|
||||||
onOAuthComplete(data);
|
onOAuthComplete(data, OAuthSchemeKey);
|
||||||
},
|
},
|
||||||
error: function(jqXHR, textStatus, errorThrown)
|
error: function(jqXHR, textStatus, errorThrown)
|
||||||
{
|
{
|
||||||
@@ -241,7 +278,7 @@ window.processOAuthCode = function processOAuthCode(data) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
window.onOAuthComplete = function onOAuthComplete(token) {
|
window.onOAuthComplete = function onOAuthComplete(token,OAuthSchemeKey) {
|
||||||
if(token) {
|
if(token) {
|
||||||
if(token.error) {
|
if(token.error) {
|
||||||
var checkbox = $('input[type=checkbox],.secured')
|
var checkbox = $('input[type=checkbox],.secured')
|
||||||
@@ -252,10 +289,13 @@ window.onOAuthComplete = function onOAuthComplete(token) {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
var b = token[window.swaggerUi.tokenName];
|
var b = token[window.swaggerUi.tokenName];
|
||||||
|
if (!OAuthSchemeKey){
|
||||||
|
OAuthSchemeKey = token.state;
|
||||||
|
}
|
||||||
if(b){
|
if(b){
|
||||||
// if all roles are satisfied
|
// if all roles are satisfied
|
||||||
var o = null;
|
var o = null;
|
||||||
$.each($('.auth .api-ic .api_information_panel'), function(k, v) {
|
$.each($('.auth .api_information_panel'), function(k, v) {
|
||||||
var children = v;
|
var children = v;
|
||||||
if(children && children.childNodes) {
|
if(children && children.childNodes) {
|
||||||
var requiredScopes = [];
|
var requiredScopes = [];
|
||||||
@@ -292,7 +332,7 @@ window.onOAuthComplete = function onOAuthComplete(token) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
window.swaggerUi.api.clientAuthorizations.add(oauth2KeyName, new SwaggerClient.ApiKeyAuthorization('Authorization', 'Bearer ' + b, 'header'));
|
window.swaggerUi.api.clientAuthorizations.add(OAuthSchemeKey, new SwaggerClient.ApiKeyAuthorization('Authorization', 'Bearer ' + b, 'header'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user