async def test_invalid_access_token_procedure(username, route, variables): """Test that JWT decoding fails for some example invalid tokens.""" access_tokens = [ 42, 3.14, None, '', 'password', [], {}, access.generate(username)['access_token'][:-1], access.generate(username.upper())['access_token'], access.generate(f'{username}+')['access_token'], jwt.encode( { 'iss': 'FastSurvey', 'sub': username, 'iat': 0, 'exp': 0 }, key=settings.PRIVATE_RSA_KEY, algorithm='RS256', ), jwt.encode( { 'iss': 'FastSurvey', 'sub': username, 'iat': 0, 'exp': 4102444800 }, key=base64.b64decode(variables['invalid_private_rsa_key']), algorithm='RS256', ), jwt.encode( { 'iss': 'FastSurvey', 'sub': username, 'iat': 0, 'exp': 4102444800 }, key=settings.PRIVATE_RSA_KEY, algorithm='HS256', ), jwt.encode( { 'iss': 'FastSurvey', 'sub': username, 'iat': 0, 'exp': 4102444800 }, key=settings.PRIVATE_RSA_KEY, algorithm='RS512', ), ] for access_token in access_tokens: with pytest.raises(fastapi.HTTPException): await route(access_token=access_token, username=username)
async def test_fetching_existing_user_with_invalid_access_token( mock_email_sending, client, username, account_data, cleanup, ): """Test that correct account data is returned on valid request.""" await main.account_manager.create(username, account_data) access_token = access.generate('tomato')['access_token'] headers = {'Authorization': f'Bearer {access_token}'} response = await client.get(f'/users/{username}', headers=headers) assert check_error(response, errors.AccessForbiddenError)
async def verify(self, verification_token, password): """Verify an existing account via its unique verification token.""" account_data = await database.database['accounts'].find_one( filter={'verification_token': verification_token}, projection={ 'password_hash': True, 'verified': True }, ) if account_data is None or account_data['verified']: raise errors.InvalidVerificationTokenError() if not pw.verify(password, account_data['password_hash']): raise errors.InvalidPasswordError() result = await database.database['accounts'].update_one( filter={'verification_token': verification_token}, update={'$set': { 'verified': True }}) if result.matched_count == 0: raise errors.InvalidVerificationTokenError() return access.generate(account_data['_id'])
async def authenticate(self, identifier, password): """Authenticate user by their username or email and their password.""" expression = ({ 'email_address': identifier } if '@' in identifier else { '_id': identifier }) account_data = await database.database['accounts'].find_one( filter=expression, projection={ 'password_hash': True, 'verified': True }, ) if account_data is None: raise errors.UserNotFoundError() password_hash = account_data['password_hash'] if not pw.verify(password, password_hash): raise errors.InvalidPasswordError() if account_data['verified'] is False: raise errors.AccountNotVerifiedError() return access.generate(account_data['_id'])
def headers(username): """Provide an authentication header to access protected routes.""" access_token = access.generate(username)['access_token'] return {'Authorization': f'Bearer {access_token}'}
async def refresh_access_token( access_token: str = docs.ARGUMENTS['access_token'], ): """Generate a new access token with a refreshed expiration time.""" return access.generate(access.decode(access_token))
async def test_valid_access_token_procedure(username, route): """Test JWT access token generation and decoding procedure.""" access_token = access.generate(username)['access_token'] await route(access_token=access_token, username=username)