def test_08_split_user(self): user = split_user("user@realm") self.assertTrue(user == ("user", "realm"), user) user = split_user("user") self.assertTrue(user == ("user", ""), user) user = split_user("user@email@realm") self.assertTrue(user == ("user@email", "realm"), user) user = split_user("realm\\user") self.assertTrue(user == ("user", "realm"), user)
def test_08_split_user(self): user = split_user("user@realm1") self.assertTrue(user == ("user", "realm1"), user) user = split_user("user") self.assertTrue(user == ("user", ""), user) user = split_user("user@email@realm1") self.assertTrue(user == ("user@email", "realm1"), user) user = split_user("realm1\\user") self.assertTrue(user == ("user", "realm1"), user) # The user is not split, since there is no real "non_existing_realm.com" user = split_user("user@non_existing_realm.com") self.assertEqual(user, ("user@non_existing_realm.com", ""))
def is_remote_user_allowed(req): """ Checks if the REMOTE_USER server variable is allowed to be used. .. note:: This is not used as a decorator! :param req: The flask request, containing the remote user and the client IP :return: """ res = False if req.remote_user: loginname, realm = split_user(req.remote_user) realm = realm or get_default_realm() # Check if the remote user is allowed if "client_ip" not in g: g.client_ip = get_client_ip( req, get_from_config(SYSCONF.OVERRIDECLIENT)) if "policy_object" not in g: g.policy_object = PolicyClass() ruser_active = g.policy_object.get_action_values(ACTION.REMOTE_USER, scope=SCOPE.WEBUI, user=loginname, realm=realm, client=g.client_ip) res = ruser_active return res
def is_remote_user_allowed(req): """ Checks if the REMOTE_USER server variable is allowed to be used. .. note:: This is not used as a decorator! :param req: The flask request, containing the remote user and the client IP :return: """ res = False if req.remote_user: loginname, realm = split_user(req.remote_user) realm = realm or get_default_realm() # Check if the remote user is allowed client_ip = req.remote_addr if "policy_object" not in g: g.policy_object = PolicyClass() ruser_active = g.policy_object.get_action_values(ACTION.REMOTE_USER, scope=SCOPE.WEBUI, user=loginname, realm=realm, client=client_ip) res = ruser_active return res
def before_request(): """ This is executed before the request """ ensure_no_config_object() request.all_data = get_all_params(request.values, request.data) privacyidea_server = current_app.config.get("PI_AUDIT_SERVERNAME") or \ request.host g.policy_object = PolicyClass() g.audit_object = getAudit(current_app.config) g.event_config = EventConfiguration() # access_route contains the ip adresses of all clients, hops and proxies. g.client_ip = get_client_ip(request, get_from_config(SYSCONF.OVERRIDECLIENT)) g.audit_object.log({"success": False, "client": g.client_ip, "client_user_agent": request.user_agent.browser, "privacyidea_server": privacyidea_server, "action": "{0!s} {1!s}".format(request.method, request.url_rule), "action_detail": "", "info": ""}) username = getParam(request.all_data, "username") if username: # We only fill request.User, if we really have a username. # On endpoints like /auth/rights, this is not available loginname, realm = split_user(username) # overwrite the split realm if we have a realm parameter. Default back to default_realm realm = getParam(request.all_data, "realm", default=realm) or realm or get_default_realm() # Prefill the request.User. This is used by some pre-event handlers request.User = User(loginname, realm)
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. :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 = getParam(request.all_data, "realm") details = {} if username is None: raise AuthError(_("Authentication failure. Missing Username"), id=ERROR.AUTHENTICATE_MISSING_USERNAME) if realm: username = username + "@" + 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 loginname, realm = split_user(username) realm = realm or get_default_realm() 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)
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. :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 = request.all_data.get("username") password = request.all_data.get("password") realm = request.all_data.get("realm") details = {} if realm: username = username + "@" + realm g.audit_object.log({"user": username}) 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" if username is None: raise AuthError("Authentication failure", "missing Username", status=401) # Verify the password admin_auth = False user_auth = False loginname, realm = split_user(username) realm = realm or get_default_realm() # 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) 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) if role == ROLE.ADMIN: g.audit_object.log({"user": "", "administrator": username}) if not admin_auth and not user_auth: raise AuthError("Authentication failure", "Wrong credentials", status=401, details=details or {}) else: g.audit_object.log({"success": True}) # 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) else: import os import binascii nonce = binascii.hexlify(os.urandom(20)) rights = [] # 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) # 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}, details=details)
def get_webui_settings(request, response): """ This decorator is used in the /auth API to add configuration information like the logout_time or the policy_template_url to the response. :param request: flask request object :param response: flask response object :return: the response """ content = json.loads(response.data) # check, if the authentication was successful, then we need to do nothing if content.get("result").get("status") is True: _role = content.get("result").get("value").get("role") username = content.get("result").get("value").get("username") # get the realm _loginname, realm = split_user(username) if not realm: realm = get_default_realm() policy_object = g.policy_object try: client = request.remote_addr except Exception: client = None logout_time_pol = policy_object.get_action_values( action=ACTION.LOGOUTTIME, scope=SCOPE.WEBUI, realm=realm, client=client, unique=True) token_page_size_pol = policy_object.get_action_values( action=ACTION.TOKENPAGESIZE, scope=SCOPE.WEBUI, realm=realm, client=client, unique=True ) user_page_size_pol = policy_object.get_action_values( action=ACTION.USERPAGESIZE, scope=SCOPE.WEBUI, realm=realm, client=client, unique=True ) user_details_pol = policy_object.get_policies( action=ACTION.USERDETAILS, scope=SCOPE.WEBUI, realm=realm, client=client ) default_tokentype_pol = policy_object.get_action_values( action=ACTION.DEFAULT_TOKENTYPE, scope=SCOPE.WEBUI, realm=realm, client=client, unique=True ) token_page_size = DEFAULT_PAGE_SIZE user_page_size = DEFAULT_PAGE_SIZE default_tokentype = DEFAULT_TOKENTYPE if len(token_page_size_pol) == 1: token_page_size = int(token_page_size_pol[0]) if len(user_page_size_pol) == 1: user_page_size = int(user_page_size_pol[0]) if len(default_tokentype_pol) == 1: default_tokentype = default_tokentype_pol[0] logout_time = DEFAULT_LOGOUT_TIME if len(logout_time_pol) == 1: logout_time = int(logout_time_pol[0]) policy_template_url_pol = policy_object.get_action_values( action=ACTION.POLICYTEMPLATEURL, scope=SCOPE.WEBUI, client=client, unique=True) policy_template_url = DEFAULT_POLICY_TEMPLATE_URL if len(policy_template_url_pol) == 1: policy_template_url = policy_template_url_pol[0] content["result"]["value"]["logout_time"] = logout_time content["result"]["value"]["token_page_size"] = token_page_size content["result"]["value"]["user_page_size"] = user_page_size content["result"]["value"]["policy_template_url"] = policy_template_url content["result"]["value"]["default_tokentype"] = default_tokentype content["result"]["value"]["user_details"] = len(user_details_pol) > 0 response.data = json.dumps(content) return response
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. :type username: basestring :jsonparam password: The password/credentials of the user who wants to authenticate to the API. :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 = request.all_data.get("username") password = request.all_data.get("password") realm = "" secret = current_app.secret_key # 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 authtype = "password" if username is None: raise AuthError("Authentication failure", "missing Username", status=401) # Verify the password admin_auth = False user_auth = False if verify_db_admin(username, password): role = ROLE.ADMIN admin_auth = True if not admin_auth: # The user could not be identified against the admin database, # so we do the rest of the check username, realm = split_user(username) realm = realm or get_default_realm() user_obj = User(username, realm) options = {"g": g, "clientip": request.remote_addr} transaction_id = getParam(request.all_data, "transaction_id") state = getParam(request.all_data, "state") if transaction_id: options["transaction_id"] = transaction_id if state: options["state"] = state superuser_realms = current_app.config.get("SUPERUSER_REALM", []) user_auth, role, details = check_webui_user(user_obj, password, options=options, superuser_realms= superuser_realms) # The details with the transaction_id are raised with the AuthError details = details or {} if not admin_auth and not user_auth: raise AuthError("Authentication failure", "Wrong credentials", status=401, details=details) # 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 token = jwt.encode({"username": username, "realm": realm, "nonce": geturandom(hex=True), "role": role, "authtype": authtype, "exp": datetime.utcnow() + validity, "rights": "TODO"}, secret) g.audit_object.log({"success": True, "administrator": username, "jwt_token": token}) # 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": username, "realm": realm, "rights": "TODO"})
def get_webui_settings(request, response): """ This decorator is used in the /auth API to add configuration information like the logout_time or the policy_template_url to the response. :param request: flask request object :param response: flask response object :return: the response """ content = json.loads(response.data) # check, if the authentication was successful, then we need to do nothing if content.get("result").get("status") is True: _role = content.get("result").get("value").get("role") username = content.get("result").get("value").get("username") # get the realm _loginname, realm = split_user(username) if not realm: realm = get_default_realm() policy_object = g.policy_object try: client = request.remote_addr except Exception: client = None logout_time_pol = policy_object.get_action_values( action=ACTION.LOGOUTTIME, scope=SCOPE.WEBUI, realm=realm, client=client, unique=True) token_page_size_pol = policy_object.get_action_values( action=ACTION.TOKENPAGESIZE, scope=SCOPE.WEBUI, realm=realm, client=client, unique=True) user_page_size_pol = policy_object.get_action_values( action=ACTION.USERPAGESIZE, scope=SCOPE.WEBUI, realm=realm, client=client, unique=True) user_details_pol = policy_object.get_policies( action=ACTION.USERDETAILS, scope=SCOPE.WEBUI, realm=realm, client=client) default_tokentype_pol = policy_object.get_action_values( action=ACTION.DEFAULT_TOKENTYPE, scope=SCOPE.WEBUI, realm=realm, client=client, unique=True) token_page_size = DEFAULT_PAGE_SIZE user_page_size = DEFAULT_PAGE_SIZE default_tokentype = DEFAULT_TOKENTYPE if len(token_page_size_pol) == 1: token_page_size = int(token_page_size_pol[0]) if len(user_page_size_pol) == 1: user_page_size = int(user_page_size_pol[0]) if len(default_tokentype_pol) == 1: default_tokentype = default_tokentype_pol[0] logout_time = DEFAULT_LOGOUT_TIME if len(logout_time_pol) == 1: logout_time = int(logout_time_pol[0]) policy_template_url_pol = policy_object.get_action_values( action=ACTION.POLICYTEMPLATEURL, scope=SCOPE.WEBUI, client=client, unique=True) policy_template_url = DEFAULT_POLICY_TEMPLATE_URL if len(policy_template_url_pol) == 1: policy_template_url = policy_template_url_pol[0] content["result"]["value"]["logout_time"] = logout_time content["result"]["value"]["token_page_size"] = token_page_size content["result"]["value"]["user_page_size"] = user_page_size content["result"]["value"]["policy_template_url"] = policy_template_url content["result"]["value"]["default_tokentype"] = default_tokentype content["result"]["value"]["user_details"] = len(user_details_pol) > 0 response.data = json.dumps(content) return response