def test_create_access_token_with_object(self):
        # Complex object to test building a JWT from. Normally if you are using
        # this functionality, this is something that would be retrieved from
        # disk somewhere (think sqlalchemy)
        class TestUser:
            def __init__(self, username, roles):
                self.username = username
                self.roles = roles

        # Setup the flask stuff
        app = Flask(__name__)
        app.secret_key = 'super=secret'
        app.config['JWT_ALGORITHM'] = 'HS256'
        jwt = JWTManager(app)

        @jwt.user_claims_loader
        def custom_claims(user):
            return {'roles': user.roles}

        @jwt.user_identity_loader
        def user_identity_lookup(user):
            return user.username

        # Create the token using the complex object
        with app.test_request_context():
            user = TestUser(username='******', roles=['bar', 'baz'])
            token = create_access_token(identity=user)

            # Decode the token and make sure the values are set properly
            token_data = _decode_jwt(token, app.secret_key,
                                     app.config['JWT_ALGORITHM'])
            self.assertEqual(token_data['identity'], 'foo')
            self.assertEqual(token_data['user_claims']['roles'],
                             ['bar', 'baz'])
示例#2
0
    def wrapper(*args, **kwargs):
        token = request.args.get('refresh_token')
        secret = _get_secret_key()
        algorithm = get_algorithm()
        jwt_data = _decode_jwt(token, secret, algorithm)

        if jwt_data['type'] != 'refresh':
            raise WrongTokenError(
                'Only refresh tokens can access this endpoint')

        ctx_stack.top.jwt = jwt_data
        return fn(*args, **kwargs)
示例#3
0
    def test_get_token_ttl(self):
        # This is called when using a simplekv backend that supports ttl (such
        # as redis or memcached). Because I do not want to require having those
        # installed to run the unit tests, I'm going to fiat that the code for
        # them works, and manually test the helper methods they call for correctness.

        # Test token ttl
        with self.app.test_request_context():
            token_str = _encode_refresh_token('foo', 'secret', 'HS256',
                                              timedelta(minutes=5))
            token = _decode_jwt(token_str, 'secret', 'HS256')
            time.sleep(2)
            token_ttl = _get_token_ttl(token).total_seconds()
            self.assertGreater(token_ttl, 296)
            self.assertLessEqual(token_ttl, 298)

        # Test ttl is 0 if token is already expired
        with self.app.test_request_context():
            token_str = _encode_refresh_token('foo', 'secret', 'HS256',
                                              timedelta(seconds=0))
            token = _decode_jwt(token_str, 'secret', 'HS256')
            time.sleep(2)
            token_ttl = _get_token_ttl(token).total_seconds()
            self.assertEqual(token_ttl, 0)
    def test_decode_invalid_jwt(self):
        with self.app.test_request_context():
            # Verify underlying pyjwt expires verification works
            with self.assertRaises(jwt.ExpiredSignatureError):
                token_data = {
                    'exp': datetime.utcnow() - timedelta(minutes=5),
                }
                encoded_token = jwt.encode(token_data, 'secret',
                                           'HS256').decode('utf-8')
                _decode_jwt(encoded_token, 'secret', 'HS256')

            # Missing jti
            with self.assertRaises(JWTDecodeError):
                token_data = {
                    'exp': datetime.utcnow() + timedelta(minutes=5),
                    'identity': 'banana',
                    'type': 'refresh'
                }
                encoded_token = jwt.encode(token_data, 'secret',
                                           'HS256').decode('utf-8')
                _decode_jwt(encoded_token, 'secret', 'HS256')

            # Missing identity
            with self.assertRaises(JWTDecodeError):
                token_data = {
                    'jti': 'banana',
                    'exp': datetime.utcnow() + timedelta(minutes=5),
                    'type': 'refresh'
                }
                encoded_token = jwt.encode(token_data, 'secret',
                                           'HS256').decode('utf-8')
                _decode_jwt(encoded_token, 'secret', 'HS256')

            # Missing type
            with self.assertRaises(JWTDecodeError):
                token_data = {
                    'jti': 'banana',
                    'identity': 'banana',
                    'exp': datetime.utcnow() + timedelta(minutes=5),
                }
                encoded_token = jwt.encode(token_data, 'secret',
                                           'HS256').decode('utf-8')
                _decode_jwt(encoded_token, 'secret', 'HS256')

            # Missing fresh in access token
            with self.assertRaises(JWTDecodeError):
                token_data = {
                    'jti': 'banana',
                    'identity': 'banana',
                    'exp': datetime.utcnow() + timedelta(minutes=5),
                    'type': 'access',
                    'user_claims': {}
                }
                encoded_token = jwt.encode(token_data, 'secret',
                                           'HS256').decode('utf-8')
                _decode_jwt(encoded_token, 'secret', 'HS256')

            # Bad fresh in access token
            with self.assertRaises(JWTDecodeError):
                token_data = {
                    'jti': 'banana',
                    'identity': 'banana',
                    'exp': datetime.utcnow() + timedelta(minutes=5),
                    'type': 'access',
                    'user_claims': {},
                    'fresh': 'banana'
                }
                encoded_token = jwt.encode(token_data, 'secret',
                                           'HS256').decode('utf-8')
                _decode_jwt(encoded_token, 'secret', 'HS256')

            # Missing user claims in access token
            with self.assertRaises(JWTDecodeError):
                token_data = {
                    'jti': 'banana',
                    'identity': 'banana',
                    'exp': datetime.utcnow() + timedelta(minutes=5),
                    'type': 'access',
                    'fresh': True
                }
                encoded_token = jwt.encode(token_data, 'secret',
                                           'HS256').decode('utf-8')
                _decode_jwt(encoded_token, 'secret', 'HS256')

            # Bad user claims
            with self.assertRaises(JWTDecodeError):
                token_data = {
                    'jti': 'banana',
                    'identity': 'banana',
                    'exp': datetime.utcnow() + timedelta(minutes=5),
                    'type': 'access',
                    'fresh': True,
                    'user_claims': 'banana'
                }
                encoded_token = jwt.encode(token_data, 'secret',
                                           'HS256').decode('utf-8')
                _decode_jwt(encoded_token, 'secret', 'HS256')

            # Bad token type
            with self.assertRaises(JWTDecodeError):
                token_data = {
                    'jti': 'banana',
                    'identity': 'banana',
                    'exp': datetime.utcnow() + timedelta(minutes=5),
                    'type': 'banana',
                    'fresh': True,
                    'user_claims': 'banana'
                }
                encoded_token = jwt.encode(token_data, 'secret',
                                           'HS256').decode('utf-8')
                _decode_jwt(encoded_token, 'secret', 'HS256')

        # Missing and bad csrf tokens
        self.app.config['JWT_TOKEN_LOCATION'] = 'cookies'
        self.app.config['JWT_COOKIE_CSRF_PROTECTION'] = True
        with self.app.test_request_context():
            now = datetime.utcnow()
            with self.assertRaises(JWTDecodeError):
                token_data = {
                    'exp': now + timedelta(minutes=5),
                    'iat': now,
                    'nbf': now,
                    'jti': 'banana',
                    'identity': 'banana',
                    'type': 'refresh',
                }
                encoded_token = jwt.encode(token_data, 'secret',
                                           'HS256').decode('utf-8')
                _decode_jwt(encoded_token, 'secret', 'HS256')

            with self.assertRaises(JWTDecodeError):
                token_data = {
                    'exp': now + timedelta(minutes=5),
                    'iat': now,
                    'nbf': now,
                    'jti': 'banana',
                    'identity': 'banana',
                    'type': 'refresh',
                    'csrf': True
                }
                encoded_token = jwt.encode(token_data, 'secret',
                                           'HS256').decode('utf-8')
                _decode_jwt(encoded_token, 'secret', 'HS256')
    def test_decode_jwt(self):
        # Test decoding a valid access token
        with self.app.test_request_context():
            now = datetime.utcnow()
            now_ts = calendar.timegm(now.utctimetuple())
            token_data = {
                'exp': now + timedelta(minutes=5),
                'iat': now,
                'nbf': now,
                'jti': 'banana',
                'identity': 'banana',
                'fresh': True,
                'type': 'access',
                'user_claims': {
                    'foo': 'bar'
                },
            }
            encoded_token = jwt.encode(token_data, 'secret',
                                       'HS256').decode('utf-8')
            data = _decode_jwt(encoded_token, 'secret', 'HS256')
            self.assertIn('exp', data)
            self.assertIn('iat', data)
            self.assertIn('nbf', data)
            self.assertIn('jti', data)
            self.assertIn('identity', data)
            self.assertIn('fresh', data)
            self.assertIn('type', data)
            self.assertIn('user_claims', data)
            self.assertEqual(data['exp'], now_ts + (5 * 60))
            self.assertEqual(data['iat'], now_ts)
            self.assertEqual(data['nbf'], now_ts)
            self.assertEqual(data['jti'], 'banana')
            self.assertEqual(data['identity'], 'banana')
            self.assertEqual(data['fresh'], True)
            self.assertEqual(data['type'], 'access')
            self.assertEqual(data['user_claims'], {'foo': 'bar'})

        # Test decoding a valid refresh token
        with self.app.test_request_context():
            now = datetime.utcnow()
            now_ts = calendar.timegm(now.utctimetuple())
            token_data = {
                'exp': now + timedelta(minutes=5),
                'iat': now,
                'nbf': now,
                'jti': 'banana',
                'identity': 'banana',
                'type': 'refresh',
            }
            encoded_token = jwt.encode(token_data, 'secret',
                                       'HS256').decode('utf-8')
            data = _decode_jwt(encoded_token, 'secret', 'HS256')
            self.assertIn('exp', data)
            self.assertIn('iat', data)
            self.assertIn('nbf', data)
            self.assertIn('jti', data)
            self.assertIn('identity', data)
            self.assertIn('type', data)
            self.assertEqual(data['exp'], now_ts + (5 * 60))
            self.assertEqual(data['iat'], now_ts)
            self.assertEqual(data['nbf'], now_ts)
            self.assertEqual(data['jti'], 'banana')
            self.assertEqual(data['identity'], 'banana')
            self.assertEqual(data['type'], 'refresh')