Ejemplo n.º 1
0
    def test_validate_aud(self):
        id_token = jwt.encode({'alg': 'HS256'}, {'aud': 'foo'}, 'k')
        claims_options = {
            'aud': {
                'essential': True,
                'value': 'foo'
            }
        }
        claims = jwt.decode(id_token, 'k', claims_options=claims_options)
        claims.validate()

        claims.options = {
            'aud': {'values': ['bar']}
        }
        self.assertRaises(
            errors.InvalidClaimError,
            claims.validate
        )

        id_token = jwt.encode({'alg': 'HS256'}, {'aud': ['foo', 'bar']}, 'k')
        claims = jwt.decode(id_token, 'k', claims_options=claims_options)
        claims.validate()
        # no validate
        claims.options = {'aud': {'values': []}}
        claims.validate()
Ejemplo n.º 2
0
def authorize():
    """ 
  @todo move this into login()? change url redirect on twitch for /login
  @todo better error handling, redirect to an error page with better troubleshooting/contact admin 
  @todo Cache the keys for X amount of time
  @todo Better nonce check? could someone pass their own nonce to defeat the condition check? !=? ==?
  """
    # Send user back to login if no nonce is set (shouldn't access /authorize directly)
    #if not session.get('OIDC_nonce'):
    #  return redirect(url_force('login'))

    # Make sure we received an auth code before requesting an access token
    if not request.values.get('code'):
        return "Invalid response during OpenID exchange with Twitch. (missing auth code)"
    else:
        token = oauth.twitch.authorize_access_token()
        if (token.get('nonce') != session.get('OIDC_nonce')):
            return "Unexpected response during OpenID exchange with Twitch. (mismatched nonce)"
        try:
            # Validate the ID Token by decoding it, exception raised if it fails
            jwt.decode(token.get('id_token'), twitch.get_oauth_keys())
        except jwt.BadSignatureError:
            return "Unexpected response during OpenID exchange with Twitch. (invalid id token)"
        claims = oauth.twitch.parse_id_token(token)
        # Confirm we're the audience for this ID Token
        if (claims.get('aud') != current_app.config.get('TWITCH_CLIENT_ID')):
            return "Unexpected response during OpenID exchange with Twitch. (mismatched audience)"
        # Oof! Pass the information on to the handler
        return handle_authorize(token, claims)
Ejemplo n.º 3
0
    def test_validate_exp(self):
        id_token = jwt.encode({'alg': 'HS256'}, {'exp': 'invalid'}, 'k')
        claims = jwt.decode(id_token, 'k')
        self.assertRaises(errors.InvalidClaimError, claims.validate)

        id_token = jwt.encode({'alg': 'HS256'}, {'exp': 1234}, 'k')
        claims = jwt.decode(id_token, 'k')
        self.assertRaises(errors.ExpiredTokenError, claims.validate)
Ejemplo n.º 4
0
    def test_validate_nbf(self):
        id_token = jwt.encode({'alg': 'HS256'}, {'nbf': 'invalid'}, 'k')
        claims = jwt.decode(id_token, 'k')
        self.assertRaises(errors.InvalidClaimError, claims.validate)

        id_token = jwt.encode({'alg': 'HS256'}, {'nbf': 1234}, 'k')
        claims = jwt.decode(id_token, 'k')
        claims.validate()

        id_token = jwt.encode({'alg': 'HS256'}, {'nbf': 1234}, 'k')
        claims = jwt.decode(id_token, 'k')
        self.assertRaises(errors.InvalidTokenError, claims.validate, 123)
Ejemplo n.º 5
0
 def decode_auth_token(self, auth_token, jwks=None):
     """
     Decodes the auth token
     :param auth_token:
     :return: integer|string
     """
     try:
         if jwks:
             payload = jwt.decode(auth_token, jwks)
         else:
             payload = jwt.decode(auth_token, self.public_key())
         return payload
     except:
         LOGGER.exception('token is invalid', exc_info=True)
         raise Exception('token is invalid')
Ejemplo n.º 6
0
    def valide_token(self, token: str):
        """validate token string, return a parsed token if valid, return None if not valid
        :return tuple (is_valid -> bool, id_token or None)
        """
        try:
            if "https://accounts.google.com" in self.metadata_url:
                # google's certs would change from time to time, let's refetch it before every try
                self.fetch_jwk()
            token = jwt.decode(token, self.jwk)
        except ValueError as e:
            if str(e) == 'Invalid JWK kid':
                logger.info(
                    'This token cannot be decoded with current provider, will try another provider if available.'
                )
                return None, None
            else:
                raise e

        try:
            token.validate()
            return True, token
        except ExpiredTokenError as e:
            logger.info('Auth header expired, %s', e)
            return True, None
        except JoseError as e:
            logger.debug('Jose error: %s', e)
            report()
            return None, None
Ejemplo n.º 7
0
def parse_id_token(remote,
                   id_token,
                   claims_options,
                   access_token=None,
                   nonce=None):
    """Parse UserInfo from id_token."""
    def load_key(header, payload):
        jwk_set = remote.fetch_jwk_set()
        try:
            return jwk.loads(jwk_set, header.get('kid'))
        except ValueError:
            jwk_set = remote.fetch_jwk_set(force=True)
            return jwk.loads(jwk_set, header.get('kid'))

    claims_params = dict(
        nonce=nonce,
        client_id=remote.client_id,
    )
    if access_token:
        claims_params['access_token'] = access_token
        claims_cls = CodeIDToken
    else:
        claims_cls = ImplicitIDToken
    claims = jwt.decode(
        id_token,
        key=load_key,
        claims_cls=claims_cls,
        claims_options=claims_options,
        claims_params=claims_params,
    )
    claims.validate(leeway=120)
    return UserInfo(claims)
Ejemplo n.º 8
0
def get_jwt():
    """
    Get Authorization token
    and validate its signature against the application's secret key.
    """
    expected_errors = {
        KeyError: 'Wrong JWT payload structure',
        TypeError: '<SECRET_KEY> is missing',
        BadSignatureError: 'Failed to decode JWT with provided key',
        DecodeError: 'Wrong JWT structure'
    }

    token = get_auth_token()

    try:
        credentials = jwt.decode(token, current_app.config['SECRET_KEY'])
        client_id = credentials['client_id']
        client_secret = credentials['client_secret']
        tenant_id = credentials['tenant_id']
        return {
            'client_id': client_id,
            'client_secret': client_secret,
            'tenant_id': tenant_id
        }
    except tuple(expected_errors) as error:
        message = expected_errors[error.__class__]
        raise AuthorizationError(message)
Ejemplo n.º 9
0
async def validate_passport(passport: Dict) -> JWTClaims:
    """Decode a passport and validate its contents."""
    LOG.debug("Validating passport.")

    # Passports from `get_ga4gh_controlled()` will be of form
    # passport[0] -> encoded passport (JWT)
    # passport[1] -> unverified decoded header (contains `jku`)
    # Passports from `get_bona_fide_status()` will be of form
    # passport[0] -> encoded passport (JWT)
    # passport[1] -> unverified decoded header (contains `jku`)
    # passport[2] -> unverified decoded payload

    # JWT decoding and validation settings
    # The `aud` claim will be ignored, because Beacon has no prior knowledge
    # as to where the token has originated from, and is therefore unable to
    # verify the intended audience. Other claims will be validated as per usual.
    claims_options = {"aud": {"essential": False}}

    # Attempt to decode the token and validate its contents
    # None of the exceptions are fatal, and will not raise an exception
    # Because even if the validation of one passport fails, the query
    # Should still continue in case other passports are valid
    try:
        # Get JWK for this passport from a third party provider
        # The JWK will be requested from a URL that is given in the `jku` claim in the header
        passport_key = await get_jwk(passport[1].get("jku"))
        # Decode the JWT using public key
        decoded_passport = jwt.decode(passport[0], passport_key, claims_options=claims_options)
        # Validate the JWT signature
        decoded_passport.validate()
        # Return decoded and validated payload contents
        return decoded_passport
    except Exception as e:
        LOG.error(f"Something went wrong when processing JWT tokens: {e}")
Ejemplo n.º 10
0
def get_jwt(access_token):
    from authlib.jose import jwt
    public_key = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyi7yZQmSCcMjcLxz+/qZe8eTzqcesfWJ71soc80/Bw0ccd9Oftk6HJsdSa86nXPlcbvS/eM2+u5o0MHZNjk0f04sc8KO+U0HWLTrpVP8mcG5VCL51vGlrIvv6Mvb+id0PZxqVP8e+Pp1z1lL7QJLyjWgx6XMr53S9b8Ek2a/TTqaWQTrx/xm7pLsN8UGOqi37vsHt0MOdWqx9Y7K87PIxDFky7z0dxdB0/pDknt7o38cUnQmh46xcuZbBCNu9RmozZ0s4mSU7a4d8qiM41SY8GQoz3NyUpALgdnqZ6jSgnxvZql1sLmQJhMeLYRkkDDbKNQLdxmG3Q4mGDQ1vE1QlwIDAQAB"
    key = '-----BEGIN PUBLIC KEY-----\n' + public_key + '\n-----END PUBLIC KEY-----'
    key_binary = key.encode('ascii')
    claims = jwt.decode(access_token, key_binary)
    return claims
def test_health_call_success(route, client, avotx_api_request, valid_jwt):
    app = client.application

    avotx_api_request.return_value = avotx_api_response(HTTPStatus.OK)

    response = client.post(route, headers=headers(valid_jwt))

    expected_url = f"{app.config['AVOTX_URL']}/api/v1/user/me"

    expected_headers = {
        'User-Agent': app.config['CTR_USER_AGENT'],
        'X-OTX-API-KEY': (jwt.decode(valid_jwt,
                                     app.config['SECRET_KEY'])['key']),
    }

    expected_params = {}

    avotx_api_request.assert_called_once_with(expected_url,
                                              headers=expected_headers,
                                              params=expected_params)

    expected_payload = {'data': {'status': 'ok'}}

    assert response.status_code == HTTPStatus.OK
    assert response.get_json() == expected_payload
Ejemplo n.º 12
0
async def mark_ticket(request):
    """call ticket op to handle this handler only make authenticate disappear for provider"""
    # verify jwt for callback url
    token = request.query_params.get('token')
    ticket_id = request.path_params['ticket_id']

    try:
        payload = jwt.decode(token, config.SESSION_SECRET_KEY)
        logger.debug(f'recieved callback req: {payload}')
        assert payload['ticket_id'] == ticket_id
    except (jwterrors.BadSignatureError, AssertionError):
        raise ApiError(ApiErrors.parameter_validation_failed, description="token error")
    ticket = await Ticket.get(ticket_id)
    if not ticket:
        raise ApiError(ApiErrors.not_found, description=f"ticket {ticket_id} not found!")

    try:
        data = await request.json()
        assert 'execution_status' in data, "mark body fields error"
        ticket.annotate(execution_status=data["execution_status"], final_exec_status=True)
        logger.debug(f"ticket annotation: {ticket.annotation}")
        # add notification to ticket mark action
        await ticket.notify(TicketPhase.MARK)
        await ticket.save()
    except (RuntimeError, AssertionError) as e:
        raise ApiError(ApiErrors.parameter_validation_failed, description=f'decode mark body error: {str(e)}')
    return dict(msg='Success')
Ejemplo n.º 13
0
def extract_auth_info(auth_token):
    try:
        claims = jwt.decode(auth_token, get_public_key())
    except (BadSignatureError, DecodeError):
        return None

    return dict(claims)
Ejemplo n.º 14
0
 def _parse_id_token(self, token_data, nonce):
     id_token = token_data['id_token']
     claims_params = {
         'nonce': nonce,
         'client_id': self.oidc_settings['client_id']
     }
     if 'access_token' in token_data:
         claims_params['access_token'] = token_data['access_token']
         claims_cls = CodeIDToken
     else:
         claims_cls = ImplicitIDToken
     # XXX: should we allow extra claims to be specified in the settings?
     claims_options = {'iss': {'values': [self.oidc_settings['issuer']]}}
     claims = jwt.decode(
         id_token,
         key=self._load_jwk,
         claims_cls=claims_cls,
         claims_options=claims_options,
         claims_params=claims_params,
     )
     claims.validate(leeway=120)
     info = UserInfo(claims)
     for key in INTERNAL_FIELDS:
         info.pop(key, None)
     return info
Ejemplo n.º 15
0
def test_app(context, app):
    client_id = 'baa448a8-205c-4faa-a048-a10e4b32a136'
    client_secret = 'joWgziYLap3eKDL6Gk2SnkJoyz0F8ukB'

    resp = app.post('/auth/token',
                    auth=(client_id, client_secret),
                    data={
                        'grant_type': 'client_credentials',
                        'scope': 'profile',
                    })
    assert resp.status_code == 200, resp.text

    data = resp.json()
    assert data == {
        'token_type': 'Bearer',
        'expires_in': 864000,
        'scope': 'profile',
        'access_token': data['access_token'],
    }

    config = context.get('config')
    key = jwk.loads(
        json.loads((config.config_path / 'keys/public.json').read_text()))
    token = jwt.decode(data['access_token'], key)
    assert token == {
        'iss': config.server_url,
        'sub': client_id,
        'aud': client_id,
        'iat': int(token['iat']),
        'exp': int(token['exp']),
        'scope': 'profile',
    }
Ejemplo n.º 16
0
        def parse_openid(self, token, nonce=None):
            def load_key(header, payload):
                jwk_set = self.fetch_jwk_set()
                try:
                    return jwk.loads(jwk_set, header.get('kid'))
                except ValueError:
                    jwk_set = self.fetch_jwk_set(force=True)
                    return jwk.loads(jwk_set, header.get('kid'))

            claims_options = {
                'iss': {
                    'values': [issuer_url],
                },
            }
            claims_params = {
                'nonce': nonce,
                'client_id': self.client_id,
            }

            access_token = token.get('access_token')
            if access_token is not None:
                claims_params['access_token'] = access_token
                claims_cls = CodeIDToken
            else:
                claims_cls = ImplicitIDToken

            claims = jwt.decode(token['id_token'],
                                key=load_key,
                                claims_cls=claims_cls,
                                claims_options=claims_options,
                                claims_params=claims_params)
            claims.validate(leeway=120)
            return UserInfo(claims)
Ejemplo n.º 17
0
    async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:
        if scope["type"] not in ("http", "websocket"):  # pragma: no cover
            await self.app(scope, receive, send)
            return

        connection = HTTPConnection(scope)
        initial_session_was_empty = True

        if self.session_cookie in connection.cookies:
            data = connection.cookies[self.session_cookie].encode("utf-8")
            try:
                jwt_payload = jwt.decode(
                    data,
                    str(
                        self.jwt_secret.decode
                        if self.jwt_secret.decode
                        else self.jwt_secret.encode
                    ),
                )
                jwt_payload.validate_exp(time.time(), 0)
                scope["session"] = jwt_payload
                initial_session_was_empty = False
            except (BadSignatureError, ExpiredTokenError):
                scope["session"] = {}
        else:
            scope["session"] = {}

        async def send_wrapper(message: Message) -> None:
            if message["type"] == "http.response.start":
                if scope["session"]:
                    if "exp" not in scope["session"]:
                        scope["session"]["exp"] = int(time.time()) + self.max_age
                    data = jwt.encode(
                        self.jwt_header, scope["session"], str(self.jwt_secret.encode)
                    )

                    headers = MutableHeaders(scope=message)
                    header_value = "%s=%s; path=/; Max-Age=%d; %s" % (
                        self.session_cookie,
                        data.decode("utf-8"),
                        self.max_age,
                        self.security_flags,
                    )
                    if self.domain:  # pragma: no cover
                        header_value += f"; domain={self.domain}"
                    headers.append("Set-Cookie", header_value)
                elif not initial_session_was_empty:
                    # The session has been cleared.
                    headers = MutableHeaders(scope=message)
                    header_value = "%s=%s; %s" % (
                        self.session_cookie,
                        "null; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT;",
                        self.security_flags,
                    )
                    if self.domain:  # pragma: no cover
                        header_value += f"; domain={self.domain}"
                    headers.append("Set-Cookie", header_value)
            await send(message)

        await self.app(scope, receive, send_wrapper)
def userinfo():
    req = flask.request
    log_request('GET-USERINFO', req)
    access_token = req.headers.get('Authorization', None)
    # TODO: if not access_token

    # TODO: Validate access-token

    log.info("GET-USERINFO: Access token: '{}'".format(access_token))

    access_token_parts = access_token.split()
    if access_token_parts[0].lower() != 'bearer' or len(access_token_parts) != 2:
        return flask.render_template('error.html', text='Invalid authorization')

    access_token = access_token_parts[1]

    # FIXME
    with open('jwt-key.pub', 'rb') as f:
        key_data = f.read()
    pub_key = JsonWebKey.import_key(key_data, {'kty': 'RSA'})

    access_token_json = jwt.decode(access_token, pub_key)
    scope = access_token_json['scope']

    # TODO: Validate audience in access token covers /userinfo
    log.info("GET-USERINFO: Access token audience: '{}'".format(access_token_json['aud']))

    log.info("GET-USERINFO: Scope '{}'".format(scope))

    claims = dict()
    # See https://openid.net/specs/openid-connect-basic-1_0.html#StandardClaims for what claims to include in access token
    if 'profile' in scope:
        claims['name'] = 'Name of user is {}'.format(access_token_json['sub'].capitalize())

    return claims
Ejemplo n.º 19
0
    def verifyToken(self, accessToken=None, jwks=None):
        """Verify access token

        :param str accessToken: access token
        :param dict jwks: JWKs

        :return: dict
        """
        # Define an access token
        if not accessToken:
            accessToken = self.token["access_token"]
        # Renew a JWKs of an identity provider if needed
        if not jwks:
            result = self.updateJWKs()
            if not result["OK"]:
                return result
            jwks = self.jwks
        if not jwks:
            return S_ERROR("JWKs not found.")
        # Try to decode and verify an access token
        self.log.debug("Try to decode token %s with JWKs:\n" % accessToken, pprint.pformat(jwks))
        try:
            return S_OK(jwt.decode(accessToken, JsonWebKey.import_key_set(jwks)))
        except Exception as e:
            self.log.exception(e)
            return S_ERROR(repr(e))
Ejemplo n.º 20
0
def _verify_token(nonce: str,
                  email,
                  raw_token: str,
                  public_key: bytes,
                  claims_cls=None):
    """Verify a JWT token signature with the public_key."""
    claims_options = {
        "iss": {
            "essential": True,
            "value": TOKEN_NAMESPACE
        },
        "aud": {
            "essential": True,
            "value": CLIENT_ID
        },
        "sub": {
            "essential": True,
            "value": email
        },
    }
    decoded_token = jwt.decode(
        raw_token,
        public_key,
        claims_cls=claims_cls,
        claims_options=claims_options,
        claims_params={"nonce": nonce},
    )
    decoded_token.validate()
    return decoded_token
Ejemplo n.º 21
0
 def decode_token(self, token: (JWT, str, dict)):
     try:
         decoded_token = jwt.decode(s=token,
                                    key=self.key_holder.get_public_key())
     except (BadSignatureError, Exception) as err:
         raise ValidationError(err)
     return decoded_token
Ejemplo n.º 22
0
def decode_api_key_v2(api_key: str, auth_public_key: str, required_scopes=None) -> Optional[TokenInfo]:
    """
    Check and retrieve authentication information from api_key.
    Returned value will be passed in 'token_info' parameter of your operation function, if there is one.
    'sub' or 'uid' will be set in 'user' parameter of your operation function, if there is one.
    Should return None if api_key is invalid or does not allow access to called API.
    """

    try:
        token = jwt.decode(api_key, key=auth_public_key)
    except AuthlibBaseError:
        return None

    expires_at = datetime.datetime.fromtimestamp(token['exp'])
    user_info = UserInfo.parse_raw(token['user_info'])

    now = datetime.datetime.now()
    if now > expires_at:
        return None

    t = TokenInfo(
        user_id=user_info.user_id,
        groups_read=[g.group_id for g in user_info.groups],
        groups_write=[g.group_id for g in user_info.groups if g.mode in (Mode.write, Mode.admin)],
        groups_admin=[g.group_id for g in user_info.groups if g.mode == Mode.admin],
        api_key=api_key,
        auth_method=AuthMethod.bearer
    )
    return t
Ejemplo n.º 23
0
def validate_passport(passport):
    """Validate passport claims

    Accepts:
        passport(tuple) : ( passport(str), header ) or ( passport(str), header, payload )

    """
    LOG.info("Validating passport")
    token = passport[0]
    header = passport[1]

    # Beacon can't verify audience because it does not know where the token originated in the first place
    claims_options = {"aud": {"essential": False}}
    try:
        # obtain public key for this passport
        public_key = elixir_key(header.get("jku"))
        # Try decoding the token using the public key
        decoded_passport = jjwt.decode(token,
                                       public_key,
                                       claims_options=claims_options)
        # And validating the signature
        decoded_passport.validate()
        return decoded_passport
    except Exception as ex:
        LOG.error(f"Error while decoding/validating passport:{ex}")
Ejemplo n.º 24
0
async def validate_token(token: str) -> None:
    """Validate JWT."""
    LOG.debug("Validating access token.")

    # Get JWK to decode the token with
    jwk = await get_jwk()

    # Claims that must exist in the token, and required values if specified
    claims_options = {
        "iss": {"essential": True, "values": CONFIG.aai["iss"].split(",")},  # Token allowed from these issuers
        "aud": {"essential": True, "values": CONFIG.aai["aud"].split(",")},  # Token allowed for these audiences
        "iat": {"essential": True},
        "exp": {"essential": True},
    }
    try:
        # Decode the token and validate the contents
        decoded_data = jwt.decode(token, jwk, claims_options=claims_options)
        decoded_data.validate()
    except MissingClaimError as e:
        raise web.HTTPUnauthorized(text=f"Could not validate access token: Missing claim(s): {e}")
    except ExpiredTokenError as e:
        raise web.HTTPUnauthorized(text=f"Could not validate access token: Expired signature: {e}")
    except InvalidClaimError as e:
        raise web.HTTPForbidden(text=f"Could not validate access token: Token info not corresponding with claim: {e}")
    except BadSignatureError as e:
        raise web.HTTPForbidden(text=f"Could not validate access token: Token signature could not be verified: {e}")
Ejemplo n.º 25
0
def parse_id_token(token_data, nonce):
    def load_key(header, payload):
        # TODO: cache this?
        jwk_set = requests.get(current_app.config['OIDC_JWKS_URL']).json()
        return jwk.loads(jwk_set, header.get('kid'))

    id_token = token_data['id_token']
    claims_params = {
        'nonce': nonce,
        'client_id': current_app.config['OIDC_CLIENT_ID']
    }
    if 'access_token' in token_data:
        claims_params['access_token'] = token_data['access_token']
        claims_cls = CodeIDToken
    else:
        claims_cls = ImplicitIDToken
    claims_options = {'iss': {'values': [current_app.config['OIDC_ISSUER']]}}
    claims = jwt.decode(
        id_token,
        key=load_key,
        claims_cls=claims_cls,
        claims_options=claims_options,
        claims_params=claims_params,
    )
    claims.validate(leeway=120)
    return UserInfo(claims)
Ejemplo n.º 26
0
 def check_authorized(self, headers, path, write=False):
     if ENABLE_AUTH:
         try:
             if not request.headers["Authorization"].startswith("Bearer "):
                 return 400
             token = request.headers["Authorization"].split(" ")[1]
             claims = jwt.decode(token, open(AUTH_TOKEN_PUBKEY).read())
             claims.validate()
             if claims["iss"] != AUTH_TOKEN_ISSUER:
                 return 401
             # TODO: Check 'aud' claim matches 'mocks.<domain>'
             if not self._check_path_match(
                     path, claims["x-nmos-registration"]["read"]):
                 return 403
             if write:
                 if not self._check_path_match(
                         path, claims["x-nmos-registration"]["write"]):
                     return 403
         except KeyError:
             # TODO: Add debug which can be returned in the error response JSON
             return 400
         except Exception:
             # TODO: Add debug which can be returned in the error response JSON
             return 400
     return True
Ejemplo n.º 27
0
 def test_validate_iat(self):
     id_token = jwt.encode({'alg': 'HS256'}, {'iat': 'invalid'}, 'k')
     claims = jwt.decode(id_token, 'k')
     self.assertRaises(
         errors.InvalidClaimError,
         claims.validate
     )
Ejemplo n.º 28
0
    async def __call__(
        self, request: Request
    ) -> Tuple[bool, Union[dict, HTTPException]]:
        authorization: str = request.headers.get("Authorization")
        scheme, token = get_authorization_scheme_param(authorization)
        if not authorization or scheme.lower() != "bearer":
            token = request.cookies.get(config.JWT_ACCESS_TOKEN_COOKIE)
        if not token:
            error = HTTPException(
                status_code=HTTP_401_UNAUTHORIZED,
                detail="Not authenticated",
                headers={"WWW-Authenticate": "Bearer"},
            )
            if self.auto_error:
                raise error
            else:
                return False, error

        try:
            token = jwt.decode(token, config.JWT_PUBLIC_KEY)
            token.validate()
        except ExpiredTokenError as e:
            error = HTTPException(status_code=HTTP_401_UNAUTHORIZED, detail=str(e))
            if self.auto_error:
                raise error
            else:
                return False, error
        except JoseError as e:
            error = HTTPException(status_code=HTTP_400_BAD_REQUEST, detail=str(e))
            if self.auto_error:
                raise error
            else:
                return False, error

        return True, token
Ejemplo n.º 29
0
def validate_request(request):
    try:
        authorization_value = request.headers["Authorization"]
    except KeyError:
        raise web.HTTPUnprocessableEntity(text="No authorization header provided!")

    auth_type, auth_token = authorization_value.split(" ")

    if auth_type != "Bearer":
        raise web.HTTPUnprocessableEntity(text="Invalid authentication method!")

    tokens = request.app["tokens"]

    if auth_token not in tokens.values():
        raise web.HTTPUnprocessableEntity(text="Invalidated authentication token used!")

    claims = jwt.decode(auth_token, request.app["public_key"])

    try:
        claims.validate()
        return claims
    except errors.ExpiredTokenError:
        del request.app["tokens"][get_key_with_value(tokens, auth_token)]

        raise web.HTTPUnprocessableEntity(text="Provided token is expired!")
Ejemplo n.º 30
0
        def wrapper(*args, **kwargs):
            response, status_code = func(*args, **kwargs)

            claims = {}
            if bool(request) is True:
                # If bool(request) is False, then we're not responding
                # to a HTTP request. This happens for instance when we're
                # updating the cache.
                if test and mock_jwt_claims is not None:
                    claims = copy.deepcopy(mock_jwt_claims)

                else:
                    try:
                        jwt_token = request.headers.get('Authorization')
                        jwt_secret = os.environ.get("JWT_SECRET")

                        if jwt_token:
                            # remove type ("Bearer") if present
                            jwt_token = jwt_token.split(" ")[-1]

                        claims = jwt.decode(jwt_token, jwt_secret)
                        claims.validate()

                    except Exception:
                        # This is only to extract claims if the JWT is valid.
                        # If we're unable to get claims from a valid JWT,
                        # we just return an empty dictionary.
                        # We don't throw any exceptions at this point.
                        claims = {}

            filter_func(response, claims)

            return response, status_code