Esempio n. 1
0
def get_token_auth_header():
    auth = request.headers.get('Authorization')
    if not auth:
        raise AuthError({
            'code': 'authorization_header_missing',
            'description': 'Authorization header is expected.'
        }, 401)

    parts = auth.split()
    if parts[0].lower() != 'bearer':
        raise AuthError({
            'code': 'invalid_header',
            'description': 'Authorization header must start with "Bearer".'
        }, 401)

    elif len(parts) == 1:
        raise AuthError({
            'code': 'invalid_header',
            'description': 'Token not found.'
        }, 401)

    elif len(parts) > 2:
        raise AuthError({
            'code': 'invalid_header',
            'description': 'Authorization header must be bearer token.'
        }, 401)

    token = parts[1]
    return token
Esempio n. 2
0
def _check_permissions(permission, payload):
    if 'permissions' not in payload:
        raise AuthError(
            {
                'code': 'invalid_claims',
                'description': 'Permissions not included in JWT'
            }, 400)

    # For unit testing purposes
    # The key-value pair of 'test_permission' is included in the request
    # headers when the request is identified as an unit test request;
    # permissions of the routes then can be tested via the manipulations of
    # the permissions list in the payload
    if 'test_permission' in request.headers:
        payload['permissions'] = [request.headers['test_permission']]

    if isinstance(permission, list) and len(permission) > 1:
        if not set(permission).intersection(payload['permissions']):
            raise AuthError(
                {
                    'code': 'unauthorized',
                    'description': 'Permission not found'
                }, 401)
    else:
        if permission not in payload['permissions']:
            raise AuthError(
                {
                    'code': 'unauthorized',
                    'description': 'Permission not found'
                }, 401)

    return True
Esempio n. 3
0
def verify_decode_jwt(token):
    jsonurl = urlopen(f'https://{AUTH0_DOMAIN}/.well-known/jwks.json')
    jwks = json.loads(jsonurl.read())
    unverified_header = jwt.get_unverified_header(token)
    rsa_key = {}

    if 'kid' not in unverified_header:
        raise AuthError(
            {
                'code': 'invalid_header',
                'description': 'Authorization malformed.'
            }, 401)

    for key in jwks['keys']:
        if key['kid'] == unverified_header['kid']:
            rsa_key = {
                'kty': key['kty'],
                'kid': key['kid'],
                'use': key['use'],
                'n': key['n'],
                'e': key['e']
            }

    if not rsa_key:
        raise AuthError(
            {
                'code': 'invalid_header',
                'description': 'Unable to find the appropriate key.'
            }, 400)

    try:
        payload = jwt.decode(token,
                             rsa_key,
                             algorithms=ALGORITHMS,
                             audience=API_AUDIENCE,
                             issuer='https://' + AUTH0_DOMAIN + '/')

        return payload

    except jwt.ExpiredSignatureError:
        raise AuthError(
            {
                'code': 'token_expired',
                'description': 'Token expired.'
            }, 401)

    except jwt.JWTClaimsError:
        raise AuthError(
            {
                'code':
                'invalid_claims',
                'description':
                ('Incorrect claims. Please, check the audience and issuer.')
            }, 401)
    except Exception:
        raise AuthError(
            {
                'code': 'invalid_header',
                'description': 'Unable to parse authentication token.'
            }, 400)
Esempio n. 4
0
def check_permissions(permission, payload):
    permissions = payload.get("permissions")
    if permissions is None:
        raise AuthError({
            "code": "invalid_payload",
            "description": "permission missing in payload"
            }, 401)

    if permission not in permissions:
        raise AuthError({
            "code": "invalid_payload",
            "description": "Permission not found."
            }, 401)

    return True
Esempio n. 5
0
def check_permissions(permission, payload):
    if 'permissions' not in payload:
        raise AuthError(
            {
                'code': 'invalid_claims',
                'description': 'Permissions not included in JWT.'
            }, 400)

    if permission not in payload['permissions']:
        raise AuthError(
            {
                'code': 'unauthorized',
                'description': 'Permission not found.'
            }, 403)

    return True
Esempio n. 6
0
        def wrapper(*args, **kwargs):
            token = _get_token_auth_header()
            try:
                payload = _verify_decode_jwt(token)
            except BaseException:
                raise AuthError(
                    {
                        "code": "jwt_decode_error",
                        "description": "Error decoding JWT"
                    }, 401)

            _check_permissions(permission, payload)

            return f(payload, *args, **kwargs)
Esempio n. 7
0
def validate_response(response):
    """validate_response
    """
    error_suffix = " response={!r}".format(response)
    if response.status_code in (status.HTTP_401_UNAUTHORIZED,
                                status.HTTP_403_FORBIDDEN):
        raise AuthError("operation=auth_error," + error_suffix, response)
    if response.status_code == status.HTTP_404_NOT_FOUND:
        raise NotFoundError("operation=not_found_error," + error_suffix,
                            response)
    if status.is_client_error(code=response.status_code):
        raise ClientError("operation=client_error," + error_suffix, response)
    if status.is_server_error(code=response.status_code):
        raise ServerError("operation=server_error," + error_suffix, response)
Esempio n. 8
0
def verify_decode_jwt(token):
    jsonurl = urlopen("https://"+AUTH0_DOMAIN+"/.well-known/jwks.json")
    jwks = json.loads(jsonurl.read())
    unverified_header = jwt.get_unverified_header(token)
    rsa_key = {}
    for key in jwks["keys"]:
        if key["kid"] == unverified_header["kid"]:
            rsa_key = {
                "kty": key["kty"],
                "kid": key["kid"],
                "use": key["use"],
                "n": key["n"],
                "e": key["e"]
            }
    if rsa_key:
        try:
            payload = jwt.decode(
                token,
                rsa_key,
                algorithms=ALGORITHMS,
                audience=API_AUDIENCE,
                issuer="https://"+AUTH0_DOMAIN+"/"
            )
            return payload

        except jwt.ExpiredSignatureError:
            raise AuthError("token is expired", 401)
        except jwt.JWTClaimsError:
            raise AuthError("invalid_claims", 401)
        except Exception as e:
            raise AuthError({"code": "invalid_header",
                            "description":
                                "Unable to parse authentication"
                                " token."}, 401)

    raise AuthError("Unable to find appropriate key", 401)
Esempio n. 9
0
def _get_token_auth_header():

    #############################################################
    #
    # TODO This is not the correct way to implement security,
    # I'd imagine that one should be passing the access key
    # between the front end and back end through the request
    # header. However, I have spend two weeks trying different
    # ways and still couldn't come up with a feasible solution.
    # Since this part is not critical for the capstone, I have
    # implemented this temporary solution to force the
    # application to work, and I will try to figure it out in
    # a later time.
    #
    # This implementation does not grab the access token from
    # the request header, but check the host url from the request
    # header and see if it's the same as the 'API Audience' set
    # up using the Auth0 API UI. If it is, grab the access key
    # stored in the Flask session when the application is going
    # through the callback code after logging in. And all the
    # steps after that follow strictly to how we are taught.
    #
    ###############################################################

    if request.headers['HOST'] in api_audience:
        # Postman test work-around
        if 'POSTMAN_TOKEN' not in request.headers:
            # Unit test work-around
            if 'test_permission' in request.headers:
                return test_token

            if conf_access_key in session:
                access_key = session[conf_access_key]
                return access_key['access']
            else:
                raise AuthError(
                    {
                        "code": "authorization_required",
                        "description": "User is not logged in"
                    }, 401)

    if 'Authorization' not in request.headers:
        raise AuthError(
            {
                "code": "authorization_required",
                "description": "Authorization is expected in header"
            }, 401)

    # "Authorization": "bearer <<token>>"
    auth_header = request.headers['Authorization']

    header_parts = auth_header.split(' ')

    if len(header_parts) != 2 or header_parts[0].lower() != 'bearer':
        raise AuthError(
            {
                "code": "invalid_token",
                "description":
                "Mendatory authorization requires 'bearer' token"
            }, 401)

    return header_parts[1]
Esempio n. 10
0
def _verify_decode_jwt(token):
    # Get the public key from Auth0
    jsonurl = urlopen(f'https://{auth0_domain}/.well-known/jwks.json')
    jwks = json.loads(jsonurl.read())

    # Get the data in the header
    unverified_header = jwt.get_unverified_header(token)

    # Choose the key
    rsa_key = {}
    if 'kid' not in unverified_header:
        raise AuthError(
            {
                'code': 'invalid_header',
                'description': 'Authorization malformed'
            }, 401)

    for key in jwks['keys']:
        if key['kid'] == unverified_header['kid']:
            rsa_key = {
                'kty': key['kty'],
                'kid': key['kid'],
                'use': key['use'],
                'n': key['n'],
                'e': key['e']
            }

    # Finally, verify!!!
    if rsa_key:
        try:
            # USE THE KEY TO VALIDATE THE JWT
            payload = jwt.decode(token,
                                 rsa_key,
                                 algorithms=algorithms,
                                 audience=api_audience,
                                 issuer=(f'https://{auth0_domain}/'))

            return payload

        except jwt.ExpiredSignatureError:
            raise AuthError(
                {
                    'code': 'token_expired',
                    'description': 'Token expired'
                }, 401)

        except jwt.JWTClaimsError:
            raise AuthError(
                {
                    'code':
                    'invalid_claims',
                    'description':
                    'Incorrect claims. Please check the audience and issuer'
                }, 401)
        except Exception:
            raise AuthError(
                {
                    'code': 'invalid_header',
                    'description': 'Unable to parse authentication token'
                }, 400)
    raise AuthError(
        {
            'code': 'invalid_header',
            'description': 'Unable to find the appropriate key'
        }, 400)