14.2.1.7. API Policies

14.2.1.7.1. Pre Policies

These are the policy decorators as PRE conditions for the API calls. I.e. these conditions are executed before the wrapped API call. This module uses the policy base functions from privacyidea.lib.policy but also components from flask like g.

Wrapping the functions in a decorator class enables easy modular testing.

The functions of this module are tested in tests/test_api_lib_policy.py

privacyidea.api.lib.prepolicy.allowed_audit_realm(request=None, action=None)[source]

This decorator function takes the request and adds additional parameters to the request according to the policy for the SCOPE.ADMIN or ACTION.AUDIT :param request: :param action: :return: True

privacyidea.api.lib.prepolicy.api_key_required(request=None, action=None)[source]

This is a decorator for check_user_pass and check_serial_pass. It checks, if a policy scope=auth, action=apikeyrequired is set. If so, the validate request will only performed, if a JWT token is passed with role=validate.

privacyidea.api.lib.prepolicy.auditlog_age(request=None, action=None)[source]

This pre condition checks for the policy auditlog_age and set the “timelimit” parameter of the audit search API.

Check ACTION.AUDIT_AGE

The decorator can wrap GET /audit/

Parameters
  • request (Request Object) – The request that is intercepted during the API call

  • action (basestring) – An optional Action

Returns

Always true. Modified the parameter request

privacyidea.api.lib.prepolicy.check_admin_tokenlist(request=None, action=None)[source]

Depending on the policy scope=admin, action=tokenlist, the allowed_realms parameter is set to define, the token of which realms and administrator is allowed to see.

Sets the allowed_realms None: means the admin has no restrictions []: the admin can not see any realms [“realm1”, “realm2”…]: the admin can see these realms

Parameters

request

Returns

privacyidea.api.lib.prepolicy.check_anonymous_user(request=None, action=None)[source]

This decorator function takes the request and verifies the given action for the SCOPE USER without an authenticated user but the user from the parameters.

This is used with password_reset

Parameters
  • request

  • action

Returns

True otherwise raises an Exception

privacyidea.api.lib.prepolicy.check_application_tokentype(request=None, action=None)[source]

This pre policy checks if the request is allowed to specify the tokentype. If the policy is not set, a possibly set parameter “type” is removed from the request.

Check ACTION.APPLICATION_TOKENTYPE

This decorator should wrap

/validate/check, /validate/samlcheck and /validate/triggerchallenge.

Parameters
  • request (Request Object) – The request that is intercepted during the API call

  • action (basestring) – An optional Action

Returns

Always true. Modified the parameter request

privacyidea.api.lib.prepolicy.check_base_action(request=None, action=None, anonymous=False)[source]

This decorator function takes the request and verifies the given action for the SCOPE ADMIN or USER.

Parameters
  • request

  • action

  • anonymous – If set to True, the user data is taken from the request parameters.

Returns

True otherwise raises an Exception

privacyidea.api.lib.prepolicy.check_external(request=None, action='init')[source]

This decorator is a hook to an external check function, that is called before the token/init or token/assign API.

Parameters
  • request (flask Request object) – The REST request

  • action (basestring) – This is either “init” or “assign”

Returns

either True or an Exception is raised

privacyidea.api.lib.prepolicy.check_max_token_realm(request=None, action=None)[source]

Pre Policy This checks the maximum token per realm. Check ACTION.MAXTOKENREALM

This decorator can wrap:

/token/init (with a realm and user) /token/assign /token/tokenrealms

Parameters
  • req (Request Object) – The request that is intercepted during the API call

  • action (basestring) – An optional Action

Returns

True otherwise raises an Exception

privacyidea.api.lib.prepolicy.check_max_token_user(request=None, action=None)[source]

Pre Policy This checks the maximum token per user policy. Check ACTION.MAXTOKENUSER Check ACTION.MAXACTIVETOKENUSER

This decorator can wrap:

/token/init (with a realm and user) /token/assign

Parameters
  • req

  • action

Returns

True otherwise raises an Exception

privacyidea.api.lib.prepolicy.check_otp_pin(request=None, action=None)[source]

This policy function checks if the OTP PIN that is about to be set follows the OTP PIN policies ACTION.OTPPINMAXLEN, ACTION.OTPPINMINLEN and ACTION.OTPPINCONTENTS and token-type-specific PIN policy actions in the SCOPE.USER or SCOPE.ADMIN. It is used to decorate the API functions.

The pin is investigated in the params as “otppin” or “pin”

In case the given OTP PIN does not match the requirements an exception is raised.

privacyidea.api.lib.prepolicy.check_token_init(request=None, action=None)[source]

This decorator function takes the request and verifies if the requested tokentype is allowed to be enrolled in the SCOPE ADMIN or the SCOPE USER. :param request: :param action: :return: True or an Exception is raised

privacyidea.api.lib.prepolicy.check_token_upload(request=None, action=None)[source]

This decorator function takes the request and verifies the given action for scope ADMIN :param req: :param filename: :return:

privacyidea.api.lib.prepolicy.encrypt_pin(request=None, action=None)[source]

This policy function is to be used as a decorator for several API functions. E.g. token/assign, token/setpin, token/init If the policy is set to define the PIN to be encrypted, the request.all_data is modified like this: encryptpin = True

It uses the policy SCOPE.ENROLL, ACTION.ENCRYPTPIN

privacyidea.api.lib.prepolicy.enroll_pin(request=None, action=None)[source]

This policy function is used as decorator for init token. It checks, if the user or the admin is allowed to set a token PIN during enrollment. If not, it deleted the PIN from the request.

privacyidea.api.lib.prepolicy.indexedsecret_force_attribute(request, action)[source]

This is a token specific wrapper for indexedsecret token for the endpoint /token/init The otpkey is overwritten with the value from the user attribute specified in policy scope=SCOPE.USER and SCOPE.ADMIN, action=PIIXACTION.FORCE_ATTRIBUTE. :param request: :param action: :return:

privacyidea.api.lib.prepolicy.init_random_pin(request=None, action=None)[source]

This policy function is to be used as a decorator in the API init function If the policy is set accordingly it adds a random PIN to the request.all_data like.

It uses the policy SCOPE.ENROLL, ACTION.OTPPINRANDOM and ACTION.OTPPINCONTENTS to set a random OTP PIN during Token enrollment

privacyidea.api.lib.prepolicy.init_token_defaults(request=None, action=None)[source]

This policy function is used as a decorator for the API init function. Depending on policy settings it can add token specific default values like totp_hashlib, hotp_hashlib, totp_otplen…

privacyidea.api.lib.prepolicy.init_tokenlabel(request=None, action=None)[source]

This policy function is to be used as a decorator in the API init function. It adds the tokenlabel definition to the params like this: params : { “tokenlabel”: “<u>@<r>” }

In addition it adds the tokenissuer to the params like this: params : { “tokenissuer”: “privacyIDEA instance” }

It also checks if the force_app_pin policy is set and adds the corresponding value to params.

It uses the policy SCOPE.ENROLL, ACTION.TOKENLABEL and ACTION.TOKENISSUER to set the tokenlabel and tokenissuer of Smartphone tokens during enrollment and this fill the details of the response.

privacyidea.api.lib.prepolicy.is_remote_user_allowed(req)[source]

Checks if the REMOTE_USER server variable is allowed to be used.

Note

This is not used as a decorator!

Parameters

req – The flask request, containing the remote user and the client IP

Returns

a bool value

privacyidea.api.lib.prepolicy.mangle(request=None, action=None)[source]

This pre condition checks if either of the parameters pass, user or realm in a validate/check request should be rewritten based on an authentication policy with action “mangle”. See mangle for an example.

Check ACTION.MANGLE

This decorator should wrap

/validate/check

Parameters
  • request (Request Object) – The request that is intercepted during the API call

  • action (basestring) – An optional Action

Returns

Always true. Modified the parameter request

privacyidea.api.lib.prepolicy.mock_fail(req, action)[source]

This is a mock function as an example for check_external. This function creates a problem situation and the token/init or token/assign will show this exception accordingly.

privacyidea.api.lib.prepolicy.mock_success(req, action)[source]

This is a mock function as an example for check_external. This function returns success and the API call will go on unmodified.

privacyidea.api.lib.prepolicy.papertoken_count(request=None, action=None)[source]

This is a token specific wrapper for paper token for the endpoint /token/init. According to the policy scope=SCOPE.ENROLL, action=PAPERACTION.PAPER_COUNT it sets the parameter papertoken_count to enroll a paper token with such many OTP values.

Parameters
  • request

  • action

Returns

class privacyidea.api.lib.prepolicy.prepolicy(function, request, action=None)[source]

This is the decorator wrapper to call a specific function before an API call. The prepolicy decorator is to be used in the API calls. A prepolicy decorator then will modify the request data or raise an exception

privacyidea.api.lib.prepolicy.pushtoken_add_config(request, action)[source]

This is a token specific wrapper for push token for the endpoint /token/init According to the policy scope=SCOPE.ENROLL, action=SSL_VERIFY or action=FIREBASE_CONFIG the parameters are added to the enrollment step. :param request: :param action: :return:

privacyidea.api.lib.prepolicy.pushtoken_disable_wait(request, action)[source]

This is used for the /auth endpoint and sets the PUSH_ACTION.WAIT parameter to False.

Parameters
  • request

  • action

Returns

privacyidea.api.lib.prepolicy.pushtoken_wait(request, action)[source]

This is a auth specific wrapper to decorate /validate/check According to the policy scope=SCOPE.AUTH, action=push_wait

Parameters
  • request

  • action

Returns

privacyidea.api.lib.prepolicy.realmadmin(request=None, action=None)[source]

This decorator adds the first REALM to the parameters if the administrator, calling this API is a realm admin. This way, if the admin calls e.g. GET /user without realm parameter, he will not see all users, but only users in one of his realms.

TODO: If a realm admin is allowed to see more than one realm,

this is not handled at the moment. We need to change the underlying library functions!

Parameters
  • request – The HTTP reqeust

  • action – The action like ACTION.USERLIST

privacyidea.api.lib.prepolicy.required_email(request=None, action=None)[source]

This precondition checks if the “email” parameter matches the regular expression in the policy scope=register, action=requiredemail. See requiredemail.

Check ACTION.REQUIREDEMAIL

This decorator should wrap POST /register

Parameters
  • request – The Request Object

  • action – An optional Action

Returns

Modifies the request parameters or raises an Exception

privacyidea.api.lib.prepolicy.save_client_application_type(request, action)[source]

This decorator is used to write the client IP and the HTTP user agent ( clienttype) to the database.

In fact this is not a policy decorator, as it checks no policy. In fact, we could however one day define this as a policy, too. :param req: :return:

privacyidea.api.lib.prepolicy.set_random_pin(request=None, action=None)[source]

This policy function is to be used as a decorator in the API setrandompin function If the policy is set accordingly it adds a random PIN to the request.all_data like.

It uses the policy ACTION.OTPPINSETRANDOM in SCOPE.ADMIN or SCOPE.USER to set a random OTP PIN

privacyidea.api.lib.prepolicy.set_realm(request=None, action=None)[source]

Pre Policy This pre condition gets the current realm and verifies if the realm should be rewritten due to the policy definition. I takes the realm from the request and - if a policy matches - replaces this realm with the realm defined in the policy

Check ACTION.SETREALM

This decorator should wrap

/validate/check

Parameters
  • request (Request Object) – The request that is intercepted during the API call

  • action (basestring) – An optional Action

Returns

Always true. Modified the parameter request

privacyidea.api.lib.prepolicy.sms_identifiers(request=None, action=None)[source]

This is a token specific wrapper for sms tokens to be used with the endpoint /token/init. According to the policy scope=SCOPE.ADMIN or scope=SCOPE.USER action=SMSACTION.GATEWAYS the sms.identifier is only allowed to be set to the listed gateways.

Parameters
  • request

  • action

Returns

privacyidea.api.lib.prepolicy.tantoken_count(request=None, action=None)[source]

This is a token specific wrapper for tan token for the endpoint /token/init. According to the policy scope=SCOPE.ENROLL, action=TANACTION.TANTOKEN_COUNT it sets the parameter tantoken_count to enroll a tan token with such many OTP values.

Parameters
  • request

  • action

Returns

privacyidea.api.lib.prepolicy.twostep_enrollment_activation(request=None, action=None)[source]

This policy function enables the two-step enrollment process according to the configured policies. It is used to decorate the /token/init endpoint.

If a <type>_2step policy matches, the 2stepinit parameter is handled according to the policy. If no policy matches, the 2stepinit parameter is removed from the request data.

privacyidea.api.lib.prepolicy.twostep_enrollment_parameters(request=None, action=None)[source]

If the 2stepinit parameter is set to true, this policy function reads additional configuration from policies and adds it to request.all_data, that is:

  • {type}_2step_serversize is written to 2step_serversize

  • {type}_2step_clientsize is written to 2step_clientsize

  • {type}_2step_difficulty is written to 2step_difficulty

If no policy matches, the value passed by the user is kept.

This policy function is used to decorate the /token/init endpoint.

privacyidea.api.lib.prepolicy.u2ftoken_allowed(request, action)[source]
This is a token specific wrapper for u2f token for the endpoint

/token/init. According to the policy scope=SCOPE.ENROLL, action=U2FACTION.REQ it checks, if the assertion certificate is an allowed U2F token type.

If the token, which is enrolled contains a non allowed attestation certificate, we bail out.

Parameters
  • request

  • action

Returns

privacyidea.api.lib.prepolicy.u2ftoken_verify_cert(request, action)[source]

This is a token specific wrapper for u2f token for the endpoint /token/init According to the policy scope=SCOPE.ENROLL, action=U2FACTION.NO_VERIFY_CERT it can add a parameter to the enrollment parameters to not verify the attestation certificate. The default is to verify the cert. :param request: :param action: :return:

privacyidea.api.lib.prepolicy.webauthntoken_allowed(request, action)[source]

This is a token specific wrapper for WebAuthn token for the endpoint /token/init.

According to the policy scope=SCOPE.ENROLL, action=WEBAUTHNACTION.REQ it checks, if the assertion certificate is for an allowed WebAuthn token type. According to the policy scope=SCOPE.ENROLL, action=WEBAUTHNACTION.AUTHENTICATOR_SELECTION_LIST it checks, whether the AAGUID is whitelisted. Note: If self-attestation is allowed, it is – of course – possible to bypass the check for WEBAUTHNACTION.REQ

If the token, which is being enrolled does not contain an allowed attestation certificate, or does not have an allowed AAGUID, we bail out.

A very similar check (same policy actions, different policy scope) is performed during authorization, however due to architectural limitations, this lives within the token implementation itself.

Parameters
  • request

  • action

Returns

Return type

privacyidea.api.lib.prepolicy.webauthntoken_auth(request, action)[source]

This is a WebAuthn token specific wrapper for the endpoints /validate/triggerchallenge, /validate/check, and /auth.

This will enrich the challenge creation request for WebAuthn tokens with the necessary configuration information from policy actions with scope=SCOPE.AUTH. The request will be augmented with the allowed transports and the text to display to the user when asking to confirm the challenge on the token, as specified by the actions WEBAUTHNACTION.ALLOWED_TRANSPORTS, and ACTION.CHALLENGETEXT, respectively.

Both of these policies are optional, and have sensible defaults.

Parameters
  • request

  • action

Returns

Return type

privacyidea.api.lib.prepolicy.webauthntoken_authz(request, action)[source]

This is a WebAuthn token specific wrapper for the /auth, and /validate/check endpoints.

This will enrich the authorization request for WebAuthn tokens with the necessary configuration information from policy actions with scope=SCOPE.AUTHZ. This is currently the authorization pendant to webauthntoken_allowed(), but maybe expanded to cover other authorization policies in the future, should any be added. The request will as of now simply be augmented with the policies the attestation certificate is to be matched against.

Parameters
  • request

  • action

Returns

Return type

privacyidea.api.lib.prepolicy.webauthntoken_enroll(request, action)[source]

This is a token specific wrapper for the WebAuthn token for the endpoint /token/init.

This will enrich the initialization request for WebAuthn tokens with the necessary configuration information from policy actions with scope=SCOPE.ENROLL. The request will be augmented with a name and id for the relying party, as specified by the with actions WEBAUTHNACTION.RELYING_PARTY_NAME and WEBAUTHNACTION.RELYING_PARTY_ID, respectively, authenticator attachment preference, public key credential algorithm preferences, authenticator attestation requirement level, authenticator attestation requirement form, allowed AAGUIDs, and the text to display to the user when asking to confirm the challenge on the token, as specified by the actions WEBAUTHNACTION.AUTHENTICATOR_ATTACHMENT, WEBAUTHNACTION.PUBLIC_KEY_CREDENTIAL_ALGORITHM_PREFERENCE, WEBAUTHNACTION.AUTHENTICATOR_ATTESTATION_LEVEL, WEBAUTHNACTION.AUTHENTICATOR_ATTESTATION_FORM, WEBAUTHNACTION.AUTHENTICATOR_SELECTION_LIST, and ACTION.CHALLENGETEXT, respectively.

Setting WEBAUTHNACTION.RELYING_PARTY_NAME and WEBAUTHNACTION.RELYING_PARTY_ID is mandatory, and if either of these is not set, we bail out.

Parameters
  • request

  • action

Returns

Return type

privacyidea.api.lib.prepolicy.webauthntoken_request(request, action)[source]

This is a WebAuthn token specific wrapper for all endpoints using WebAuthn tokens.

This wraps the endpoints /token/init, /validate/triggerchallenge, /auth, and /validate/check. It will add WebAuthn configuration information to the requests, wherever a piece of information is needed for several different requests and thus cannot be provided by one of the more specific wrappers without adding unnecessary redundancy.

Depending on the type of request, the request will be augmented with some (or all) of the authenticator timeout, user verification requirement and list of allowed AAGUIDs for the current scope, as specified by the policies with the determined scope and the actions WEBAUTHNACTION.TIMEOUT, WEBAUTHNACTION.USER_VERIFICATION_REQUIREMENT, and WEBAUTHNACTION.AUTHENTICATOR_SELECTION_LIST, respectively.

The value of the ORIGIN http header will also be added to the request for the ENROLL and AUTHZ scopes. This is to make the unit tests not require mocking.

Parameters
  • request

  • action

Returns

Return type

14.2.1.7.2. Post Policies

These are the policy decorators as POST conditions for the API calls. I.e. these conditions are executed after the wrapped API call. This module uses the policy base functions from privacyidea.lib.policy but also components from flask like g.

Wrapping the functions in a decorator class enables easy modular testing.

The functions of this module are tested in tests/test_api_lib_policy.py

privacyidea.api.lib.postpolicy.add_user_detail_to_response(request, response)[source]

This policy decorated is used in the AUTHZ scope. If the boolean value add_user_in_response is set, the details will contain a dictionary “user” with all user details.

Parameters
  • request

  • response

Returns

privacyidea.api.lib.postpolicy.autoassign(request, response)[source]

This decorator decorates the function /validate/check. Depending on ACTION.AUTOASSIGN it checks if the user has no token and if the given OTP-value matches a token in the users realm, that is not yet assigned to any user.

If a token can be found, it assigns the token to the user also taking into account ACTION.MAXTOKENUSER and ACTION.MAXTOKENREALM. :return:

privacyidea.api.lib.postpolicy.check_serial(request, response)[source]

This policy function is to be used in a decorator of an API function. It checks, if the token, that was used in the API call has a serial number that is allowed to be used.

If not, a PolicyException is raised.

Parameters

response (Response object) – The response of the decorated function

Returns

A new (maybe modified) response

privacyidea.api.lib.postpolicy.check_tokeninfo(request, response)[source]

This policy function is used as a decorator for the validate API. It checks after a successful authentication if the token has a matching tokeninfo field. If it does not match, authorization is denied. Then a PolicyException is raised.

Parameters

response (Response object) – The response of the decorated function

Returns

A new modified response

privacyidea.api.lib.postpolicy.check_tokentype(request, response)[source]

This policy function is to be used in a decorator of an API function. It checks, if the token, that was used in the API call is of a type that is allowed to be used.

If not, a PolicyException is raised.

Parameters

response (Response object) – The response of the decorated function

Returns

A new (maybe modified) response

privacyidea.api.lib.postpolicy.construct_radius_response(request, response)[source]

This decorator implements the /validate/radiuscheck endpoint. In case this URL was requested, a successful authentication results in an empty response with a HTTP 204 status code. An unsuccessful authentication results in an empty response with a HTTP 400 status code. :return:

privacyidea.api.lib.postpolicy.get_webui_settings(request, response)[source]

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

privacyidea.api.lib.postpolicy.is_authorized(request, response)[source]

This policy decorator is used in the AUTHZ scope to decorate the /validate/check and /validate/triggerchallenge endpoint. I will cause authentication to fail, if the policy authorized=deny_access is set.

Parameters
  • request

  • response

Returns

privacyidea.api.lib.postpolicy.mangle_challenge_response(request, response)[source]

This policy decorator is used in the AUTH scope to decorate the /validate/check endpoint. It can modify the contents of the response “detail”->”message” to allow a better readability for a challenge response text.

Parameters
  • request

  • response

Returns

privacyidea.api.lib.postpolicy.no_detail_on_fail(request, response)[source]

This policy function is used with the AUTHZ scope. If the boolean value no_detail_on_fail is set, the details will be stripped if the authentication request failed.

Parameters
  • request

  • response

Returns

privacyidea.api.lib.postpolicy.no_detail_on_success(request, response)[source]

This policy function is used with the AUTHZ scope. If the boolean value no_detail_on_success is set, the details will be stripped if the authentication request was successful.

Parameters
  • request

  • response

Returns

privacyidea.api.lib.postpolicy.offline_info(request, response)[source]

This decorator is used with the function /validate/check. It is not triggered by an ordinary policy but by a MachineToken definition. If for the given Client and Token an offline application is defined, the response is enhanced with the offline information - the hashes of the OTP.

class privacyidea.api.lib.postpolicy.postpolicy(function, request=None)[source]

Decorator that allows one to call a specific function after the decorated function. The postpolicy decorator is to be used in the API calls.

class privacyidea.api.lib.postpolicy.postrequest(function, request=None)[source]

Decorator that is supposed to be used with after_request.

privacyidea.api.lib.postpolicy.save_pin_change(request, response, serial=None)[source]

This policy function checks if the next_pin_change date should be stored in the tokeninfo table.

  1. Check scope:enrollment and ACTION.CHANGE_PIN_FIRST_USE. This action is used, when the administrator enrolls a token or sets a PIN

  2. Check scope:enrollment and ACTION.CHANGE_PIN_EVERY is used, if the user changes the PIN.

This function decorates /token/init and /token/setpin. The parameter “pin” and “otppin” is investigated.

Parameters
  • request

  • action

Returns

privacyidea.api.lib.postpolicy.sign_response(request, response)[source]

This decorator is used to sign the response. It adds the nonce from the request, if it exist and adds the nonce and the signature to the response.

Note

This only works for JSON responses. So if we fail to decode the JSON, we just pass on.

The usual way to use it is, to wrap the after_request, so that we can also sign errors.

@postrequest(sign_response, request=request) def after_request(response):

Parameters
  • request – The Request object

  • response – The Response object