| |
@@ -70,6 +70,7 @@
|
| |
EINVALIDTOK = 'Invalid or expired token. Please visit %s to get or '\
|
| |
'renew your API token.'\
|
| |
% urljoin(pagure_config['APP_URL'], 'settings#api-keys')
|
| |
+ EINVALIDOIDCTOK = 'Invalid or expired OIDC token'
|
| |
ENOISSUE = 'Issue not found'
|
| |
EISSUENOTALLOWED = 'You are not allowed to view this issue'
|
| |
EPULLREQUESTSDISABLED = 'Pull-Request have been deactivated for this '\
|
| |
@@ -162,7 +163,74 @@
|
| |
return jsonout
|
| |
|
| |
|
| |
- def api_login_required(acls=None):
|
| |
+ def check_oidc_token(scopes, optional=False):
|
| |
+ ''' Check if the provided oidc token has the required scopes
|
| |
+ and allow the user to access the desired enpoint.
|
| |
+ '''
|
| |
+ from pagure.ui.oidc_login import oidc
|
| |
+ valid = False
|
| |
+ if 'Authorization' in flask.request.headers:
|
| |
+ token = flask.request.headers.get("Authorization").strip()
|
| |
+ if token.startswith('Bearer '):
|
| |
+ token = token[len('Bearer '):].strip()
|
| |
+ valid = oidc.validate_token(token=token, scopes_required=scopes)
|
| |
+
|
| |
+ if valid is True:
|
| |
+ try:
|
| |
+ flask.g.fas_user = pagure.lib.get_user(
|
| |
+ flask.g.session, flask.g.oidc_token_info['sub'])
|
| |
+ flask.g.authenticated = True
|
| |
+ flask.g.fas_user.cla_done = True
|
| |
+ except pagure.exceptions.PagureException:
|
| |
+ output = {
|
| |
+ 'error_code': APIERROR.EDBERROR.name,
|
| |
+ 'error': APIERROR.EDBERROR.value}
|
| |
+ jsonout = flask.jsonify(output)
|
| |
+ jsonout.status_code = 404
|
| |
+ return jsonout
|
| |
+
|
| |
+ elif optional is True:
|
| |
+ return
|
| |
+
|
| |
+ else:
|
| |
+ output = {
|
| |
+ 'error_code': APIERROR.EINVALIDOIDCTOK.name,
|
| |
+ 'error': APIERROR.EINVALIDOIDCTOK.value}
|
| |
+ jsonout = flask.jsonify(output)
|
| |
+ jsonout.status_code = 401
|
| |
+ return jsonout
|
| |
+
|
| |
+
|
| |
+ def create_oidc_scopes(acls, kwargs):
|
| |
+ ''' Create the oidc scopes from the acls '''
|
| |
+ # Convert default acls to OIDC scopes
|
| |
+ # ie acl: create_issue becomes
|
| |
+ # https://pagure.io/oidc/create_issue
|
| |
+ scopes = []
|
| |
+ if acls is not None:
|
| |
+ scopes = [pagure_config.get('OIDC_SCOPES_BASENAME') + acl
|
| |
+ for acl in acls]
|
| |
+
|
| |
+ # Build the name of the scope in function of repo, username
|
| |
+ # or namespace specific api call.
|
| |
+ # https://pagure.io/oidc/create_issue(username/namespace/repo)
|
| |
+ repo = None
|
| |
+ if kwargs.get('repo'):
|
| |
+ repo = kwargs.get('repo')
|
| |
+ if kwargs.get('namespace'):
|
| |
+ repo = '{}/{}'.format(kwargs.get('namespace'), repo)
|
| |
+ if kwargs.get('username'):
|
| |
+ repo = '{}/{}'.format(kwargs.get('username'), repo)
|
| |
+
|
| |
+ if repo is not None:
|
| |
+ copy_scopes = list(scopes)
|
| |
+ for scope in copy_scopes:
|
| |
+ scopes.append(scope + '({})'.format(repo))
|
| |
+
|
| |
+ return scopes
|
| |
+
|
| |
+
|
| |
+ def api_login_required(acls=None, optional=False):
|
| |
''' Decorator used to indicate that authentication is required for some
|
| |
API endpoint.
|
| |
'''
|
| |
@@ -174,9 +242,20 @@
|
| |
def decorated_function(*args, **kwargs):
|
| |
''' Actually does the job with the arguments provided. '''
|
| |
|
| |
+ # First verify pagure's API token, if the token is not valid
|
| |
+ # then check if this is an OIDC token.
|
| |
response = check_api_acls(acls)
|
| |
- if response:
|
| |
- return response
|
| |
+ if response is not None:
|
| |
+ if pagure_config.get('OIDC_API_TOKEN', False):
|
| |
+
|
| |
+ scopes = create_oidc_scopes(acls, kwargs)
|
| |
+ oidc_response = check_oidc_token(scopes)
|
| |
+
|
| |
+ if oidc_response is not None:
|
| |
+ return oidc_response
|
| |
+ else:
|
| |
+ return response
|
| |
+
|
| |
return function(*args, **kwargs)
|
| |
|
| |
return decorated_function
|
| |
@@ -196,9 +275,18 @@
|
| |
def decorated_function(*args, **kwargs):
|
| |
''' Actually does the job with the arguments provided. '''
|
| |
|
| |
+ # First verify pagure's API token, if the token is not valid
|
| |
+ # then check if this is an OIDC token.
|
| |
response = check_api_acls(acls, optional=True)
|
| |
- if response:
|
| |
- return response
|
| |
+ if response is not None:
|
| |
+ if pagure_config.get('OIDC_API_TOKEN', False):
|
| |
+ scopes = ['openid']
|
| |
+ oidc_response = check_oidc_token(scopes, optional=True)
|
| |
+ if oidc_response is not None:
|
| |
+ return oidc_response
|
| |
+ else:
|
| |
+ return response
|
| |
+
|
| |
return function(*args, **kwargs)
|
| |
|
| |
return decorated_function
|
| |
Add support to use OIDC token for pagure's API.