def api_endpoint(request, g): """ This provides a function to be plugged into the API endpoint /ttype/<tokentype> which is defined in api/ttype.py See :ref:`rest_ttype`. :param request: The Flask request :param g: The Flask global object g :return: Flask Response or text """ params = request.all_data action = getParam(params, "action", optional) or \ API_ACTIONS.AUTHENTICATION if action not in API_ACTIONS.ALLOWED_ACTIONS: raise ParameterError("Allowed actions are {0!s}".format( API_ACTIONS.ALLOWED_ACTIONS)) if action == API_ACTIONS.METADATA: session = getParam(params, "session", required) serial = getParam(params, "serial", required) # The user identifier is displayed in the App # We need to set the user ID tokens = get_tokens(serial=serial) if not tokens: # pragma: no cover raise ParameterError("No token with serial {0!s}".format(serial)) user_identifier, user_displayname = tokens[0].get_user_displayname() service_identifier = get_from_config("tiqr.serviceIdentifier") or\ "org.privacyidea" ocrasuite = get_from_config("tiqr.ocrasuite") or OCRA_DEFAULT_SUITE service_displayname = get_from_config("tiqr.serviceDisplayname") or \ "privacyIDEA" reg_server = get_from_config("tiqr.regServer") auth_server = get_from_config("tiqr.authServer") or reg_server logo_url = get_from_config("tiqr.logoUrl") service = {"displayName": service_displayname, "identifier": service_identifier, "logoUrl": logo_url, "infoUrl": "https://www.privacyidea.org", "authenticationUrl": "{0!s}".format(auth_server), "ocraSuite": ocrasuite, "enrollmentUrl": "{0!s}?action={1!s}&session={2!s}&serial={3!s}".format( reg_server, API_ACTIONS.ENROLLMENT, session, serial) } identity = {"identifier": user_identifier, "displayName": user_displayname } res = {"service": service, "identity": identity } return "json", res elif action == API_ACTIONS.ENROLLMENT: """ operation: register secret: HEX notificationType: GCM notificationAddress: ... language: de session: serial: """ res = "Fail" serial = getParam(params, "serial", required) session = getParam(params, "session", required) secret = getParam(params, "secret", required) # The secret needs to be stored in the token object. # We take the token "serial" and check, if it contains the "session" # in the tokeninfo. enroll_tokens = get_tokens(serial=serial) if len(enroll_tokens) == 1: if enroll_tokens[0].get_tokeninfo("session") == session: # save the secret enroll_tokens[0].set_otpkey(secret) # delete the session enroll_tokens[0].del_tokeninfo("session") res = "OK" else: raise ParameterError("Invalid Session") return "plain", res elif action == API_ACTIONS.AUTHENTICATION: res = "FAIL" userId = getParam(params, "userId", required) session = getParam(params, "sessionKey", required) passw = getParam(params, "response", required) operation = getParam(params, "operation", required) res = "INVALID_CHALLENGE" # The sessionKey is stored in the db_challenge.transaction_id # We need to get the token serial for this sessionKey challenges = get_challenges(transaction_id=session) # We found exactly one challenge if (len(challenges) == 1 and challenges[0].is_valid() and challenges[0].otp_valid is False): # Challenge is still valid (time has not passed) and no # correct response was given. serial = challenges[0].serial tokens = get_tokens(serial=serial) if len(tokens) == 1: # We found exactly the one token res = "INVALID_RESPONSE" r = tokens[0].verify_response( challenge=challenges[0].challenge, passw=passw) if r > 0: res = "OK" # Mark the challenge as answered successfully. challenges[0].set_otp_status(True) cleanup_challenges() return "plain", res
def api_endpoint(cls, request, g): """ This provides a function to be plugged into the API endpoint /ttype/<tokentype> which is defined in api/ttype.py See :ref:`rest_ttype`. :param request: The Flask request :param g: The Flask global object g :return: Flask Response or text """ params = request.all_data action = getParam(params, "action", optional) or \ API_ACTIONS.AUTHENTICATION if action not in API_ACTIONS.ALLOWED_ACTIONS: raise ParameterError("Allowed actions are {0!s}".format( API_ACTIONS.ALLOWED_ACTIONS)) if action == API_ACTIONS.METADATA: session = getParam(params, "session", required) serial = getParam(params, "serial", required) # The user identifier is displayed in the App # We need to set the user ID token = get_one_token(serial=serial, tokentype="tiqr") user_identifier, user_displayname = token.get_user_displayname() service_identifier = get_from_config("tiqr.serviceIdentifier") or\ "org.privacyidea" ocrasuite = get_from_config("tiqr.ocrasuite") or OCRA_DEFAULT_SUITE service_displayname = get_from_config("tiqr.serviceDisplayname") or \ "privacyIDEA" reg_server = get_from_config("tiqr.regServer") auth_server = get_from_config("tiqr.authServer") or reg_server logo_url = get_from_config("tiqr.logoUrl") info_url = get_from_config("tiqr.infoUrl") or \ "https://www.privacyidea.org" service = {"displayName": service_displayname, "identifier": service_identifier, "logoUrl": logo_url, "infoUrl": info_url, "authenticationUrl": "{0!s}".format(auth_server), "ocraSuite": ocrasuite, "enrollmentUrl": "{0!s}?action={1!s}&session={2!s}&serial={3!s}".format( reg_server, API_ACTIONS.ENROLLMENT, session, serial) } identity = {"identifier": user_identifier, "displayName": user_displayname } res = {"service": service, "identity": identity } return "json", res elif action == API_ACTIONS.ENROLLMENT: """ operation: register secret: HEX notificationType: GCM notificationAddress: ... language: de session: serial: """ res = "Fail" serial = getParam(params, "serial", required) session = getParam(params, "session", required) secret = getParam(params, "secret", required) # The secret needs to be stored in the token object. # We take the token "serial" and check, if it contains the "session" # in the tokeninfo. enroll_token = get_one_token(serial=serial, tokentype="tiqr") tokeninfo_session = enroll_token.get_tokeninfo("session") if tokeninfo_session and tokeninfo_session == session: # save the secret enroll_token.set_otpkey(secret) # delete the session enroll_token.del_tokeninfo("session") res = "OK" else: raise ParameterError("Invalid Session") return "plain", res elif action == API_ACTIONS.AUTHENTICATION: res = "FAIL" userId = getParam(params, "userId", required) session = getParam(params, "sessionKey", required) passw = getParam(params, "response", required) operation = getParam(params, "operation", required) res = "INVALID_CHALLENGE" # The sessionKey is stored in the db_challenge.transaction_id # We need to get the token serial for this sessionKey challenges = get_challenges(transaction_id=session) # We found several challenges with the given transaction ID, # and some of the challenges may belong to other tokens. # We only handle the TiQR tokens. for challenge in challenges: if challenge.is_valid() and challenge.otp_valid is False: # Challenge is still valid (time has not passed) and no # correct response was given. token = get_one_token(serial=challenge.serial) if token.type.lower() == "tiqr": # We found a TiQR token with a valid challenge with the given transaction ID r = token.verify_response( challenge=challenge.challenge, passw=passw) if r > 0: res = "OK" # Mark the challenge as answered successfully. challenge.set_otp_status(True) # We have found a valid TiQR token transaction, we break out of the loop break else: # Send back how may retries there are left for the token is blocked token.inc_failcount() fail = token.get_failcount() maxfail = token.get_max_failcount() res = "INVALID_RESPONSE:{0!s}".format(maxfail - fail) break cleanup_challenges() return "plain", res