def get_access_token() -> Response:
    refresh_token_jwt = request.headers.get('refreshToken')
    if not refresh_token_jwt:
        return create_unauthorized_response('refresh token required')
    jwt_decoder = JwtDecoder(current_app.secret_key)
    decode_result = jwt_decoder.decode_jwt(refresh_token_jwt)
    if not decode_result.ok:
        if decode_result.error == 'token-invalid':
            return create_unauthorized_response('refresh token invalid')
        elif decode_result.error == 'signature-expired':
            return create_unauthorized_response('refresh token expired')
    token = g.database_session.query(RefreshToken) \
      .filter_by(token=refresh_token_jwt) \
      .first()
    if not token:
        return create_unauthorized_response('refresh token revoked')
    account_id = decode_result.payload['sub']
    token_factory = AuthenticationTokenFactory(
        JwtFactory(current_app.secret_key), datetime.utcnow)
    access_token = token_factory.create_access_token(account_id)
    return make_response(
        jsonify({
            'jwt':
            access_token.jwt,
            'expiresIn':
            (access_token.expiration_date - datetime.now()).seconds,
        }), HTTPStatus.OK)
Beispiel #2
0
    def test_decode_jwt(self):
        jwt_factory = JwtFactory('secret')
        factory = AuthenticationTokenFactory(jwt_factory, datetime.utcnow)
        token = factory.create_access_token(1)
        decoder = JwtDecoder('secret')

        result = decoder.decode_jwt(token.jwt)

        self.assertTrue(result.ok)
        self.assertEqual(result.payload['sub'], 1)
Beispiel #3
0
    def test_decode_expired_jwt(self):
        utc_now_supplier = lambda: datetime(2008, 8, 3, 20, 31)
        jwt_factory = JwtFactory('secret')
        factory = AuthenticationTokenFactory(jwt_factory, utc_now_supplier)
        token = factory.create_access_token(1)
        decoder = JwtDecoder('secret')

        result = decoder.decode_jwt(token.jwt)

        self.assertFalse(result.ok)
        self.assertEqual(result.error, 'signature-expired')
Beispiel #4
0
    def test_encode_token(self):
        utc_now_supplier = lambda: datetime(2019, 8, 3, 20, 31)
        jwt_factory = JwtFactory('secret')
        factory = AuthenticationTokenFactory(jwt_factory, utc_now_supplier)

        token = factory.create_access_token(1)

        self.assertEqual(
            token,
            AccessToken(
                'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1NjQ4NjYwNjAsImlhdCI6M'
                'TU2NDg2NDI2MCwic3ViIjoxfQ.WSvE-OCzvVPVayHicY1viqLYYA560cCK-9FOZ6NY2o0',
                1, datetime(2019, 8, 3, 21, 1)))
Beispiel #5
0
class TestAuthenticatedAccountsRoles(AppTestCase):
    def setUp(self) -> None:
        super().setUp()
        secret_key = self._app.secret_key
        time_supplier = datetime.datetime.utcnow
        jwt_factory = JwtFactory(secret_key)
        self.token_factory = AuthenticationTokenFactory(
            jwt_factory, time_supplier)

    def test_get_authenticated_accounts_roles_when_ok(self):
        cursor = self.database_connection.cursor()
        self.database_connection.commit()
        self.db_setup_account(1, 2, 'kenny', 'password', '*****@*****.**')
        self.db_insert_role(3, 'coolguy')
        self.db_insert_account_role(2, 3)
        self.db_insert_resource_permission(4, '^/.*$', 'POST')
        self.db_insert_role_resource_permission(3, 4)
        access_token_jwt = self.token_factory.create_access_token(2).jwt

        response = self.client.get('/account/roles',
                                   headers={'accessToken': access_token_jwt})

        self.assertEqual(response.status_code, HTTPStatus.OK)
        self.assertDictEqual(
            response.json, {
                'items': [
                    {
                        'name':
                        'coolguy',
                        'permissions': [
                            {
                                'method': 'POST',
                                'resource_regex': '^/.*$',
                            },
                        ],
                    },
                ],
            })
Beispiel #6
0
class TestGetAccount(AppTestCase):
    def setUp(self) -> None:
        super().setUp()
        secret_key = self._app.secret_key
        time_supplier = datetime.datetime.utcnow
        jwt_factory = JwtFactory(secret_key)
        self.token_factory = AuthenticationTokenFactory(
            jwt_factory, time_supplier)

    def test_get_authenticated_account_when_ok(self):
        self.db_setup_account(1, 1, 'hulot', 'myPassword', '*****@*****.**')
        token = self.token_factory.create_access_token(1)

        response = self.get_own_account(token.jwt)

        self.assertEqual(response.status_code, HTTPStatus.OK)
        creation_datetime = response.json['creationDatetime']
        datetime.datetime.fromisoformat(creation_datetime)  # should be ok
        self.assertDictEqual(
            response.json, {
                'id': 1,
                'username': '******',
                'email': '*****@*****.**',
                'creationDatetime': creation_datetime,
                'birder': {
                    'id': 1,
                    'name': 'hulot',
                },
            })

    def test_get_account_when_authenticated_account_disappears(self):
        token = self.token_factory.create_access_token(1)

        response = self.get_own_account(token.jwt)

        self.assertEqual(response.status_code, HTTPStatus.UNAUTHORIZED)
        self.assertEqual(
            response.json, {
                'code': ErrorCode.ACCOUNT_MISSING,
                'message': 'Authorized account gone',
            })

    def test_get_account_when_no_authentication_token(self):
        response = self.get_own_account(None)

        self.assertEqual(response.status_code, HTTPStatus.UNAUTHORIZED)
        self.assertDictEqual(
            response.json, {
                'code': ErrorCode.AUTHORIZATION_REQUIRED,
                'message': 'Authorization required',
            })

    def test_get_account_when_access_token_invalid(self):
        response = self.get_own_account('invalid')

        self.assertEqual(response.status_code, HTTPStatus.UNAUTHORIZED)
        self.assertDictEqual(
            response.json, {
                'code': ErrorCode.ACCESS_TOKEN_INVALID,
                'message': 'Access token invalid',
            })

    def test_get_account_when_access_token_expired(self):
        self.db_setup_account(1, 1, 'hulot', 'myPassword', '*****@*****.**')
        expiration = timedelta(seconds=-1)
        token = self.token_factory.create_access_token(1, expiration)

        response = self.get_own_account(token.jwt)

        self.assertEqual(response.status_code, HTTPStatus.UNAUTHORIZED)
        self.assertDictEqual(
            response.json, {
                'code': ErrorCode.ACCESS_TOKEN_EXPIRED,
                'message': 'Access token expired',
            })

    def get_own_account(self, token):
        if not token:
            return self.client.get('/account')
        else:
            return self.client.get('/account', headers={'accessToken': token})
Beispiel #7
0
class TestPasswordUpdate(AppTestCase):
    def setUp(self) -> None:
        super().setUp()
        self.db_setup_account(1, 1, 'hulot', 'oldPassword', '*****@*****.**')
        time_supplier = datetime.datetime.utcnow
        jwt_factory = JwtFactory(self._app.secret_key)
        self.token_factory = AuthenticationTokenFactory(
            jwt_factory, time_supplier)

    def test_post_password_update_when_ok(self) -> None:
        token = self.token_factory.create_access_token(1, timedelta(1))

        response = self.post_password(token.jwt, 'oldPassword', 'newPassword')

        self.assertEqual(response.status_code, HTTPStatus.NO_CONTENT)

    def test_post_password_update_when_token_missing(self) -> None:
        response = self.post_password(None, 'oldPassword', 'newPassword')

        self.assertEqual(response.status_code, HTTPStatus.UNAUTHORIZED)
        self.assertEqual(
            response.json, {
                'code': ErrorCode.AUTHORIZATION_REQUIRED,
                'message': 'Authorization required',
            })

    def test_post_password_update_when_token_invalid(self) -> None:
        response = self.post_password('invalid', 'oldPassword', 'newPassword')

        self.assertEqual(response.status_code, HTTPStatus.UNAUTHORIZED)
        self.assertEqual(
            response.json, {
                'code': ErrorCode.ACCESS_TOKEN_INVALID,
                'message': 'Access token invalid',
            })

    def test_post_password_update_when_token_expired(self) -> None:
        expiration = timedelta(seconds=-1)
        token = self.token_factory.create_access_token(1, expiration)

        response = self.post_password(token.jwt, 'oldPassword', 'newPassword')

        self.assertEqual(response.status_code, HTTPStatus.UNAUTHORIZED)
        self.assertEqual(
            response.json, {
                'code': ErrorCode.ACCESS_TOKEN_EXPIRED,
                'message': 'Access token expired',
            })

    def test_post_password_update_when_old_password_incorrect(self) -> None:
        token = self.token_factory.create_access_token(1, timedelta(1))

        response = self.post_password(token.jwt, 'incorrect', 'newPassword')

        self.assertEqual(response.status_code, HTTPStatus.UNAUTHORIZED)
        self.assertEqual(
            response.json, {
                'code': ErrorCode.OLD_PASSWORD_INCORRECT,
                'message': 'Old password incorrect',
            })

    def test_post_password_update_when_new_password_invalid(self) -> None:
        token = self.token_factory.create_access_token(1, timedelta(1))

        response = self.post_password(token.jwt, 'oldPassword', 'invalid')

        self.assertEqual(response.status_code, HTTPStatus.BAD_REQUEST)
        self.assertEqual(
            response.json, {
                'code': ErrorCode.PASSWORD_INVALID,
                'message': 'New password invalid',
            })

    def post_password(self, token, old_password, new_password):
        resource = '/account/password'
        headers = {'accessToken': token} if token else {}
        json = {'oldPassword': old_password, 'newPassword': new_password}
        return self.client.post(resource, headers=headers, json=json)
Beispiel #8
0
 def create_access_token(self, account_id: int) -> AccessToken:
     jwt_factory = JwtFactory(self._app.secret_key)
     token_factory = AuthenticationTokenFactory(jwt_factory,
                                                datetime.utcnow)
     return token_factory.create_access_token(account_id, timedelta(1))