def test_01_create_realm(self): rid = save_resolver({"resolver": self.resolvername1, "type": "passwdresolver", "fileName": "/etc/passwd"}) self.assertTrue(rid > 0, rid) rid = save_resolver({"resolver": self.resolvername2, "type": "passwdresolver", "fileName": "/etc/secrets"}) self.assertTrue(rid > 0, rid) (added, failed) = set_realm(self.realm1, [self.resolvername1, self.resolvername2]) self.assertTrue(len(failed) == 0) self.assertTrue(len(added) == 2) # test the realms realms = get_realms() self.assertTrue(self.realm1 in realms, realms) self.assertTrue(realms.get("realm1").get("default"), realms) # try to create realm with invalid name self.assertRaises(Exception, set_realm, "#####") # update the resolver list: (added, failed) = set_realm(self.realm1, [self.resolvername1, "non exiting"]) self.assertTrue(len(failed) == 1) self.assertTrue(len(added) == 1) self.assertTrue(realm_is_defined(self.realm1)) self.assertTrue(realm_is_defined("non exist") is False)
def split_user(username): """ Split the username of the form user@realm into the username and the realm splitting [email protected]@realm is also possible and will return (myemail@emailprovider, realm). If for a user@domain the "domain" does not exist as realm, the name is not split, since it might be the user@domain in the default realm We can also split realm\\user to (user, realm) :param username: the username to split :type username: string :return: username and realm :rtype: tuple """ from privacyidea.lib.realm import realm_is_defined user = username.strip() realm = "" l = user.split('@') if len(l) >= 2: if realm_is_defined(l[-1]): # split the last only if the last part is really a realm (user, realm) = user.rsplit('@', 1) else: l = user.split('\\') if len(l) >= 2: (realm, user) = user.rsplit('\\', 1) return user, realm
def split_user(username): """ Split the username of the form user@realm into the username and the realm splitting [email protected]@realm is also possible and will return ([email protected], realm). If for a user@domain the "domain" does not exist as realm, the name is not split, since it might be the user@domain in the default realm We can also split realm\\user to (user, realm) :param username: the username to split :type username: string :return: username and realm :rtype: tuple """ from privacyidea.lib.realm import realm_is_defined user = username.strip() realm = "" l = user.split('@') if len(l) >= 2: if realm_is_defined(l[-1]): # split the last only if the last part is really a realm (user, realm) = user.rsplit('@', 1) else: l = user.split('\\') if len(l) >= 2: (realm, user) = user.rsplit('\\', 1) return user, realm
def test_01_create_realm(self): rid = save_resolver({ "resolver": self.resolvername1, "type": "passwdresolver", "fileName": "/etc/passwd" }) self.assertTrue(rid > 0, rid) rid = save_resolver({ "resolver": self.resolvername2, "type": "passwdresolver", "fileName": "/etc/secrets" }) self.assertTrue(rid > 0, rid) (added, failed) = set_realm(self.realm1, [self.resolvername1, self.resolvername2]) self.assertTrue(len(failed) == 0) self.assertTrue(len(added) == 2) (added, failed) = set_realm(self.realm_dot, [self.resolvername1, self.resolvername2]) self.assertTrue(len(failed) == 0) self.assertTrue(len(added) == 2) # test the realms realms = get_realms() self.assertTrue(self.realm1 in realms, realms) self.assertTrue(realms.get("realm1").get("default"), realms) self.assertTrue(self.realm_dot in realms, realms) # delete dot realm delete_realm(self.realm_dot) # try to create realm with invalid name self.assertRaises(Exception, set_realm, "#####") # update the resolver list: (added, failed) = set_realm(self.realm1, [self.resolvername1, "non exiting"]) self.assertTrue(len(failed) == 1) self.assertTrue(len(added) == 1) self.assertTrue(realm_is_defined(self.realm1)) self.assertTrue(realm_is_defined("non exist") is False)
def get_auth_token(): """ This call verifies the credentials of the user and issues an authentication token, that is used for the later API calls. The authentication token has a validity, that is usually 1 hour. :jsonparam username: The username of the user who wants to authenticate to the API. :jsonparam password: The password/credentials of the user who wants to authenticate to the API. :jsonparam realm: The realm where the user will be searched. :return: A json response with an authentication token, that needs to be used in any further request. :status 200: in case of success :status 401: if authentication fails **Example Authentication Request**: .. sourcecode:: http POST /auth HTTP/1.1 Host: example.com Accept: application/json username=admin password=topsecret **Example Authentication Response**: .. sourcecode:: http HTTP/1.0 200 OK Content-Length: 354 Content-Type: application/json { "id": 1, "jsonrpc": "2.0", "result": { "status": true, "value": { "token": "eyJhbGciOiJIUz....jdpn9kIjuGRnGejmbFbM" } }, "version": "privacyIDEA unknown" } **Response for failed authentication**: .. sourcecode:: http HTTP/1.1 401 UNAUTHORIZED Content-Type: application/json Content-Length: 203 { "id": 1, "jsonrpc": "2.0", "result": { "error": { "code": -401, "message": "missing Authorization header" }, "status": false }, "version": "privacyIDEA unknown", "config": { "logout_time": 30 } } """ validity = timedelta(hours=1) username = getParam(request.all_data, "username") password = getParam(request.all_data, "password") realm_param = getParam(request.all_data, "realm") details = {} realm = '' # the realm parameter has precedence! Check if it exists if realm_param and not realm_is_defined(realm_param): raise AuthError(_("Authentication failure. Unknown realm: {0!s}.".format(realm_param)), id=ERROR.AUTHENTICATE_WRONG_CREDENTIALS) if username is None: raise AuthError(_("Authentication failure. Missing Username"), id=ERROR.AUTHENTICATE_MISSING_USERNAME) loginname, realm = split_user(username) # overwrite the split realm if we have a realm parameter if realm_param: realm = realm_param # and finally check if there is a realm realm = realm or get_default_realm() # Failsafe to have the user attempt in the log, whatever happens # This can be overwritten later g.audit_object.log({"user": username, "realm": realm}) secret = current_app.secret_key superuser_realms = current_app.config.get("SUPERUSER_REALM", []) # This is the default role for the logged in user. # The role privileges may be risen to "admin" role = ROLE.USER # The way the user authenticated. This could be # "password" = The admin user DB or the user store # "pi" = The admin or the user is authenticated against privacyIDEA # "remote_user" = authenticated by webserver authtype = "password" # Verify the password admin_auth = False user_auth = False user_obj = User() # Check if the remote user is allowed if (request.remote_user == username) and is_remote_user_allowed(request): # Authenticated by the Web Server # Check if the username exists # 1. in local admins # 2. in a realm # 2a. is an admin realm authtype = "remote_user " if db_admin_exist(username): role = ROLE.ADMIN admin_auth = True g.audit_object.log({"success": True, "user": "", "administrator": username, "info": "internal admin"}) else: # check, if the user exists user_obj = User(loginname, realm) g.audit_object.log({"user": user_obj.login, "realm": user_obj.realm, "info": log_used_user(user_obj)}) if user_obj.exist(): user_auth = True if user_obj.realm in superuser_realms: role = ROLE.ADMIN admin_auth = True elif verify_db_admin(username, password): role = ROLE.ADMIN admin_auth = True # This admin is not in the default realm! realm = "" g.audit_object.log({"success": True, "user": "", "administrator": username, "info": "internal admin"}) else: # The user could not be identified against the admin database, # so we do the rest of the check options = {"g": g, "clientip": g.client_ip} for key, value in request.all_data.items(): if value and key not in ["g", "clientip"]: options[key] = value user_obj = User(loginname, realm) user_auth, role, details = check_webui_user(user_obj, password, options=options, superuser_realms= superuser_realms) details = details or {} if role == ROLE.ADMIN: g.audit_object.log({"user": "", "administrator": user_obj.login, "realm": user_obj.realm, "resolver": user_obj.resolver, "serial": details.get('serial', None), "info": u"{0!s}|loginmode={1!s}".format(log_used_user(user_obj), details.get("loginmode"))}) else: g.audit_object.log({"user": user_obj.login, "realm": user_obj.realm, "resolver": user_obj.resolver, "serial": details.get('serial', None), "info": u"{0!s}|loginmode={1!s}".format(log_used_user(user_obj), details.get("loginmode"))}) if not admin_auth and not user_auth: raise AuthError(_("Authentication failure. Wrong credentials"), id=ERROR.AUTHENTICATE_WRONG_CREDENTIALS, details=details or {}) else: g.audit_object.log({"success": True}) request.User = user_obj # If the HSM is not ready, we need to create the nonce in another way! hsm = init_hsm() if hsm.is_ready: nonce = geturandom(hex=True) # Add the role to the JWT, so that we can verify it internally # Add the authtype to the JWT, so that we could use it for access # definitions rights = g.policy_object.ui_get_rights(role, realm, loginname, g.client_ip) menus = g.policy_object.ui_get_main_menus({"username": loginname, "role": role, "realm": realm}, g.client_ip) else: import os nonce = hexlify_and_unicode(os.urandom(20)) rights = [] menus = [] # What is the log level? log_level = current_app.config.get("PI_LOGLEVEL", 30) token = jwt.encode({"username": loginname, "realm": realm, "nonce": nonce, "role": role, "authtype": authtype, "exp": datetime.utcnow() + validity, "rights": rights}, secret, algorithm='HS256').decode('utf8') # Add the role to the response, so that the WebUI can make decisions # based on this (only show selfservice, not the admin part) return send_result({"token": token, "role": role, "username": loginname, "realm": realm, "log_level": log_level, "rights": rights, "menus": menus}, details=details)