Skip to content

Commit

Permalink
Enable addition OAuth 2.0 grant flows
Browse files Browse the repository at this point in the history
  • Loading branch information
blakeembrey committed Nov 14, 2014
1 parent 5719878 commit 4b59917
Show file tree
Hide file tree
Showing 10 changed files with 272 additions and 33 deletions.
34 changes: 34 additions & 0 deletions app/scripts/client/auth_strategies/oauth2/credentials_manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
};
}
};
};
Expand Down
47 changes: 34 additions & 13 deletions app/scripts/client/auth_strategies/oauth2/grant.js
Original file line number Diff line number Diff line change
@@ -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);
}
};
Expand All @@ -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;
})();
37 changes: 30 additions & 7 deletions app/scripts/client/auth_strategies/oauth2/request_access_token.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
};
};
})();
32 changes: 32 additions & 0 deletions app/scripts/directives/oauth2.js
Original file line number Diff line number Diff line change
Expand Up @@ -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: '='
}
};
Expand Down
3 changes: 2 additions & 1 deletion app/styles/forms.less
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,8 @@ input.warning {
outline: 0;
}

.required {
.required:before {
content: "* ";
color: @warning;
}

Expand Down
33 changes: 29 additions & 4 deletions app/views/oauth2.tmpl.html
Original file line number Diff line number Diff line change
@@ -1,11 +1,36 @@
<fieldset class="labelled-inline" role="oauth2">
<div class="control-group">
<label for="clientId">Client ID</label>
<input type="text" name="clientId" ng-model='credentials.clientId'/>
<label for="grantType">Grant Type</label>
<select
name="grantType"
ng-model="credentials.grantType"
ng-options="grant.name for grant in grantTypes">
</select>
</div>

<div class="control-group">
<label for="clientSecret">Client Secret</label>
<input type="password" name="clientSecret" ng-model='credentials.clientSecret'/>
<label for="clientId" class="required">Client ID</label>

<input type="text" name="clientId" ng-model="credentials.clientId" required>
</div>

<div class="control-group" ng-if="hasClientSecret">
<label for="clientSecret" ng-class="{ required: requiresClientSecret }">
Client Secret
</label>

<input type="password" name="clientSecret" ng-model="credentials.clientSecret" ng-required="requiresClientSecret">
</div>

<div class="control-group" ng-if="hasOwnerCredentials">
<label for="username" class="required">Username</label>

<input type="text" name="username" ng-model="credentials.username" required>
</div>

<div class="control-group" ng-if="hasOwnerCredentials">
<label for="password" class="required">Password</label>

<input type="password" name="password" ng-model="credentials.password" required>
</div>
</fieldset>
3 changes: 1 addition & 2 deletions app/views/parameter_fields.tmpl.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@
<div class="parameter-field" ng-repeat="definition in parameter.definitions" ng-show="parameter.isSelected(definition)">
<div repeatable="definition.repeat" repeatable-model="parameters.values[parameterName]">
<div class="control-group">
<label for="{{parameterName}}">
<span class="required" ng-if="definition.required">*</span>
<label for="{{parameterName}}" ng-class="{ required: definition.required }">
{{definition.displayName}}
</label>
<parameter-field name='parameterName' model='repeatableModel[$index]' definition='definition' ></parameter-field>
Expand Down
6 changes: 3 additions & 3 deletions app/views/security_schemes.tmpl.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ <h2>Authentication</h2>
<toggle-item heading="Anonymous"></toggle-item>
<toggle-item ng-repeat="(name, scheme) in schemes" heading="{{name}}">
<div ng-switch="scheme.type">
<basic-auth ng-switch-when="Basic Authentication" credentials='keychain[name]'></basic-auth>
<oauth1 ng-switch-when="OAuth 1.0" credentials='keychain[name]'></oauth1>
<oauth2 ng-switch-when="OAuth 2.0" credentials='keychain[name]'></oauth2>
<basic-auth ng-switch-when="Basic Authentication" scheme="scheme" credentials="keychain[name]"></basic-auth>
<oauth1 ng-switch-when="OAuth 1.0" scheme="scheme" credentials="keychain[name]"></oauth1>
<oauth2 ng-switch-when="OAuth 2.0" scheme="scheme" credentials="keychain[name]"></oauth2>
</div>
</toggle-item>
</toggle>
Expand Down
106 changes: 103 additions & 3 deletions dist/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
<head>
<title>api:Console</title>

<link rel="stylesheet" href="styles/app.css"/>
<!-- build:css({.tmp,app}) styles/app.css -->
<link rel="stylesheet" href="styles/app.css" type="text/css" />
<!-- endbuild -->

<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
Expand Down Expand Up @@ -41,9 +43,107 @@ <h1>Initialize RAML Console</h1>
<raml-console with-root-documentation></raml-console>
</div>

<script src="scripts/vendor.js"></script>
<!-- build:js({.tmp,app}) scripts/vendor.js -->
<script src="vendor/bower_components/vkbeautify/vkbeautify.js"></script>
<script src="vendor/bower_components/angular/angular.js"></script>
<script src="vendor/bower_components/angular-animate/angular-animate.js"></script>
<script src="vendor/bower_components/angular-sanitize/angular-sanitize.js"></script>
<script src="vendor/jquery.js"></script>
<script src="vendor/bower_components/raml-js-parser/dist/raml-parser.js"></script>
<script src="vendor/bower_components/crypto-js/rollups/hmac-sha1.js"></script>
<script src="vendor/bower_components/crypto-js/components/enc-base64.js"></script>
<script src="vendor/bower_components/showdown/src/showdown.js"></script>
<script src="vendor/bower_components/showdown/src/extensions/table.js"></script>
<script src="vendor/bower_components/codemirror/lib/codemirror.js"></script>
<script src="vendor/bower_components/codemirror/mode/xml/xml.js"></script>
<script src="vendor/bower_components/codemirror/mode/javascript/javascript.js"></script>
<!-- endbuild -->

<script src="scripts/app.js"></script>
<!-- build:js({.tmp,app}) scripts/app.js -->
<script src="scripts/inspector.js"></script>
<script src="scripts/inspector/method.js"></script>
<script src="scripts/inspector/parameterized_header.js"></script>
<script src="scripts/client.js"></script>
<script src="scripts/client/auth_strategies.js"></script>
<script src="scripts/client/auth_strategies/anonymous.js"></script>
<script src="scripts/client/auth_strategies/basic_auth.js"></script>
<script src="scripts/client/auth_strategies/oauth1.js"></script>
<script src="scripts/client/auth_strategies/oauth1/request_authorization.js"></script>
<script src="scripts/client/auth_strategies/oauth1/request_temporary_credentials.js"></script>
<script src="scripts/client/auth_strategies/oauth1/request_token_credentials.js"></script>
<script src="scripts/client/auth_strategies/oauth1/signer.js"></script>
<script src="scripts/client/auth_strategies/oauth1/signer/hmac.js"></script>
<script src="scripts/client/auth_strategies/oauth1/signer/plaintext.js"></script>
<script src="scripts/client/auth_strategies/oauth2.js"></script>
<script src="scripts/client/auth_strategies/oauth2/create_token.js"></script>
<script src="scripts/client/auth_strategies/oauth2/credentials_manager.js"></script>
<script src="scripts/client/auth_strategies/oauth2/grant.js"></script>
<script src="scripts/client/auth_strategies/oauth2/request_access_token.js"></script>
<script src="scripts/client/auth_strategies/oauth2/request_authorization.js"></script>
<script src="scripts/client/auth_strategies/oauth2/token.js"></script>
<script src="scripts/client/parameterized_string.js"></script>
<script src="scripts/client/path_builder.js"></script>
<script src="scripts/client/request.js"></script>
<script src="scripts/client/validator.js"></script>
<script src="scripts/controllers.js"></script>
<script src="scripts/controllers/body_documentation.js"></script>
<script src="scripts/controllers/documentation.js"></script>
<script src="scripts/controllers/named_parameters_documentation.js"></script>
<script src="scripts/controllers/raml_console.js"></script>
<script src="scripts/controllers/resource.js"></script>
<script src="scripts/controllers/tabset.js"></script>
<script src="scripts/controllers/toggle.js"></script>
<script src="scripts/controllers/try_it.js"></script>
<script src="scripts/controllers/try_it/body_content.js"></script>
<script src="scripts/controllers/try_it/body_type.js"></script>
<script src="scripts/controllers/try_it/context.js"></script>
<script src="scripts/controllers/try_it/named_parameter.js"></script>
<script src="scripts/controllers/try_it/named_parameters.js"></script>
<script src="scripts/directives.js"></script>
<script src="scripts/directives/api_resources.js"></script>
<script src="scripts/directives/basic_auth.js"></script>
<script src="scripts/directives/body_content.js"></script>
<script src="scripts/directives/body_documentation.js"></script>
<script src="scripts/directives/code_mirror.js"></script>
<script src="scripts/directives/collapsible.js"></script>
<script src="scripts/directives/documentation.js"></script>
<script src="scripts/directives/enum.js"></script>
<script src="scripts/directives/input.js"></script>
<script src="scripts/directives/markdown.js"></script>
<script src="scripts/directives/method.js"></script>
<script src="scripts/directives/named_parameters.js"></script>
<script src="scripts/directives/named_parameters_documentation.js"></script>
<script src="scripts/directives/oauth1.js"></script>
<script src="scripts/directives/oauth2.js"></script>
<script src="scripts/directives/parameter_field.js"></script>
<script src="scripts/directives/parameter_fields.js"></script>
<script src="scripts/directives/parameterized_parameter.js"></script>
<script src="scripts/directives/raml_console.js"></script>
<script src="scripts/directives/raml_console_initializer.js"></script>
<script src="scripts/directives/resource.js"></script>
<script src="scripts/directives/resource_documentation.js"></script>
<script src="scripts/directives/repeatable.js"></script>
<script src="scripts/directives/repeatable_add.js"></script>
<script src="scripts/directives/repeatable_remove.js"></script>
<script src="scripts/directives/responses.js"></script>
<script src="scripts/directives/root_documentation.js"></script>
<script src="scripts/directives/security_schemes.js"></script>
<script src="scripts/directives/tabs.js"></script>
<script src="scripts/directives/toggle.js"></script>
<script src="scripts/directives/try_it.js"></script>
<script src="scripts/directives/validated_input.js"></script>
<script src="scripts/filters.js"></script>
<script src="scripts/filters/name_from_parameterizable.js"></script>
<script src="scripts/filters/yes_no.js"></script>
<script src="scripts/services.js"></script>
<script src="scripts/services/config.js"></script>
<script src="scripts/services/data_store.js"></script>
<script src="scripts/services/raml_parser_wrapper.js"></script>
<script src="scripts/settings.js"></script>
<script src="scripts/utils.js"></script>
<script src="scripts/raml.js"></script>
<script src="scripts/raml_console.js"></script>
<!-- endbuild -->

<script>
RAML.Settings.proxy = '/proxy/';
Expand Down
Loading

0 comments on commit 4b59917

Please sign in to comment.