def __init__(self): self._jwt_validator = TokenValidator( settings.COGNITO_AWS_REGION, settings.COGNITO_USER_POOL, settings.COGNITO_AUDIENCE) super().__init__()
def get(self, request, format=None, **kwargs): if settings.COGNITO_ENABLED is False: body = {"message": "page not found"} return Response(body, status=status.HTTP_404_NOT_FOUND) else: body = {"message": "page found"} code = request.query_params.get("code", None) if code is None: return Response({"message": "Not Found"}, status=status.HTTP_404_NOT_FOUND) redirect_uri = request.build_absolute_uri('?') redirect_uri = redirect_uri.rstrip('/') token_resp = requests.post( "https://" + settings.COGNITO_DOMAIN + "/oauth2/token", data={ "grant_type": "authorization_code", "client_id": settings.COGNITO_AUDIENCE, "code": code, "scope": "openid", "redirect_uri": redirect_uri }) try: aws = token_resp.json() response = {"aws": aws} if token_resp.status_code != 200: logger.error(f"AWS returned {aws}") return Response( { "aws error": aws, "status": token_resp.status_code }, status=token_resp.status_code) id_token = aws['id_token'] validator = TokenValidator(settings.COGNITO_AWS_REGION, settings.COGNITO_USER_POOL, settings.COGNITO_AUDIENCE) jwt_payload = validator.validate(id_token) response.update({"jwt": jwt_payload}) user = User.objects.get_or_create_for_cognito(jwt_payload) response.update({"user": user.username}) # Upgrade the connection to a session login(request, user) # Use this to get id_token for debug #return Response({"id_token": id_token}) return redirect("/projects") except TokenError as e: return Response({"message": "invalid token"}, status=status.HTTP_404_NOT_FOUND)
class JSONWebTokenAuthentication(BaseAuthentication): """Token based authentication using the JSON Web Token standard.""" def __init__(self): self._jwt_validator = TokenValidator(settings.COGNITO_AWS_REGION, settings.COGNITO_USER_POOL, settings.COGNITO_AUDIENCE) super().__init__() def authenticate(self, request): """Entrypoint for Django Rest Framework""" jwt_token = self.get_jwt_token(request) if jwt_token is None: return None # Authenticate token try: jwt_payload = self._jwt_validator.validate(jwt_token) except TokenError: raise exceptions.AuthenticationFailed() user = USER_MODEL.objects.get_or_create_for_cognito(jwt_payload) return (user, jwt_token) def get_jwt_token(self, request): auth = get_authorization_header(request).split() if not auth or smart_text(auth[0].lower()) != 'bearer': return None if len(auth) == 1: msg = _('Invalid Authorization header. No credentials provided.') raise exceptions.AuthenticationFailed(msg) elif len(auth) > 2: msg = _('Invalid Authorization header. Credentials string ' 'should not contain spaces.') raise exceptions.AuthenticationFailed(msg) return auth[1] def authenticate_header(self, request): """ Method required by the DRF in order to return 401 responses for authentication failures, instead of 403. More details in https://www.django-rest-framework.org/api-guide/authentication/#custom-authentication. """ return 'Bearer: api'
class JSONWebTokenAuthentication(BaseAuthentication): """Token based authentication using the JSON Web Token standard.""" def __init__(self): self._jwt_validator = TokenValidator( settings.COGNITO_AWS_REGION, settings.COGNITO_USER_POOL, settings.COGNITO_AUDIENCE) super().__init__() def authenticate(self, request): """Entrypoint for Django Rest Framework""" jwt_token = self.get_jwt_token(request) if jwt_token is None: return None # Authenticate token try: jwt_payload = self._jwt_validator.validate(jwt_token) except TokenError: raise exceptions.AuthenticationFailed() get_or_create_for_cognito_code = '{function_name}(jwt_payload, request)'.format( function_name=settings.COGNITO_GET_USER_OR_CREATE_FUNCTION, jwt_payload=jwt_payload, request=request) user = eval(get_or_create_for_cognito_code) return (user, jwt_token) def get_jwt_token(self, request): auth = get_authorization_header(request).split() if not auth or smart_text(auth[0].lower()) != settings.COGNITO_AUTH_HEADER: return None if len(auth) == 1: msg = _('Invalid Authorization header. No credentials provided.') raise exceptions.AuthenticationFailed(msg) elif len(auth) > 2: msg = _('Invalid Authorization header. Credentials string ' 'should not contain spaces.') raise exceptions.AuthenticationFailed(msg) return auth[1]
def get_token_validator(self): return TokenValidator( settings.COGNITO_AWS_REGION, settings.COGNITO_USER_POOL, settings.COGNITO_AUDIENCE, )