Add ability to one-click generate an authorization access token in the applications panel

This commit is contained in:
Joseph Schorr 2014-11-17 14:54:07 -05:00
parent ccc16fd6f4
commit 58ca76239b
8 changed files with 66 additions and 4 deletions

View file

@ -9,6 +9,7 @@ from data.database import (OAuthApplication, OAuthAuthorizationCode, OAuthAccess
random_string_generator)
from data.model.legacy import get_user
from auth import scopes
from flask import render_template
logger = logging.getLogger(__name__)
@ -154,6 +155,7 @@ class DatabaseAuthorizationProvider(AuthorizationProvider):
def get_token_response(self, response_type, client_id, redirect_uri, **params):
# Ensure proper response_type
if response_type != 'token':
err = 'unsupported_response_type'
@ -161,7 +163,7 @@ class DatabaseAuthorizationProvider(AuthorizationProvider):
# Check redirect URI
is_valid_redirect_uri = self.validate_redirect_uri(client_id, redirect_uri)
if not is_valid_redirect_uri:
if redirect_uri != 'display' and not is_valid_redirect_uri:
return self._invalid_redirect_uri_response()
# Check conditions
@ -196,6 +198,10 @@ class DatabaseAuthorizationProvider(AuthorizationProvider):
url = utils.build_url(redirect_uri, params)
url += '#access_token=%s&token_type=%s&expires_in=%s' % (access_token, token_type, expires_in)
if redirect_uri == 'display':
return self._make_response(
render_template("message.html", message="Access Token: " + access_token))
return self._make_response(headers={'Location': url}, status_code=302)

View file

@ -198,6 +198,7 @@ def render_page_template(name, **kwargs):
feature_set=json.dumps(features.get_features()),
config_set=json.dumps(getFrontendVisibleConfig(app.config)),
oauth_set=json.dumps(get_oauth_config()),
scope_set=json.dumps(scopes.ALL_SCOPES),
mixpanel_key=app.config.get('MIXPANEL_KEY', ''),
google_analytics_key=app.config.get('GOOGLE_ANALYTICS_KEY', ''),
sentry_public_dsn=app.config.get('SENTRY_PUBLIC_DSN', ''),

View file

@ -376,7 +376,7 @@ def request_authorization_code():
if (not current_user.is_authenticated() or
not provider.validate_has_scopes(client_id, current_user.db_user().username, scope)):
if not provider.validate_redirect_uri(client_id, redirect_uri):
if redirect_uri != 'display' and not provider.validate_redirect_uri(client_id, redirect_uri):
current_app = provider.get_application_for_client_id(client_id)
if not current_app:
abort(404)
@ -416,7 +416,6 @@ def request_authorization_code():
else:
return provider.get_authorization_code(response_type, client_id, redirect_uri, scope=scope)
@web.route('/oauth/access_token', methods=['POST'])
@no_cache
@param_required('grant_type')

View file

@ -4871,4 +4871,12 @@ i.slack-icon {
#startTriggerDialog #runForm .field-title {
width: 120px;
padding-right: 10px;
}
#gen-token table {
margin: 10px;
}
#gen-token input[type="checkbox"] {
margin-right: 10px;
}

View file

@ -1711,6 +1711,12 @@ quayApp = angular.module('quay', quayDependencies, function($provide, cfpLoading
return notificationService;
}]);
$provide.factory('OAuthService', ['$location', 'Config', function($location, Config) {
var oauthService = {};
oauthService.SCOPES = window.__auth_scopes;
return oauthService;
}]);
$provide.factory('KeyService', ['$location', 'Config', function($location, Config) {
var keyService = {}
var oauth = window.__oauth;

View file

@ -2676,12 +2676,28 @@ function OrgMemberLogsCtrl($scope, $routeParams, $rootScope, $timeout, Restangul
}
function ManageApplicationCtrl($scope, $routeParams, $rootScope, $location, $timeout, ApiService) {
function ManageApplicationCtrl($scope, $routeParams, $rootScope, $location, $timeout, OAuthService, ApiService, UserService, Config) {
var orgname = $routeParams.orgname;
var clientId = $routeParams.clientid;
$scope.Config = Config;
$scope.OAuthService = OAuthService;
$scope.updating = false;
$scope.genScopes = {};
UserService.updateUserIn($scope);
$scope.getScopes = function(scopes) {
var checked = [];
for (var scopeName in scopes) {
if (scopes.hasOwnProperty(scopeName) && scopes[scopeName]) {
checked.push(scopeName);
}
}
return checked;
};
$scope.askResetClientSecret = function() {
$('#resetSecretModal').modal({});
};

View file

@ -30,6 +30,7 @@
<ul class="nav nav-pills nav-stacked">
<li class="active"><a href="javascript:void(0)" data-toggle="tab" data-target="#settings">Settings</a></li>
<li><a href="javascript:void(0)" data-toggle="tab" data-target="#oauth">OAuth Information</a></li>
<li><a href="javascript:void(0)" data-toggle="tab" data-target="#gen-token">Generate Token</a></li>
<li><a href="javascript:void(0)" data-toggle="tab" data-target="#delete">Delete Application</a></li>
</ul>
</div>
@ -91,6 +92,30 @@
</div>
</div>
<!-- Generate Token tab -->
<div id="gen-token" class="tab-pane">
<div style="margin-bottom: 20px">
Click the button below to generate a new <a href="http://tools.ietf.org/html/rfc6749#section-1.4" target="_new">OAuth 2 Access Token</a>.
</div>
<div style="margin-bottom: 20px">
<strong>Note:</strong> The generated token will act on behalf of user <img src="//www.gravatar.com/avatar/{{ user.gravatar }}?s=16&d=identicon" style="margin-left: 6px; margin-right: 4px;">
{{ user.username }}
</div>
<table>
<tr ng-repeat="(scopeName, scopeInfo) in OAuthService.SCOPES">
<td><label onclick="event.stopPropagation()"><input type="checkbox" value="scopeInfo[0]" ng-model="genScopes[scopeName]">{{ scopeInfo[3] }}</label></td>
</tr>
</table>
<a class="btn btn-success"
href="{{ Config.getUrl('/oauth/authorize?response_type=token&client_id=' + application.client_id + '&scope=' + getScopes(genScopes).join(',') + '&redirect_uri=display') }}"
ng-disabled="!getScopes(genScopes).length" target="_blank">
Generate Access Token
</a>
</div>
<!-- OAuth tab -->
<div id="oauth" class="tab-pane">
<table style="margin-top: 20px;">

View file

@ -45,6 +45,7 @@
window.__features = {{ feature_set|safe }};
window.__config = {{ config_set|safe }};
window.__oauth = {{ oauth_set|safe }};
window.__auth_scopes = {{ scope_set|safe }};
window.__token = '{{ csrf_token() }}';
</script>