def authenticate_and_fetch_profile(self, username, password, username_for_profile=None): """Authenticates a user with credentials username and password against AD. If authentication is successful then it fetches a profile of a user identified by username_for_profile and if found the profile is returned. :param username: LDAP username :param password: LDAP password :param username_for_profile: Username of the profile to be fetched :return: user profile base on the LDAP_USER_ATTRIBUTES """ if username_for_profile is None: username_for_profile = username if self.fqdn is not None: username = username + "@" + self.fqdn try: ldap_conn = Connection(self.ldap_server, auto_bind=True, user=username, password=password) user_filter = self.user_filter.format(username_for_profile) logger.info('base filter:{} user filter:{}'.format( self.base_filter, user_filter)) with ldap_conn: result = ldap_conn.search(self.base_filter, user_filter, SEARCH_SCOPE_WHOLE_SUBTREE, attributes=list( self.profile_attrs.keys())) if not result: # the search returns false in case of user not a security group member. raise CredentialsAuthError( credentials={'username': username}, message='User does not belong to security Group or ' 'could not find the user profile.') response = dict() user_profile = ldap_conn.response[0]['attributes'] for ad_profile_attr, sd_profile_attr in self.profile_attrs.items( ): response[sd_profile_attr] = \ user_profile[ad_profile_attr] if user_profile.__contains__(ad_profile_attr) else '' response[sd_profile_attr] = response[sd_profile_attr][0] \ if isinstance(response[sd_profile_attr], list) else response[sd_profile_attr] return response except LDAPException as e: raise CredentialsAuthError(credentials={'username': username}, error=e)
def authenticate(self, credentials): user = get_resource_service('auth_users').find_one(req=None, username=credentials.get('username')) if not user: raise CredentialsAuthError(credentials) if 'is_enabled' in user and not user.get('is_enabled', False): raise UserDisabledError() if not user.get('is_active', False): raise UserInactiveError() password = credentials.get('password').encode('UTF-8') hashed = user.get('password').encode('UTF-8') if not (password and hashed): raise CredentialsAuthError(credentials) try: rehashed = bcrypt.hashpw(password, hashed) if hashed != rehashed: raise CredentialsAuthError(credentials) except ValueError: raise CredentialsAuthError(credentials) return user
def authenticate(self, credentials): auth_url = app.config['XMPP_AUTH_URL'] if not auth_url: raise SuperdeskApiError.notConfiguredError() domain = app.config['XMPP_AUTH_DOMAIN'] jid = credentials.get('jid') if not jid: raise CredentialsAuthError(credentials) user = get_resource_service('auth_users').find_one(req=None, jid=jid) if not user: raise CredentialsAuthError(credentials) try: r = requests.post(app.config['XMPP_AUTH_URL'], data={ "jid": jid, "domain": domain, "transaction_id": credentials.get('transactionId') }) except Exception: raise CredentialsAuthError(credentials) else: if r.status_code != 200: raise CredentialsAuthError(credentials) return user
def authenticate(self, credentials): auth_header = request.headers.get("Authorization", "").split(" ", 1) if auth_header[0] != "Bearer" and len(auth_header) != 2: raise CredentialsAuthError(credentials) token = auth_header[1] is_valid = self.oidc.validate_token(token, ["openid", "email", "profile"]) if not is_valid: raise CredentialsAuthError(credentials) users_service = get_resource_service("users") username = g.oidc_token_info["username"] user = users_service.find_one(req=None, username=username) or {} sync_data = { "username": username, "email": g.oidc_token_info.get("email", user.get("email")), "display_name": g.oidc_token_info.get("name"), } # first name and last name is optional in Keycloak if "given_name" in g.oidc_token_info: sync_data["first_name"] = g.oidc_token_info.get("given_name") if "family_name" in g.oidc_token_info: sync_data["last_name"] = g.oidc_token_info.get("family_name") if not user: # email is optional in Keycloak if not sync_data["email"]: raise CredentialsAuthError( sync_data, message=_("Please update your account email address")) user_role = None client_id = g.oidc_token_info.get("client_id", "") keycloak_roles = g.oidc_token_info.get("resource_access", {}).get( client_id, {}).get("roles", []) for role_name in keycloak_roles: role = get_resource_service("roles").find_one( req=None, name=ignorecase_query(role_name)) if role: user_role = role.get("_id") break sync_data.update({ "password": "", "user_type": "user", "role": user_role, "needs_activation": False, }) users_service.post([sync_data]) else: users_service.patch(user[config.ID_FIELD], sync_data) user.update(sync_data) return user
def authenticate(self, credentials): user = get_resource_service('auth_users').find_one(req=None, username=credentials.get('username')) if not user: raise CredentialsAuthError(credentials) password = credentials.get('password').encode('UTF-8') hashed = user.get('password').encode('UTF-8') if not (password and hashed): raise CredentialsAuthError(credentials) if not bcrypt.checkpw(password, hashed): raise CredentialsAuthError(credentials) return user
class ImportUsersTestCase(SuperdeskTestCase): """ for testing import user using ldap. """ def test_import_user_using_command(self, mock_ldap_connection): user = {'username': '******', 'password': '******', 'user_to_import': 'barf'} cmd = ImportUserProfileFromADCommand() cmd.run(user['username'], user['password'], user['user_to_import']) auth_user = get_resource_service('auth').authenticate({'username': '******', 'password': '******'}) self.assertEqual(auth_user['username'], user['user_to_import']) cmd.run(user['username'], user['password'], 'BARF') auth_user2 = get_resource_service('auth').authenticate({'username': '******', 'password': '******'}) self.assertEqual(auth_user2['username'], user['user_to_import']) self.assertEqual(auth_user2['_id'], auth_user['_id']) @mock.patch('apps.ldap.ldap.get_user', return_value={'username': '******'}) def test_import_profile_for_already_imported_user_raises_exception(self, mock_ldap_connection, mock_get_user): with self.assertRaises(SuperdeskApiError) as context: service = get_resource_service('import_profile') doc = {'username': '******', 'password': '******', 'profile_to_import': 'barf'} users = service.post([doc]) self.assertIsNotNone(users) self.assertEqual(len(users), 1) doc = {'username': '******', 'password': '******', 'profile_to_import': 'BARF '} service.post([doc]) ex = context.exception self.assertEqual(ex.message, 'User already exists in the system.') self.assertEqual(ex.status_code, 400) self.assertDictEqual(ex.payload, {'profile_to_import': 1}) @mock.patch('apps.ldap.ldap.get_user', return_value={'username': '******'}) def test_import_user_by_not_logged_in_user_raises_exception(self, mock_ldap_connection, mock_get_user): with self.assertRaises(SuperdeskApiError) as context: service = get_resource_service('import_profile') doc = {'username': '******', 'password': '******', 'profile_to_import': 'barf'} service.post([doc]) ex = context.exception self.assertEqual(ex.message, 'Invalid Credentials.') self.assertEqual(ex.status_code, 403) self.assertDictEqual(ex.payload, {'credentials': 1}) @mock.patch('apps.ldap.ldap.ADAuth.authenticate_and_fetch_profile', side_effect=CredentialsAuthError(credentials={'username': '******'}, error='test')) @mock.patch('apps.ldap.ldap.get_user', return_value={'username': '******'}) def test_user_import_profile_with_invalid_credentials(self, mock_ldap_connection, mock_auth, mock_get_user): with self.assertRaises(SuperdeskApiError) as context: service = get_resource_service('import_profile') doc = {'username': '******', 'password': '******', 'profile_to_import': 'barf'} service.post([doc]) ex = context.exception self.assertEqual(ex.message, 'Invalid Credentials.') self.assertEqual(ex.status_code, 403) self.assertDictEqual(ex.payload, {'credentials': 1})
def authenticate(self, credentials, ignore_expire=False): user = get_resource_service("auth_users").find_one(req=None, username=credentials.get("username")) if not user: raise CredentialsAuthError(credentials) password = credentials.get("password").encode("UTF-8") hashed = user.get("password").encode("UTF-8") if not (password and hashed): raise CredentialsAuthError(credentials) if not bcrypt.checkpw(password, hashed): raise CredentialsAuthError(credentials) if not ignore_expire and app.settings.get("PASSWORD_EXPIRY_DAYS", 0) > 0: days = app.settings.get("PASSWORD_EXPIRY_DAYS") date = user.get("password_changed_on") if date is None or (date + datetime.timedelta(days=days)) < utcnow(): raise PasswordExpiredError() return user
def disable_sd_desktop_notification(self, credentials): user = get_resource_service('users').find_one( req=None, username=credentials.get('username')) if not user: raise CredentialsAuthError(credentials) user_updates = user user_preferences = user_updates.get('user_preferences') if user_preferences: desktop_notification = user_preferences.get('desktop:notification') if desktop_notification: enabled = desktop_notification.get('enabled') if enabled: user_updates['user_preferences']['desktop:notification'][ 'enabled'] = False get_resource_service('users').system_update(user['_id'], user_updates, user)
def create(self, docs, **kwargs): for doc in docs: username = doc['username'] credentials = { 'username': username, 'password': doc['old_password'] } try: get_resource_service('auth_db').authenticate(credentials, True) except Exception as e: raise CredentialsAuthError(credentials=credentials, error=e) user = superdesk.get_resource_service('users').find_one( req=None, username=username) superdesk.get_resource_service('users').update_password( user['_id'], doc['new_password']) del doc['old_password'] del doc['new_password'] return [user['_id']]
def create(self, docs, **kwargs): for doc in docs: username = doc["username"] credentials = {"username": username, "password": doc["old_password"]} try: get_resource_service("auth_db").authenticate(credentials, True) except Exception as e: raise CredentialsAuthError(credentials=credentials, error=e) user = superdesk.get_resource_service("users").find_one(req=None, username=username) superdesk.get_resource_service("users").update_password(user["_id"], doc["new_password"]) del doc["old_password"] del doc["new_password"] # return etag for further user updates user = superdesk.get_resource_service("users").find_one(req=None, _id=user["_id"]) doc["_etag"] = user["_etag"] return [user["_id"]]
class ImportUsersTestCase(TestCase): """for testing import user using ldap.""" def test_import_user_using_command(self, mock_ldap_connection): user = { "username": "******", "password": "******", "user_to_import": "barf" } cmd = ImportUserProfileFromADCommand() cmd.run(user["username"], user["password"], user["user_to_import"]) auth_user = get_resource_service("auth_db").authenticate({ "username": "******", "password": "******" }) self.assertEqual(auth_user["username"], user["user_to_import"]) cmd.run(user["username"], user["password"], "BARF") auth_user2 = get_resource_service("auth_db").authenticate({ "username": "******", "password": "******" }) self.assertEqual(auth_user2["username"], user["user_to_import"]) self.assertEqual(auth_user2["_id"], auth_user["_id"]) @mock.patch("apps.ldap.ldap.get_user", return_value={"username": "******"}) def test_import_profile_for_already_imported_user_raises_exception( self, mock_ldap_connection, mock_get_user): with self.assertRaises(SuperdeskApiError) as context: service = get_resource_service("import_profile") doc = { "username": "******", "password": "******", "profile_to_import": "barf" } users = service.post([doc]) self.assertIsNotNone(users) self.assertEqual(len(users), 1) doc = { "username": "******", "password": "******", "profile_to_import": "BARF " } service.post([doc]) ex = context.exception self.assertEqual(ex.message, "User already exists in the system.") self.assertEqual(ex.status_code, 400) self.assertDictEqual(ex.payload, {"profile_to_import": 1}) @mock.patch("apps.ldap.ldap.get_user", return_value={"username": "******"}) def test_import_user_by_not_logged_in_user_raises_exception( self, mock_ldap_connection, mock_get_user): with self.assertRaises(SuperdeskApiError) as context: service = get_resource_service("import_profile") doc = { "username": "******", "password": "******", "profile_to_import": "barf" } service.post([doc]) ex = context.exception self.assertEqual(ex.message, "Invalid Credentials.") self.assertEqual(ex.status_code, 403) self.assertDictEqual(ex.payload, {"credentials": 1}) @mock.patch( "apps.ldap.ldap.ADAuth.authenticate_and_fetch_profile", side_effect=CredentialsAuthError(credentials={"username": "******"}, error="test"), ) @mock.patch("apps.ldap.ldap.get_user", return_value={"username": "******"}) def test_user_import_profile_with_invalid_credentials( self, mock_ldap_connection, mock_auth, mock_get_user): with self.assertRaises(SuperdeskApiError) as context: service = get_resource_service("import_profile") doc = { "username": "******", "password": "******", "profile_to_import": "barf" } service.post([doc]) ex = context.exception self.assertEqual(ex.message, "Invalid Credentials.") self.assertEqual(ex.status_code, 403) self.assertDictEqual(ex.payload, {"credentials": 1})