diff --git a/data/model/oauth.py b/data/model/oauth.py index 51bfc053e..f6bbed992 100644 --- a/data/model/oauth.py +++ b/data/model/oauth.py @@ -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) diff --git a/endpoints/common.py b/endpoints/common.py index 6a221bd5c..5de16c034 100644 --- a/endpoints/common.py +++ b/endpoints/common.py @@ -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', ''), diff --git a/endpoints/web.py b/endpoints/web.py index b355f5ec9..b2fffd811 100644 --- a/endpoints/web.py +++ b/endpoints/web.py @@ -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') diff --git a/static/css/quay.css b/static/css/quay.css index 25934010b..7e44e3a59 100644 --- a/static/css/quay.css +++ b/static/css/quay.css @@ -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; } \ No newline at end of file diff --git a/static/js/app.js b/static/js/app.js index 7c00c5831..4351c6166 100644 --- a/static/js/app.js +++ b/static/js/app.js @@ -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; diff --git a/static/js/controllers.js b/static/js/controllers.js index 07041ae7a..62254984b 100644 --- a/static/js/controllers.js +++ b/static/js/controllers.js @@ -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({}); }; diff --git a/static/partials/manage-application.html b/static/partials/manage-application.html index aaae745b8..7d0bb1bfb 100644 --- a/static/partials/manage-application.html +++ b/static/partials/manage-application.html @@ -30,6 +30,7 @@ @@ -91,6 +92,30 @@ + +
+
+ Click the button below to generate a new OAuth 2 Access Token. +
+ +
+ Note: The generated token will act on behalf of user + {{ user.username }} +
+ + + + + +
+ + + Generate Access Token + +
+
diff --git a/templates/base.html b/templates/base.html index 317a3683e..4824848fc 100644 --- a/templates/base.html +++ b/templates/base.html @@ -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() }}';