diff --git a/app/scripts/client/auth_strategies/oauth2/credentials_manager.js b/app/scripts/client/auth_strategies/oauth2/credentials_manager.js index 1bfdc0fa2..3a043a21e 100644 --- a/app/scripts/client/auth_strategies/oauth2/credentials_manager.js +++ b/app/scripts/client/auth_strategies/oauth2/credentials_manager.js @@ -19,6 +19,40 @@ grant_type: 'authorization_code', redirect_uri: RAML.Settings.oauth2RedirectUri }; + }, + + clientCredentialsParameters: function () { + return { + client_id: credentials.clientId, + client_secret: credentials.clientSecret, + grant_type: 'client_credentials' + }; + }, + + resourceOwnerParameters: function () { + var params = { + username: credentials.username, + password: credentials.password, + grant_type: 'password' + }; + + if (!credentials.clientSecret) { + params.client_id = credentials.clientId; + } + + return params; + }, + + resourceOwnerHeaders: function () { + if (!credentials.clientSecret) { + return {}; + } + + var authorization = btoa(credentials.clientId + ':' + credentials.clientSecret); + + return { + 'Authorization': 'Bearer ' + authorization + }; } }; }; diff --git a/app/scripts/client/auth_strategies/oauth2/grant.js b/app/scripts/client/auth_strategies/oauth2/grant.js index 927eba1a3..e8296c40c 100644 --- a/app/scripts/client/auth_strategies/oauth2/grant.js +++ b/app/scripts/client/auth_strategies/oauth2/grant.js @@ -1,27 +1,26 @@ (function() { 'use strict'; - var GRANTS = [ 'code', 'token' ], IMPLICIT_GRANT = 'token'; var Oauth2 = RAML.Client.AuthStrategies.Oauth2; - function grantTypeFrom(settings) { - var authorizationGrants = settings.authorizationGrants || []; - var filtered = authorizationGrants.filter(function(grant) { return grant === IMPLICIT_GRANT; }); - var specifiedGrant = filtered[0] || authorizationGrants[0]; - - if (!GRANTS.some(function(grant) { return grant === specifiedGrant; })) { - throw new Error('Unknown grant type: ' + specifiedGrant); - } - - return specifiedGrant; - } + var grants = { + code: true, + token: true, + owner: true, + credentials: true + }; var Grant = { create: function(settings, credentials) { - var type = grantTypeFrom(settings); + var type = credentials.grantType.type; var credentialsManager = Oauth2.credentialsManager(credentials, type); + if (!grants[type]) { + throw new Error('Unknown grant type: ' + type); + } + var className = type.charAt(0).toUpperCase() + type.slice(1); + return new this[className](settings, credentialsManager); } }; @@ -47,5 +46,27 @@ return Oauth2.requestAuthorization(this.settings, this.credentialsManager); }; + Grant.Owner = function(settings, credentialsManager) { + this.settings = settings; + this.credentialsManager = credentialsManager; + }; + + Grant.Owner.prototype.request = function() { + var requestToken = Oauth2.requestOwnerToken(this.settings, this.credentialsManager); + + return requestToken(); + }; + + Grant.Credentials = function(settings, credentialsManager) { + this.settings = settings; + this.credentialsManager = credentialsManager; + }; + + Grant.Credentials.prototype.request = function() { + var requestToken = Oauth2.requestCredentialsToken(this.settings, this.credentialsManager); + + return requestToken(); + }; + Oauth2.Grant = Grant; })(); diff --git a/app/scripts/client/auth_strategies/oauth2/request_access_token.js b/app/scripts/client/auth_strategies/oauth2/request_access_token.js index 46deab3f4..c987f56d0 100644 --- a/app/scripts/client/auth_strategies/oauth2/request_access_token.js +++ b/app/scripts/client/auth_strategies/oauth2/request_access_token.js @@ -18,21 +18,44 @@ return undefined; } + function extract(data) { + var method = accessTokenFromString; + + if (typeof data === 'object') { + method = accessTokenFromObject; + } + + return method(data); + } + RAML.Client.AuthStrategies.Oauth2.requestAccessToken = function(settings, credentialsManager) { return function(code) { var request = RAML.Client.Request.create(settings.accessTokenUri, 'post'); request.data(credentialsManager.accessTokenParameters(code)); - return $.ajax(request.toOptions()).then(function(data) { - var extract = accessTokenFromString; + return $.ajax(request.toOptions()).then(extract); + }; + }; + + RAML.Client.AuthStrategies.Oauth2.requestCredentialsToken = function(settings, credentialsManager) { + return function() { + var request = RAML.Client.Request.create(settings.accessTokenUri, 'post'); + + request.data(credentialsManager.clientCredentialsParameters()); + + return $.ajax(request.toOptions()).then(extract); + }; + }; + + RAML.Client.AuthStrategies.Oauth2.requestOwnerToken = function(settings, credentialsManager) { + return function() { + var request = RAML.Client.Request.create(settings.accessTokenUri, 'post'); - if (typeof data === 'object') { - extract = accessTokenFromObject; - } + request.headers(credentialsManager.resourceOwnerHeaders()); + request.data(credentialsManager.resourceOwnerParameters()); - return extract(data); - }); + return $.ajax(request.toOptions()).then(extract); }; }; })(); diff --git a/app/scripts/directives/oauth2.js b/app/scripts/directives/oauth2.js index 400cea401..949a28d5e 100644 --- a/app/scripts/directives/oauth2.js +++ b/app/scripts/directives/oauth2.js @@ -2,11 +2,43 @@ (function() { RAML.Directives.oauth2 = function() { + + var GRANT_TYPES = [ + { name: 'Implicit', type: 'token' }, + { name: 'Authorization Code', type: 'code' }, + { name: 'Client Credentials', type: 'credentials' }, + { name: 'Resource Owner Password Credentials', type: 'owner' } + ]; + + var controller = function($scope) { + var authorizationGrants = $scope.scheme.settings.authorizationGrants; + + $scope.grantTypes = GRANT_TYPES.filter(function (grant) { + return authorizationGrants.indexOf(grant.type) > -1; + }); + + $scope.credentials = { + clientId: '', + clientSecret: '', + username: '', + password: '', + grantType: $scope.grantTypes[0] + }; + + $scope.$watch('credentials.grantType.type', function (type) { + $scope.hasClientSecret = type !== 'token'; + $scope.hasOwnerCredentials = type === 'owner'; + $scope.requiresClientSecret = $scope.hasClientSecret && type !== 'owner'; + }); + }; + return { restrict: 'E', templateUrl: 'views/oauth2.tmpl.html', replace: true, + controller: controller, scope: { + scheme: '=', credentials: '=' } }; diff --git a/app/styles/forms.less b/app/styles/forms.less index 8a99077d7..5abd3184c 100644 --- a/app/styles/forms.less +++ b/app/styles/forms.less @@ -113,7 +113,8 @@ input.warning { outline: 0; } -.required { +.required:before { + content: "* "; color: @warning; } diff --git a/app/views/oauth2.tmpl.html b/app/views/oauth2.tmpl.html index b01d7de38..46ed34a86 100644 --- a/app/views/oauth2.tmpl.html +++ b/app/views/oauth2.tmpl.html @@ -1,11 +1,36 @@
- - + +
- - + + + +
+ +
+ + + +
+ +
+ + + +
+ +
+ + +
diff --git a/app/views/parameter_fields.tmpl.html b/app/views/parameter_fields.tmpl.html index c27483363..8903c492c 100644 --- a/app/views/parameter_fields.tmpl.html +++ b/app/views/parameter_fields.tmpl.html @@ -3,8 +3,7 @@
-
- + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +