Have external login always make an API request to get the authorization URL
This makes the OIDC lookup lazy, ensuring that the rest of the registry and app continues working even if one OIDC provider goes down.
This commit is contained in:
parent
fda203e4d7
commit
a9791ea419
9 changed files with 128 additions and 49 deletions
|
@ -11,7 +11,9 @@ from peewee import IntegrityError
|
|||
|
||||
import features
|
||||
|
||||
from app import app, billing as stripe, authentication, avatar, user_analytics, all_queues
|
||||
from app import (app, billing as stripe, authentication, avatar, user_analytics, all_queues,
|
||||
oauth_login)
|
||||
|
||||
from auth import scopes
|
||||
from auth.auth_context import get_authenticated_user
|
||||
from auth.permissions import (AdministerOrganizationPermission, CreateRepositoryPermission,
|
||||
|
@ -24,11 +26,12 @@ from endpoints.api import (ApiResource, nickname, resource, validate_json_reques
|
|||
query_param, require_scope, format_date, show_if,
|
||||
require_fresh_login, path_param, define_json_response,
|
||||
RepositoryParamResource, page_support)
|
||||
from endpoints.exception import NotFound, InvalidToken
|
||||
from endpoints.exception import NotFound, InvalidToken, InvalidRequest, DownstreamIssue
|
||||
from endpoints.api.subscribe import subscribe
|
||||
from endpoints.common import common_login
|
||||
from endpoints.csrf import generate_csrf_token, OAUTH_CSRF_TOKEN_NAME
|
||||
from endpoints.decorators import anon_allowed
|
||||
from oauth.oidc import DiscoveryFailureException
|
||||
from util.useremails import (send_confirmation_email, send_recovery_email, send_change_email,
|
||||
send_password_changed, send_org_recovery_email)
|
||||
from util.names import parse_single_urn
|
||||
|
@ -692,14 +695,50 @@ class Signout(ApiResource):
|
|||
return {'success': True}
|
||||
|
||||
|
||||
@resource('/v1/externaltoken')
|
||||
@resource('/v1/externallogin/<service_id>')
|
||||
@internal_only
|
||||
class GenerateExternalToken(ApiResource):
|
||||
""" Resource for generating a token for external login. """
|
||||
@nickname('generateExternalLoginToken')
|
||||
def post(self):
|
||||
""" Generates a CSRF token explicitly for OIDC/OAuth-associated login. """
|
||||
return {'token': generate_csrf_token(OAUTH_CSRF_TOKEN_NAME)}
|
||||
class ExternalLoginInformation(ApiResource):
|
||||
""" Resource for both setting a token for external login and returning its authorization
|
||||
url.
|
||||
"""
|
||||
schemas = {
|
||||
'GetLogin': {
|
||||
'type': 'object',
|
||||
'description': 'Information required to an retrieve external login URL.',
|
||||
'required': [
|
||||
'kind',
|
||||
],
|
||||
'properties': {
|
||||
'kind': {
|
||||
'type': 'string',
|
||||
'description': 'The kind of URL',
|
||||
'enum': ['login', 'attach'],
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@nickname('retrieveExternalLoginAuthorizationUrl')
|
||||
@anon_allowed
|
||||
@validate_json_request('GetLogin')
|
||||
def post(self, service_id):
|
||||
""" Generates the auth URL and CSRF token explicitly for OIDC/OAuth-associated login. """
|
||||
login_service = oauth_login.get_service(service_id)
|
||||
if login_service is None:
|
||||
raise InvalidRequest()
|
||||
|
||||
csrf_token = generate_csrf_token(OAUTH_CSRF_TOKEN_NAME)
|
||||
kind = request.get_json()['kind']
|
||||
redirect_suffix = '/attach' if kind == 'attach' else ''
|
||||
|
||||
try:
|
||||
login_scopes = login_service.get_login_scopes()
|
||||
auth_url = login_service.get_auth_url(app.config, redirect_suffix, csrf_token, login_scopes)
|
||||
return {'auth_url': auth_url}
|
||||
except DiscoveryFailureException as dfe:
|
||||
logger.exception('Could not discovery OAuth endpoint information')
|
||||
raise DownstreamIssue(dfe.message)
|
||||
|
||||
|
||||
@resource('/v1/detachexternal/<service_id>')
|
||||
|
|
Reference in a new issue