def confirm_account(self, confirmation_token): ''' Confirms user in database ''' try: # Decode token jwt_manager = JWTConfirmEmailManagerFactory.new() brl_user = jwt_manager.get_confirmed_user(confirmation_token) user = self.store.read_user(brl_user) except NotInStoreException: raise NotFoundException("User '%s' doesn't exist" % brl_user) if user.confirmation_token == confirmation_token: if not user.active: # Do not re-send things if already activated try: register_signup(self.store, brl_user) except Exception as exc: logger.error("Can't register sign-up in background! %s" % str(exc)) user.active = True user.confirmation_date = datetime.datetime.now() self.store.update_user(user) jwt_auth_manager = JWTCredentialsManagerFactory.new(self.store) token = jwt_auth_manager.get_token_for(brl_user) return token, brl_user, user.ga_client_id else: raise NotFoundException("Invalid user or token")
def _get_login_page(self, user): manager = JWTCredentialsManagerFactory.new(self.store) token = manager.get_token_for(user.ID) joined_date = user.joined_date.to_iso8601 if user and user.joined_date else "" get_vars = {"oauthlogin": 1, "login": user.ID, "token": token, "client_id": user.ga_client_id, "email": user.email, "created_at": joined_date} return "%s/accounts/login?%s" % (BII_WEB_DOMAIN_URL, urllib.urlencode(get_vars))
def authenticate(self, brl_user, password): """ Create a "profile" object (object to encrypt) and expiration time. Then return the JWT token Expiration time as a UTC UNIX timestamp (an int) or as a datetime""" try: brl_user = BRLUser(brl_user) except InvalidNameException: raise AuthenticationException("Wrong user or password") self._check_password(brl_user, password) manager = JWTCredentialsManagerFactory.new(self.store) token = manager.get_token_for(brl_user) return brl_user, token
def test_invalid_token(self): '''Obtain a valid token and then change password. Token must be invalid''' brl_user, token_1 = self.user_service.authenticate(self.brl_user, self.plain_password) # Check the token is valid manager = JWTCredentialsManagerFactory.new(self.store) brl_user_test = manager.get_user(token_1) self.assertEqual(brl_user, brl_user_test) sleep(0.1) # Sleep a moment and change the password # Now change password and re-check old token self.user_service.change_password(self.brl_user, self.plain_password, "Newp@sW0rd") # Check the token is invalid (can't authenticate) self.assertRaises(DecodeError, manager.get_user, token_1)
def _get_login_page(self, user): manager = JWTCredentialsManagerFactory.new(self.store) token = manager.get_token_for(user.ID) joined_date = user.joined_date.to_iso8601 if user and user.joined_date else "" get_vars = { "oauthlogin": 1, "login": user.ID, "token": token, "client_id": user.ga_client_id, "email": user.email, "created_at": joined_date } return "%s/accounts/login?%s" % (BII_WEB_DOMAIN_URL, urllib.urlencode(get_vars))
def test_invalid_token(self): '''Obtain a valid token and then change password. Token must be invalid''' brl_user, token_1 = self.user_service.authenticate( self.brl_user, self.plain_password) # Check the token is valid manager = JWTCredentialsManagerFactory.new(self.store) brl_user_test = manager.get_user(token_1) self.assertEqual(brl_user, brl_user_test) sleep(0.1) # Sleep a moment and change the password # Now change password and re-check old token self.user_service.change_password(self.brl_user, self.plain_password, "Newp@sW0rd") # Check the token is invalid (can't authenticate) self.assertRaises(DecodeError, manager.get_user, token_1)
def confirm_password_reset(self, confirmation_token): ''' Confirms password change. User and password are inside the token ''' try: # Decode token jwt_manager = JWTPasswordResetManagerFactory.new() brl_user, plain_password = jwt_manager.get_user_and_password(confirmation_token) user = self.store.read_user(brl_user) except Exception: raise NotFoundException("No user found with name %s" % brl_user) # Update password user.password = plain_password user.active = True # If not active, activate now, email is validated self.store.update_user(user) # Generate an auth token to autologin user jwt_auth_manager = JWTCredentialsManagerFactory.new(self.store) token = jwt_auth_manager.get_token_for(brl_user) return token, brl_user
def install_plugins(self): self.bsonplugin = BSONBottlePlugin() # BiiResponse plugin. All rest methods has to return # (data serializable | None, biiresponse) or throw BiiServiceException subclass logger.info("Installing BiiReturnHandlerPlugin plugin...") self.biiresponseplugin = BiiReturnHandlerPlugin(self.bsonplugin) self.install(self.biiresponseplugin) # Very first of all, check SSL or die if BII_SSL_ENABLED: # In heroku true for all environments logger.info("Installing NonSSLBlockerBottlePlugin plugin...") nonsslblock = NonSSLBlockerBottlePlugin() self.install(nonsslblock) # First of all, check DOS attacks by IP to the API # Counts IP request, raise 401 if banned if getattr(self.store, 'ip_mc_collection', False): logger.info("Installing massive DOS blocker...") doslogin = DOSBlockerBottlePlugin(self.store.ip_mc_collection, delta=BII_DOS_ATTACK_DELTA_TIME, max_events=BII_DOS_ATTACK_MAX_REQUEST, bantime=BII_DOS_ATTACK_BAN_TIME, callback_ip_banned=self.callback_ip_banned_for_DOS, banned_http_response=self.banned_http_response_for_DOS) # TODO: Maybe configure a log alert (heroku) if we return 401 banned # to analyze the case and adjust limits? self.install(doslogin) # Second, check Http Basic auth logger.info("Installing http basic authentication plugin...") httpplugin = HttpBasicAuthenticationBottlePlugin() self.install(httpplugin) # And check auth JWT logger.info("Installing JWT authentication plugin...") jwt_manager = JWTCredentialsManagerFactory.new(self.store) jwt_plugin = JWTAuthenticationBottlePlugin(jwt_manager) self.install(jwt_plugin) # Third check excess of login error for an IP # Catch generic 401 (or 404 or other) error from authentication and stores IP, # raise 401 if already banned if getattr(self.store, 'ip_mc_collection', False): logger.info("Installing massive error blocker...") massiveerrorplugin = MassiveErrorBlockerBottlePlugin( self.store.ip_mc_collection, delta=BII_ERROR_ATTACK_DELTA_TIME, max_events=BII_ERROR_ATTACK_MAX_ATTEMPTS, bantime=BII_ERROR_ATTACK_BAN_TIME, callback_ip_banned=self.callback_ip_banned_for_many_errors, banned_http_response=self.banned_http_response_for_many_errors) self.install(massiveerrorplugin) # Last, parse BSON data logger.info("Installing bson plugin...") self.install(self.bsonplugin) # Logging actions if BII_ENABLED_BII_USER_TRACE: self.tracebottleplugin = BiiUserTraceBottlePlugin() logger.info("Installing BiiUserTraceBottlePlugin plugin...") self.install(self.tracebottleplugin)