diff --git a/docs/janssen-server/developer/interception-scripts.md b/docs/janssen-server/developer/interception-scripts.md index 2824bbeaaa8..751c177bd8e 100644 --- a/docs/janssen-server/developer/interception-scripts.md +++ b/docs/janssen-server/developer/interception-scripts.md @@ -297,7 +297,7 @@ Output: }, "modified": true, "internal": true, - "locationType": "file", + "locationType": "db", "locationPath": "string", "baseDn": "string" } diff --git a/docs/janssen-server/developer/scripts/README.md b/docs/janssen-server/developer/scripts/README.md index bb14b82c76a..411474839f2 100644 --- a/docs/janssen-server/developer/scripts/README.md +++ b/docs/janssen-server/developer/scripts/README.md @@ -303,7 +303,7 @@ Output: }, "modified": true, "internal": true, - "locationType": "file", + "locationType": "db", "locationPath": "string", "baseDn": "string" } diff --git a/docs/script-catalog/discovery/discovery/README.md b/docs/script-catalog/discovery/discovery/README.md index c9fbd6045ae..e2d297eec0d 100644 --- a/docs/script-catalog/discovery/discovery/README.md +++ b/docs/script-catalog/discovery/discovery/README.md @@ -36,7 +36,7 @@ The discovery interception script extends the base script type with the methods The `configurationAttributes` parameter is `java.util.Map`. configurationAttributes = new HashMap(); - configurationAttributes.put("Location Type", new SimpleCustomProperty("location_type", "MySQL", "Storage Location for the script")); + configurationAttributes.put("Location Type", new SimpleCustomProperty("location_type", "db", "Storage Location for the script")); ### Snippet diff --git a/docs/script-catalog/introspection/README.md b/docs/script-catalog/introspection/README.md index ac49cbde510..6a4518c0937 100644 --- a/docs/script-catalog/introspection/README.md +++ b/docs/script-catalog/introspection/README.md @@ -29,7 +29,7 @@ The introspection interception script extends the base script type with the meth The `configurationAttributes` parameter is `java.util.Map`. configurationAttributes = new HashMap(); - configurationAttributes.put("Location Type", new SimpleCustomProperty("location_type", "MySQL", "Storage Location for the script")); + configurationAttributes.put("Location Type", new SimpleCustomProperty("location_type", "db", "Storage Location for the script")); ### Snippet diff --git a/docs/script-catalog/introspection/interception-scripts-debug.md b/docs/script-catalog/introspection/interception-scripts-debug.md index 1aa4eaf6aff..2755b84428d 100644 --- a/docs/script-catalog/introspection/interception-scripts-debug.md +++ b/docs/script-catalog/introspection/interception-scripts-debug.md @@ -414,7 +414,7 @@ For Jython scripts, we need additional steps to enable breakpoints. ![LDAP basic script ](../../../assets/basic_script.png) -1. Choose to load the script from file instead of ldap. Inside the browser change `jansModuleProperty` with value `{"value1":"location_type","value2":"ldap","description":""}` to `{"value1":"location_type","value2":"file","description":""}` +1. Choose to load the script from file instead of db. Inside the browser change `jansModuleProperty` with value `{"value1":"location_type","value2":"db","description":""}` to `{"value1":"location_type","value2":"file","description":""}` 1. Specify the `Script Path` location to the location of the folder inside auth server pods: `/deploy/interception-scripts-ksync/basic.py`. Right click the upper `jansModuleProperty` and click `New Value`. A new entry for `jansModuleProperty` will be created. Insert the following for the value: `{"value1":"location_path","value2":"/deploy/interception-scripts-ksync/basic.py","description":""}` diff --git a/docs/script-catalog/person_authentication/other/passport/sample/passport_script_entry.ldif b/docs/script-catalog/person_authentication/other/passport/sample/passport_script_entry.ldif index 7142616ea58..a9a7893c93c 100644 --- a/docs/script-catalog/person_authentication/other/passport/sample/passport_script_entry.ldif +++ b/docs/script-catalog/person_authentication/other/passport/sample/passport_script_entry.ldif @@ -9,7 +9,7 @@ oxConfigurationProperty: {"value1":"generic_remote_attributes_list","value2":"us oxConfigurationProperty: {"value1":"generic_local_attributes_list","value2":"uid, mail, cn, displayName, givenName, sn, provider","description":""} oxLevel: 60 oxModuleProperty: {"value1":"usage_type","value2":"interactive","description":""} -oxModuleProperty: {"value1":"location_type","value2":"ldap","description":""} +oxModuleProperty: {"value1":"location_type","value2":"db","description":""} oxRevision: 1 oxScript:: oxScriptType: person_authentication diff --git a/jans-config-api/docs/jans-config-api-swagger.yaml b/jans-config-api/docs/jans-config-api-swagger.yaml index de3ac971a0e..4366637b94a 100644 --- a/jans-config-api/docs/jans-config-api-swagger.yaml +++ b/jans-config-api/docs/jans-config-api-swagger.yaml @@ -4266,7 +4266,7 @@ paths: "moduleProperties": [ { "value1": "location_type", - "value2": "ldap" + "value2": "db" } ], "level": 1, @@ -4274,7 +4274,7 @@ paths: "enabled": true, "modified": false, "internal": false, - "locationType": "ldap", + "locationType": "db", "baseDn": "inum=0300-BA90,ou=scripts,o=jans" }, { @@ -4288,7 +4288,7 @@ paths: "moduleProperties": [ { "value1": "location_type", - "value2": "ldap" + "value2": "db" } ], "level": 100, @@ -4296,7 +4296,7 @@ paths: "enabled": false, "modified": false, "internal": false, - "locationType": "ldap", + "locationType": "db", "baseDn": "inum=031C-4A65,ou=scripts,o=jans" } ] @@ -4333,7 +4333,7 @@ paths: "moduleProperties": [ { "value1": "location_type", - "value2": "ldap" + "value2": "db" } ], "level": 800, @@ -4341,7 +4341,7 @@ paths: "enabled": false, "modified": false, "internal": false, - "locationType": "ldap" + "locationType": "db" } responses: "200": @@ -4365,7 +4365,7 @@ paths: "moduleProperties": [ { "value1": "location_type", - "value2": "ldap" + "value2": "db" } ], "level": 800, @@ -4373,7 +4373,7 @@ paths: "enabled": false, "modified": false, "internal": false, - "locationType": "ldap", + "locationType": "db", "baseDn": "inum=4144edf6-af99-451d-be29-f3eb5c0e9143,ou=scripts,o=jans" } "401": @@ -4419,7 +4419,7 @@ paths: "moduleProperties": [ { "value1": "location_type", - "value2": "ldap" + "value2": "db" } ], "level": 800, @@ -4427,7 +4427,7 @@ paths: "enabled": false, "modified": false, "internal": false, - "locationType": "ldap" + "locationType": "db" } responses: "201": @@ -4459,7 +4459,7 @@ paths: "enabled": false, "modified": false, "internal": false, - "locationType": "ldap", + "locationType": "db", "baseDn": "inum=4144edf6-af99-451d-be29-f3eb5c0e9143,ou=scripts,o=jans" } "401": @@ -4584,7 +4584,7 @@ paths: "enabled": true, "modified": false, "internal": false, - "locationType": "ldap", + "locationType": "db", "baseDn": "inum=0300-BA90,ou=scripts,o=jans" } "401": diff --git a/jans-config-api/server/src/main/resources/example/auth/scripts/scripts-all.json b/jans-config-api/server/src/main/resources/example/auth/scripts/scripts-all.json index c2a23547f7f..5e32838d2df 100644 --- a/jans-config-api/server/src/main/resources/example/auth/scripts/scripts-all.json +++ b/jans-config-api/server/src/main/resources/example/auth/scripts/scripts-all.json @@ -14,7 +14,7 @@ "moduleProperties": [ { "value1": "location_type", - "value2": "ldap" + "value2": "db" } ], "level": 1, @@ -22,7 +22,7 @@ "enabled": true, "modified": false, "internal": false, - "locationType": "ldap", + "locationType": "db", "baseDn": "inum=0300-BA90,ou=scripts,o=jans" }, { @@ -36,7 +36,7 @@ "moduleProperties": [ { "value1": "location_type", - "value2": "ldap" + "value2": "db" } ], "level": 100, @@ -44,7 +44,7 @@ "enabled": false, "modified": false, "internal": false, - "locationType": "ldap", + "locationType": "db", "baseDn": "inum=031C-4A65,ou=scripts,o=jans" } ] diff --git a/jans-config-api/server/src/main/resources/example/auth/scripts/scripts-by-id.json b/jans-config-api/server/src/main/resources/example/auth/scripts/scripts-by-id.json index d2db159f826..57b02d70fe9 100644 --- a/jans-config-api/server/src/main/resources/example/auth/scripts/scripts-by-id.json +++ b/jans-config-api/server/src/main/resources/example/auth/scripts/scripts-by-id.json @@ -9,7 +9,7 @@ "moduleProperties": [ { "value1": "location_type", - "value2": "ldap" + "value2": "db" } ], "level": 1, @@ -17,6 +17,6 @@ "enabled": true, "modified": false, "internal": false, - "locationType": "ldap", + "locationType": "db", "baseDn": "inum=0300-BA90,ou=scripts,o=jans" } \ No newline at end of file diff --git a/jans-config-api/server/src/main/resources/example/auth/scripts/scripts-by-name.json b/jans-config-api/server/src/main/resources/example/auth/scripts/scripts-by-name.json index d2db159f826..57b02d70fe9 100644 --- a/jans-config-api/server/src/main/resources/example/auth/scripts/scripts-by-name.json +++ b/jans-config-api/server/src/main/resources/example/auth/scripts/scripts-by-name.json @@ -9,7 +9,7 @@ "moduleProperties": [ { "value1": "location_type", - "value2": "ldap" + "value2": "db" } ], "level": 1, @@ -17,6 +17,6 @@ "enabled": true, "modified": false, "internal": false, - "locationType": "ldap", + "locationType": "db", "baseDn": "inum=0300-BA90,ou=scripts,o=jans" } \ No newline at end of file diff --git a/jans-config-api/server/src/main/resources/example/auth/scripts/scripts-by-type.json b/jans-config-api/server/src/main/resources/example/auth/scripts/scripts-by-type.json index 2a860a156d1..5eaee91649a 100644 --- a/jans-config-api/server/src/main/resources/example/auth/scripts/scripts-by-type.json +++ b/jans-config-api/server/src/main/resources/example/auth/scripts/scripts-by-type.json @@ -14,7 +14,7 @@ "moduleProperties": [ { "value1": "location_type", - "value2": "ldap" + "value2": "db" } ], "level": 1, @@ -22,7 +22,7 @@ "enabled": true, "modified": false, "internal": false, - "locationType": "ldap", + "locationType": "db", "baseDn": "inum=0300-BA90,ou=scripts,o=jans" } ] diff --git a/jans-config-api/server/src/main/resources/example/auth/scripts/scripts-response.json b/jans-config-api/server/src/main/resources/example/auth/scripts/scripts-response.json index 54a04dc7722..62282e11111 100644 --- a/jans-config-api/server/src/main/resources/example/auth/scripts/scripts-response.json +++ b/jans-config-api/server/src/main/resources/example/auth/scripts/scripts-response.json @@ -9,7 +9,7 @@ "moduleProperties": [ { "value1": "location_type", - "value2": "ldap" + "value2": "db" } ], "level": 800, @@ -17,6 +17,6 @@ "enabled": false, "modified": false, "internal": false, - "locationType": "ldap", + "locationType": "db", "baseDn": "inum=4144edf6-af99-451d-be29-f3eb5c0e9143,ou=scripts,o=jans" } \ No newline at end of file diff --git a/jans-config-api/server/src/main/resources/example/auth/scripts/scripts.json b/jans-config-api/server/src/main/resources/example/auth/scripts/scripts.json index e629e1514c9..3f7c46a8889 100644 --- a/jans-config-api/server/src/main/resources/example/auth/scripts/scripts.json +++ b/jans-config-api/server/src/main/resources/example/auth/scripts/scripts.json @@ -7,7 +7,7 @@ "moduleProperties": [ { "value1": "location_type", - "value2": "ldap" + "value2": "db" } ], "level": 800, @@ -15,5 +15,5 @@ "enabled": false, "modified": false, "internal": false, - "locationType": "ldap" + "locationType": "db" } \ No newline at end of file diff --git a/jans-config-api/server/src/test/resources/json/config/scripts/custom/generic/all-script.json b/jans-config-api/server/src/test/resources/json/config/scripts/custom/generic/all-script.json index c3cf5e2763c..7020cecc5b6 100644 --- a/jans-config-api/server/src/test/resources/json/config/scripts/custom/generic/all-script.json +++ b/jans-config-api/server/src/test/resources/json/config/scripts/custom/generic/all-script.json @@ -4,7 +4,7 @@ "level": 1, "programmingLanguage": "PYTHON", "description": "Introspection Custom Parameters Sample Script", - "locationType": "LDAP", + "locationType": "db", "dn": "inum=2DAF-BA90,ou=scripts,o=gluu", "inum": "2DAF-BA90", "script": "# jans-auth is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text.\n# Copyright (c) 2019, Gluu\n#\n# Author: Yuriy Mochan\n#\n#\n\nfrom org.gluu.model.custom.script.type.introspection import IntrospectionType\nfrom org.gluu.oxauth.model.common import AuthorizationGrantList\nfrom org.gluu.oxauth.service import SessionIdService\nfrom org.gluu.service.cdi.util import CdiUtil\nfrom java.lang import String\n\nclass Introspection(IntrospectionType):\n def __init__(self, currentTimeMillis):\n self.currentTimeMillis = currentTimeMillis\n\n def init(self, customScript, configurationAttributes):\n print \"Introspection script. Initializing ...\"\n print \"Introspection script. Initialized successfully\"\n\n return True\n\n def destroy(self, configurationAttributes):\n print \"Introspection script. Destroying ...\"\n print \"Introspection script. Destroyed successfully\"\n return True\n\n def getApiVersion(self):\n return 11\n\n # Returns boolean, true - apply introspection method, false - ignore it.\n # This method is called after introspection response is ready. This method can modify introspection response.\n # Note :\n # responseAsJsonObject - is org.codehaus.jettison.json.JSONObject, you can use any method to manipulate json\n # context is reference of org.gluu.oxauth.service.external.context.ExternalIntrospectionContext (in https://github.com/GluuFederation/oxauth project, )\n def modifyResponse(self, responseAsJsonObject, context):\n token = context.getHttpRequest().getParameter(\"token\")\n if token is None:\n print \"Introspection. There is no token in request\"\n return False\n\n authorizationGrantList = CdiUtil.bean(AuthorizationGrantList)\n authorizationGrant = authorizationGrantList.getAuthorizationGrantByAccessToken(token);\n if authorizationGrant is None:\n print \"Introspection. Failed to load authorization grant by token\"\n return False\n\n # Put user_id into response\n responseAsJsonObject.accumulate(\"user_id\", authorizationGrant.getUser().getUserId())\n\n # Put custom parameters into response\n sessionDn = authorizationGrant.getSessionDn();\n if sessionDn is None:\n # There is no session\n return True\n\n sessionIdService = CdiUtil.bean(SessionIdService)\n session = sessionIdService.getSessionById(sessionDn)\n if sessionDn is None:\n print \"Introspection. Failed to load session '%s'\" % sessionDn\n return False\n\n # Return session_id\n responseAsJsonObject.accumulate(\"session_id\", sessionDn)\n \n sessionAttributes = session.getSessionAttributes()\n if sessionAttributes is None:\n # There is no session attributes\n return True\n\n # Append custom claims\n if sessionAttributes.containsKey(\"custom1\"):\n responseAsJsonObject.accumulate(\"custom1\", sessionAttributes.get(\"custom1\"))\n if sessionAttributes.containsKey(\"custom2\"):\n responseAsJsonObject.accumulate(\"custom2\", sessionAttributes.get(\"custom2\"))\n\n return True\n\n", @@ -12,7 +12,7 @@ "revision": 1, "moduleProperties": [ { - "value2": "ldap", + "value2": "db", "value1": "location_type" } ], @@ -26,7 +26,7 @@ "level": 1, "programmingLanguage": "PYTHON", "description": "Resource Owner Password Credentials Example", - "locationType": "LDAP", + "locationType": "db", "dn": "inum=2DAF-AA91,ou=scripts,o=gluu", "inum": "2DAF-AA91", "script": "from org.gluu.model.custom.script.type.owner import ResourceOwnerPasswordCredentialsType\nfrom org.gluu.oxauth.service import AuthenticationService\nfrom org.gluu.service.cdi.util import CdiUtil\nfrom java.lang import String\n\nclass ResourceOwnerPasswordCredentials(ResourceOwnerPasswordCredentialsType):\n def __init__(self, currentTimeMillis):\n self.currentTimeMillis = currentTimeMillis\n\n def init(self, customScript, configurationAttributes):\n print \"ROPC script. Initializing ...\"\n\n self.usernameParamName = \"username\"\n self.passwordParamName = \"password\"\n\n print \"ROPC script. Initialized successfully\"\n\n return True\n\n def destroy(self, configurationAttributes):\n print \"ROPC script. Destroying ...\"\n print \"ROPC script. Destroyed successfully\"\n return True\n\n def getApiVersion(self):\n return 11\n\n # Returns True and set user into context when user authenticated succesfully\n # Returns False when user not authenticated or it's needed to cancel notmal flow\n # Note :\n # context is reference of org.gluu.oxauth.service.external.context.ExternalResourceOwnerPasswordCredentialsContext#ExternalResourceOwnerPasswordCredentialsContext (in https://github.com/GluuFederation/oxauth project, )\n def authenticate(self, context):\n print \"ROPC script. Authenticate\"\n deviceIdParam = context.getHttpRequest().getParameterValues(\"device_id\")\n if deviceIdParam != None and (deviceIdParam.lenght > 0 ):\n result = deviceIdParam[0] == \"device_id_1\"\n if not result:\n return False\n\n # Set auntenticated user in context\n # context.setUser(user)\n return True\n\n # Do generic authentication in other cases\n authService = CdiUtil.bean(AuthenticationService)\n\n username = context.getHttpRequest().getParameter(self.usernameParamName)\n password = context.getHttpRequest().getParameter(self.passwordParamName)\n result = authService.authenticate(username, password)\n if not result:\n print \"ROPC script. Authenticate. Could not authenticate user '%s' \" % username\n return False\n\n context.setUser(authService.getAuthenticatedUser())\n\n return True\n", @@ -34,7 +34,7 @@ "revision": 1, "moduleProperties": [ { - "value2": "ldap", + "value2": "db", "value1": "location_type" } ], @@ -48,7 +48,7 @@ "level": 1, "programmingLanguage": "PYTHON", "description": "Frontchannel logout Sample", - "locationType": "LDAP", + "locationType": "db", "dn": "inum=2DAF-CA90,ou=scripts,o=gluu", "inum": "2DAF-CA90", "script": "# Copyright (c) 2020, Gluu\n#\n# Author: Yuriy Zabrovarnyy\n#\n\nfrom org.gluu.model.custom.script.type.logout import EndSessionType\nfrom java.lang import String\n\nclass EndSession(EndSessionType):\n def __init__(self, currentTimeMillis):\n self.currentTimeMillis = currentTimeMillis\n\n def init(self, customScript, configurationAttributes):\n print \"EndSession script. Initializing ...\"\n print \"EndSession script. Initialized successfully\"\n\n return True\n\n def destroy(self, configurationAttributes):\n print \"EndSession script. Destroying ...\"\n print \"EndSession script. Destroyed successfully\"\n return True\n\n def getApiVersion(self):\n return 11\n\n # Returns string, it must be valid HTML (with iframes according to spec http://openid.net/specs/openid-connect-frontchannel-1_0.html)\n # This method is called on `/end_session` after actual session is killed and oxauth construct HTML to return to RP.\n # Note :\n # context is reference of org.gluu.oxauth.service.external.context.EndSessionContext (in https://github.com/GluuFederation/oxauth project, )\n def getFrontchannelHtml(self, context):\n return \"\"", @@ -56,7 +56,7 @@ "revision": 1, "moduleProperties": [ { - "value2": "ldap", + "value2": "db", "value1": "location_type" } ], @@ -70,7 +70,7 @@ "level": 1, "programmingLanguage": "PYTHON", "description": "Sample UMA Claims Gathering", - "locationType": "LDAP", + "locationType": "db", "dn": "inum=2DAF-F996,ou=scripts,o=gluu", "inum": "2DAF-F996", "script": "# jans-auth is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text.\r\n# Copyright (c) 2017, Gluu\r\n#\r\n# Author: Yuriy Zabrovarnyy\r\n#\r\n\r\nfrom org.gluu.model.custom.script.type.uma import UmaClaimsGatheringType\r\n\r\nclass UmaClaimsGathering(UmaClaimsGatheringType):\r\n\r\n def __init__(self, currentTimeMillis):\r\n self.currentTimeMillis = currentTimeMillis\r\n\r\n def init(self, customScript, configurationAttributes):\r\n print \"Claims-Gathering. Initializing ...\"\r\n print \"Claims-Gathering. Initialized successfully\"\r\n\r\n return True\r\n\r\n def destroy(self, configurationAttributes):\r\n print \"Claims-Gathering. Destroying ...\"\r\n print \"Claims-Gathering. Destroyed successfully\"\r\n return True\r\n\r\n def getApiVersion(self):\r\n return 11\r\n\r\n\r\n # Main gather method. Must return True (if gathering performed successfully) or False (if fail).\r\n # Method must set claim into context (via context.putClaim('name', value)) in order to persist it (otherwise it will be lost).\r\n # All user entered values can be access via Map context.getPageClaims()\r\n def gather(self, step, context): # context is reference of org.gluu.oxauth.uma.authorization.UmaGatherContext\r\n print \"Claims-Gathering. Gathering ...\"\r\n\r\n if step == 1:\r\n if (context.getPageClaims().containsKey(\"country\")):\r\n country = context.getPageClaims().get(\"country\")\r\n print \"Country: \" + country\r\n\r\n context.putClaim(\"country\", country)\r\n return True\r\n\r\n print \"Claims-Gathering. 'country' is not provided on step 1.\"\r\n return False\r\n\r\n elif step == 2:\r\n if (context.getPageClaims().containsKey(\"city\")):\r\n city = context.getPageClaims().get(\"city\")\r\n print \"City: \" + city\r\n\r\n context.putClaim(\"city\", city)\r\n print \"Claims-Gathering. 'city' is not provided on step 2.\"\r\n return True\r\n\r\n return False\r\n\r\n def getNextStep(self, step, context):\r\n return -1\r\n\r\n def prepareForStep(self, step, context):\r\n if step == 10 and not context.isAuthenticated():\r\n # user is not authenticated, so we are redirecting user to authorization endpoint\r\n # client_id is specified via configuration attribute.\r\n # Make sure that given client has redirect_uri to Claims-Gathering Endpoint with parameter authentication=true\r\n # Sample https://sample.com/restv1/uma/gather_claims?authentication=true\r\n # If redirect to external url is performated, make sure that viewAction has onPostback=\"true\" (otherwise redirect will not work)\r\n # After user is authenticated then within the script it's possible to get user attributes as\r\n # context.getUser(\"uid\", \"sn\")\r\n # If user is authenticated to current AS (to the same server, not external one) then it's possible to\r\n # access Connect session attributes directly (no need to obtain id_token after redirect with 'code').\r\n # To fetch attributes please use getConnectSessionAttributes() method.\r\n\r\n print \"User is not authenticated. Redirect for authentication ...\"\r\n clientId = context.getConfigurationAttributes().get(\"client_id\").getValue2()\r\n redirectUri = context.getClaimsGatheringEndpoint() + \"?authentication=true\" # without authentication=true parameter it will not work\r\n authorizationUrl = context.getAuthorizationEndpoint() + \"?client_id=\" + clientId + \"&redirect_uri=\" + redirectUri + \"&scope=openid&response_type=code\"\r\n context.redirectToExternalUrl(authorizationUrl) # redirect to external url\r\n return False\r\n if step == 10 and context.isAuthenticated(): # example how to get session attribute if user is authenticated to same AS\r\n arc = context.getConnectSessionAttributes().get(\"acr\")\r\n\r\n return True\r\n\r\n def getStepsCount(self, context):\r\n return 2\r\n\r\n def getPageForStep(self, step, context):\r\n if step == 1:\r\n return \"/uma2/sample/country.xhtml\"\r\n elif step == 2:\r\n return \"/uma2/sample/city.xhtml\"\r\n return \"\"", @@ -78,7 +78,7 @@ "revision": 1, "moduleProperties": [ { - "value2": "ldap", + "value2": "db", "value1": "location_type" } ], @@ -92,7 +92,7 @@ "level": 1, "programmingLanguage": "PYTHON", "description": "Super Gluu RO Password Credentials Script", - "locationType": "LDAP", + "locationType": "db", "dn": "inum=B8FD-4C11,ou=scripts,o=gluu", "inum": "B8FD-4C11", "script": "# Super Gluu Radius Resource Owner Password Credentials Script\n# Copyright (c) 2019 Gluu Inc.\n\nfrom java.util import Date , HashMap\nfrom org.gluu.oxnotify.client import NotifyClientFactory\n\nfrom org.gluu.model.custom.script.type.owner import ResourceOwnerPasswordCredentialsType\nfrom org.gluu.oxauth.model.common import SessionIdState\nfrom org.gluu.oxauth.model.config import ConfigurationFactory , Constants\nfrom org.gluu.oxauth.security import Identity\nfrom org.gluu.oxauth.service import AuthenticationService, SessionIdService\nfrom org.gluu.oxauth.service.common import EncryptionService, UserService\nfrom org.gluu.oxauth.service.push.sns import PushPlatform, PushSnsService\nfrom org.gluu.service.cdi.util import CdiUtil\nfrom org.gluu.util import StringHelper\nfrom gluu_common import PushNotificationManager, NetworkApi, GeolocationData, SuperGluuRequestBuilder\n\nimport java\nimport json\nimport sys\n\n\nclass ResourceOwnerPasswordCredentials(ResourceOwnerPasswordCredentialsType):\n def __init__(self,currentTimeMillis):\n self.currentTimeMillis = currentTimeMillis\n self.initiateAuthStepName = \"initiate_auth\"\n self.verifyAuthStepName = \"verify_auth\"\n self.resendNotificationStepName = \"resend_notification\"\n self.stepParamName = \"__step\"\n self.acrvaluesParamName = \"__acr_values\"\n self.usernameParamName = \"username\"\n self.passwordParamName = \"__password\"\n self.idtokenParamName = \"__id_token\"\n self.sessionIdParamName = \"__session_id\"\n self.remoteIpParamName = \"__remote_ip\"\n self.sessionIdClaimName = \"__session_id\"\n self.clientIdSessionParamName = \"__client_id\"\n self.authSchemeParamName = \"__auth_scheme\"\n self.oneStepAuthScheme = \"onestep\"\n self.twoStepAuthScheme = \"twostep\"\n \n def init(self, customScript, configurationAttributes):\n\n print \"Super-Gluu-RO Init\"\n if not configurationAttributes.containsKey(\"application_id\"):\n print \"Super-Gluu-Radius RO PW Init Failed. application_id property is required\"\n return False\n \n if not configurationAttributes.containsKey(\"credentials_file\"):\n print \"Super-Gluu-RO Init Failed. credentials_file is required\"\n return False\n \n notificationServiceMode = None\n if configurationAttributes.containsKey(\"notification_service_mode\"):\n notificationServiceMode = configurationAttributes.get(\"notification_service_mode\").getValue2()\n \n \n self.applicationId = \"*\" # wildcard. Selects all devices irrespective of the application \n if configurationAttributes.containsKey(\"application_id\"):\n self.applicationId = configurationAttributes.get(\"application_id\").getValue2()\n \n credentialsFile = configurationAttributes.get(\"credentials_file\").getValue2()\n\n if configurationAttributes.containsKey(\"push_notification_title\"):\n self.pushNotificationManager.titleTemplate = configurationAttributes.get(\"push_notification_title\").getValue2()\n \n if configurationAttributes.containsKey(\"push_notification_message\"):\n self.pushNotificationManager.messageTemplate = configurationAttributes.get(\"push_notification_message\").getValue2()\n \n self.authWithoutPassword = False\n if configurationAttributes.containsKey(\"auth_without_password\"):\n auth_without_password = configurationAttributes.get(\"auth_without_password\").getValue2()\n if StringHelper.equalsIgnoreCase(auth_without_password,\"yes\"):\n self.authWithoutPassword = True\n \n self.issuerId = CdiUtil.bean(ConfigurationFactory).getAppConfiguration().getIssuer()\n if configurationAttributes.containsKey(\"issuer_id\"):\n self.issuerId = configurationAttributes.get(\"issuer_id\").getValue2()\n \n self.pushNotificationManager = PushNotificationManager(notificationServiceMode,credentialsFile)\n self.networkApi = NetworkApi()\n\n return True\n \n def destroy(self, configurationAttributes):\n\n print \"Super-Gluu-RO. Destroy\"\n self.pushNotificationManager = None\n print \"Super-Gluu-RO. Destroyed Successfully\"\n\n return True\n \n def getApiVersion(self):\n return 11\n \n def authenticate(self, context): \n if self.perform_preliminary_user_authentication(context) == False:\n print \"Super-Gluu-RO. User authentication state not validated\"\n return False\n \n step = context.getHttpRequest().getParameter(self.stepParamName)\n if StringHelper.equalsIgnoreCase(step,self.initiateAuthStepName):\n return self.initiate_authentication(context)\n elif StringHelper.equalsIgnoreCase(step,self.resendNotificationStepName):\n return self.resend_push_notification(context)\n elif StringHelper.equalsIgnoreCase(step,self.verifyAuthStepName):\n return self.verify_authentication(context)\n else:\n context.setUser(None)\n print \"Super-Gluu-RO. Unknown authentication step '%s'\" % step\n return False\n \n def initiate_authentication(self, context):\n print \"Super-Gluu-RO initiatate_authentication\"\n\n authscheme = context.getHttpRequest().getParameter(self.authSchemeParamName)\n if authscheme == None:\n authscheme = self.twoStepAuthScheme\n \n if StringHelper.equalsIgnoreCase(authscheme,self.oneStepAuthScheme):\n print \"Super-Gluu-RO using one-step authentication\"\n print \"User '%s' authenticated using one-step\" % context.getUser().getUserId()\n return True\n elif StringHelper.equalsIgnoreCase(authscheme,self.twoStepAuthScheme):\n print \"Super-Gluu-RO using two-step authentication\"\n client = CdiUtil.bean(Identity).getSessionClient().getClient()\n sessionId = self.new_unauthenticated_session(context.getUser(),client)\n # set session id in identity object \n # this will be used by our dynamic scope script \n identity = CdiUtil.bean(Identity)\n identity.setSessionId(sessionId)\n if not self.send_push_notification_to_user(sessionId,context):\n print \"Send push notification to user '%s' failed\" % context.getUser().getUserId()\n context.setUser(None)\n return False\n print \"Super-Gluu-RO initiate_authentication complete\"\n return True\n else:\n print \"Super-Gluu-RO. Unknown authentication scheme specified '%s'\" % authscheme\n context.setUser(None)\n return False\n \n \n print \"Super-Gluu-RO using two-step authentication\"\n client = CdiUtil.bean(Identity).getSessionClient().getClient()\n sessionId = self.new_unauthenticated_session(context.getUser(),client)\n # set session id in identity object\n # this will be used by our dynamic scope script\n identity = CdiUtil.bean(Identity)\n identity.setSessionId(sessionId)\n if not self.send_push_notification_to_user(sessionId,context):\n print \"Send push notification to user '%s' failed \" % context.getUser().getUserId()\n context.setUser(None)\n return False\n print \"Super-Gluu-RO initiate_authentication complete\"\n return True\n \n def resend_push_notification(self,context):\n print \"Super-Gluu-RO resend_push_notification\"\n\n sessionIdService = CdiUtil.bean(SessionIdService)\n session_id = context.getHttpRequest().getParameter(self.sessionIdParamName)\n if session_id == None:\n print \"Super-Gluu-RO. No session_id was specified for resend_push_notification\"\n context.setUser(None)\n return False\n \n sessionId = sessionIdService.getSessionId(session_id)\n if sessionId == None:\n print \"Super-Gluu-RO. Session '%s' does not exist or has expired\" % session_id\n context.setUser(None)\n return False\n \n client = CdiUtil.bean(Identity).getSessionClient().getClient()\n if not self.verify_session_ownership(sessionId,context.getUser(),client):\n print \"Super-Gluu-RO. resend_push_notification_failed due to invalid session ownership\"\n context.setUser(None)\n return False\n \n self.send_push_notification_to_user(sessionId,context)\n print \"Super-Gluu-RO resend_push_notification complete\"\n return True\n \n def verify_authentication(self, context):\n print \"Super-Gluu-RO verify_authentication\"\n session_id = context.getHttpRequest().getParameter(self.sessionIdParamName)\n sessionId = CdiUtil.bean(SessionIdService).getSessionId(session_id)\n if sessionId == None:\n print \"Super-Gluu-RO.verify_authentication failed. Session {%s} does not exist or has expired\" % session_id\n context.setUser(None)\n return False\n \n client = CdiUtil.bean(Identity).getSessionClient().getClient()\n if not self.verify_session_ownership(sessionId,context.getUser(),client):\n print \"Super-Gluu-RO. verify_authentication failed due to invalid session ownership\"\n context.setUser(None)\n return False\n \n if not self.is_session_authenticated(sessionId):\n print \"Super-Gluu-Ro. verify_authentication failed. Session is not authenticated\"\n context.setUser(None)\n return False\n \n print \"Super-Gluu-RO verify_authentication complete\"\n return True\n \n def perform_preliminary_user_authentication(self, context):\n username = context.getHttpRequest().getParameter(self.usernameParamName)\n if self.authWithoutPassword:\n userService = CdiUtil.bean(UserService)\n user = userService.getUser(username,\"uid\")\n if user == None:\n print \"Super-Gluu-RO. User '%s' not found\" % username\n return False\n context.setUser(user)\n print \"Super-Gluu-RO. User '%s' authenticated without password\" % username\n return True\n \n password = context.getHttpRequest().getParameter(self.passwordParamName)\n authService = CdiUtil.bean(AuthenticationService)\n if authService.authenticate(username, password) == False:\n print \"Super-Gluu-RO. Could not authenticate user '%s' \" % username\n return False\n\n context.setUser(authService.getAuthenticatedUser())\n return True\n \n def new_unauthenticated_session(self,user,client):\n sessionIdService = CdiUtil.bean(SessionIdService)\n authDate = Date()\n sid_attrs = HashMap()\n sid_attrs.put(Constants.AUTHENTICATED_USER,user.getUserId())\n sid_attrs.put(self.clientIdSessionParamName,client.getClientId())\n sessionId = sessionIdService.generateUnauthenticatedSessionId(user.getDn(),authDate,SessionIdState.UNAUTHENTICATED,sid_attrs,True)\n print \"Super-Gluu-RO. Generated session id. DN: '%s'\" % sessionId.getDn()\n return sessionId\n \n def send_push_notification_to_user(self, sessionId,context):\n remote_ip = context.getHttpRequest().getParameter(self.remoteIpParamName)\n if remote_ip == None or (remote_ip != None and StringHelper.isEmpty(remote_ip)):\n remote_ip = self.networkApi.get_remote_ip_from_request(context.getHttpRequest())\n \n user = context.getUser()\n srbuilder = SuperGluuRequestBuilder()\n srbuilder.username = user.getUserId()\n srbuilder.app = self.applicationId\n srbuilder.issuer = self.issuerId\n srbuilder.state = sessionId.getId()\n srbuilder.requestLocation(self.networkApi.get_geolocation_data(remote_ip))\n srbuilder.req_ip = remote_ip \n device_count = self.pushNotificationManager.sendPushNotification(user,self.applicationId,srbuilder.build())\n \n if device_count == 0:\n print \"User %s has no device enrolled for Super-Gluu authentication\" % user.getUserId()\n return False\n return True\n\n \n\n def is_session_authenticated(self, sessionId):\n if sessionId == None:\n return False\n \n state = sessionId.getState()\n custom_state = sessionId.getSessionAttributes().get(SessionIdService.SESSION_CUSTOM_STATE)\n if state == None:\n print \"Super-Gluu-RO. Session {%s} has no state variable set\" % sessionId.getId()\n return False\n \n state_unauthenticated = SessionIdState.UNAUTHENTICATED == state\n state_authenticated = SessionIdState.AUTHENTICATED == state\n custom_state_declined = StringHelper.equalsIgnoreCase(\"declined\",custom_state) \n custom_state_expired = StringHelper.equalsIgnoreCase(\"expired\",custom_state)\n custom_stated_approved = StringHelper.equalsIgnoreCase(\"approved\",custom_state)\n\n if state_unauthenticated and (custom_state_declined or custom_state_expired):\n print \"Super-Gluu-RO. Session {%s} isn't authenticated\" % sessionId.getId()\n return False\n \n if state_authenticated or (state_unauthenticated and custom_stated_approved):\n print \"Super-Gluu-RO. Session {%s} is authenticated\" % sessionId.getId()\n return True\n\n return False\n \n # this function verifies if the session was created when invoked with the \n # current client's credentials and with the current user's credentials\n\n def verify_session_ownership(self, sessionId, user, client):\n session_attributes = sessionId.getSessionAttributes()\n client_id = session_attributes.get(self.clientIdSessionParamName)\n if not StringHelper.equalsIgnoreCase(client.getClientId(),client_id):\n print \"Super-Gluu-RO. Session {%s} client_id mismatch\" % sessionId.getId()\n return False\n \n user_id = session_attributes.get(Constants.AUTHENTICATED_USER)\n if not StringHelper.equalsIgnoreCase(user_id,user.getUserId()):\n print \"Super-Gluu-RO. Session {%s} user_id mismatch\" % sessionId.getId() \n return False\n \n return True\n", @@ -100,7 +100,7 @@ "revision": 1, "moduleProperties": [ { - "value2": "ldap", + "value2": "db", "value1": "location_type" } ], @@ -131,7 +131,7 @@ "level": 1, "programmingLanguage": "PYTHON", "description": "Introspection Sample Script", - "locationType": "LDAP", + "locationType": "db", "dn": "inum=2DAF-AA90,ou=scripts,o=gluu", "inum": "2DAF-AA90", "script": "# jans-auth is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text.\n# Copyright (c) 2018, Gluu\n#\n# Author: Yuriy Zabrovarnyy\n#\n#\n\nfrom org.gluu.model.custom.script.type.introspection import IntrospectionType\nfrom java.lang import String\n\nclass Introspection(IntrospectionType):\n def __init__(self, currentTimeMillis):\n self.currentTimeMillis = currentTimeMillis\n\n def init(self, customScript, configurationAttributes):\n print \"Introspection script. Initializing ...\"\n print \"Introspection script. Initialized successfully\"\n\n return True\n\n def destroy(self, configurationAttributes):\n print \"Introspection script. Destroying ...\"\n print \"Introspection script. Destroyed successfully\"\n return True\n\n def getApiVersion(self):\n return 11\n\n # Returns boolean, true - apply introspection method, false - ignore it.\n # This method is called after introspection response is ready. This method can modify introspection response.\n # Note :\n # responseAsJsonObject - is org.codehaus.jettison.json.JSONObject, you can use any method to manipulate json\n # context is reference of org.gluu.oxauth.service.external.context.ExternalIntrospectionContext (in https://github.com/GluuFederation/oxauth project, )\n def modifyResponse(self, responseAsJsonObject, context):\n responseAsJsonObject.accumulate(\"key_from_script\", \"value_from_script\")\n return True\n\n", @@ -139,7 +139,7 @@ "revision": 1, "moduleProperties": [ { - "value2": "ldap", + "value2": "db", "value1": "location_type" } ], @@ -153,7 +153,7 @@ "level": 1, "programmingLanguage": "PYTHON", "description": "Resource Owner Password Credentials Custom Parameters Example", - "locationType": "LDAP", + "locationType": "db", "dn": "inum=2DAF-BA91,ou=scripts,o=gluu", "inum": "2DAF-BA91", "script": "# jans-auth is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text.\n# Copyright (c) 2019, Gluu\n#\n# Author: Yuriy Mochan\n#\n#\n\nfrom org.gluu.model.custom.script.type.owner import ResourceOwnerPasswordCredentialsType\nfrom org.gluu.oxauth.service import AuthenticationService, SessionIdService\nfrom org.gluu.oxauth.model.common import SessionIdState\nfrom org.gluu.oxauth.security import Identity\nfrom org.gluu.service.cdi.util import CdiUtil\nfrom org.gluu.oxauth.model.authorize import AuthorizeRequestParam\nfrom org.gluu.oxauth.model.config import Constants\nfrom org.gluu.util import StringHelper\nfrom java.lang import String\nfrom java.util import Date, HashMap\n\nclass ResourceOwnerPasswordCredentials(ResourceOwnerPasswordCredentialsType):\n def __init__(self, currentTimeMillis):\n self.currentTimeMillis = currentTimeMillis\n\n def init(self, customScript, configurationAttributes):\n print \"ROPC script. Initializing ...\"\n print \"ROPC script. Initialized successfully\"\n return True\n\n def destroy(self, configurationAttributes):\n print \"ROPC script. Destroying ...\"\n print \"ROPC script. Destroyed successfully\"\n return True\n\n def getApiVersion(self):\n return 11\n\n # Returns True and set user into context when user authenticated succesfully\n # Returns False when user not authenticated or it's needed to cancel notmal flow\n # Note :\n # context is reference of org.gluu.oxauth.service.external.context.ExternalResourceOwnerPasswordCredentialsContext#ExternalResourceOwnerPasswordCredentialsContext (in https://github.com/GluuFederation/oxauth project, )\n def authenticate(self, context):\n print \"ROPC script. Authenticate\"\n\n # Do generic authentication\n authenticationService = CdiUtil.bean(AuthenticationService)\n\n username = context.getHttpRequest().getParameter(\"username\")\n password = context.getHttpRequest().getParameter(\"password\")\n result = authenticationService.authenticate(username, password)\n if not result:\n print \"ROPC script. Authenticate. Could not authenticate user '%s' \" % username\n return False\n\n context.setUser(authenticationService.getAuthenticatedUser())\n print \"ROPC script. Authenticate. User '%s' authenticated successfully\" % username\n \n\n # Get cusom parameters from request\n customParam1Value = context.getHttpRequest().getParameter(\"custom1\")\n customParam2Value = context.getHttpRequest().getParameter(\"custom2\")\n\n customParameters = {}\n customParameters[\"custom1\"] = customParam1Value\n customParameters[\"custom2\"] = customParam2Value\n print \"ROPC script. Authenticate. User '%s'. Creating authenticated session with custom attributes: '%s'\" % (username, customParameters)\n\n session = self.createNewAuthenticatedSession(context, customParameters)\n \n # This is needed to allow store in token entry sessionId\n authenticationService.configureEventUser(session)\n\n print \"ROPC script. Authenticate. User '%s'. Created authenticated session: '%s'\" % (username, customParameters)\n\n return True\n\n def createNewAuthenticatedSession(self, context, customParameters={}):\n sessionIdService = CdiUtil.bean(SessionIdService)\n\n user = context.getUser()\n client = CdiUtil.bean(Identity).getSessionClient().getClient()\n\n # Add mandatory session parameters\n sessionAttributes = HashMap()\n sessionAttributes.put(Constants.AUTHENTICATED_USER, user.getUserId())\n sessionAttributes.put(AuthorizeRequestParam.CLIENT_ID, client.getClientId())\n sessionAttributes.put(AuthorizeRequestParam.PROMPT, \"\")\n\n # Add custom session parameters\n for key, value in customParameters.iteritems():\n if StringHelper.isNotEmpty(value):\n sessionAttributes.put(key, value)\n\n # Generate authenticated session\n sessionId = sessionIdService.generateAuthenticatedSessionId(context.getHttpRequest(), user.getDn(), sessionAttributes)\n\n print \"ROPC script. Generated session id. DN: '%s'\" % sessionId.getDn()\n\n return sessionId\n", @@ -161,7 +161,7 @@ "revision": 1, "moduleProperties": [ { - "value2": "ldap", + "value2": "db", "value1": "location_type" } ], @@ -175,7 +175,7 @@ "level": 10, "programmingLanguage": "PYTHON", "description": "Firebase notification sender", - "locationType": "LDAP", + "locationType": "db", "dn": "inum=C1BA-C1BA,ou=scripts,o=gluu", "inum": "C1BA-C1BA", "script": "# jans-auth is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text.\n# Copyright (c) 2018, Gluu\n#\n# Author: Milton BO\n#\n#\n\nfrom org.gluu.oxauth.client.fcm import FirebaseCloudMessagingResponse\nfrom org.gluu.oxauth.client.fcm import FirebaseCloudMessagingClient\nfrom org.gluu.oxauth.client.fcm import FirebaseCloudMessagingRequest\nfrom org.gluu.oxauth.util import RedirectUri\nfrom org.gluu.model.custom.script.type.ciba import EndUserNotificationType\nfrom java.lang import String\nfrom java.util import UUID\n\nclass EndUserNotification(EndUserNotificationType):\n def __init__(self, currentTimeMillis):\n self.currentTimeMillis = currentTimeMillis\n\n def init(self, configurationAttributes):\n print \"Firebase EndUserNotification script. Initializing ...\"\n print \"Firebase EndUserNotification script. Initialized successfully\"\n\n return True\n\n def destroy(self, configurationAttributes):\n print \"Firebase EndUserNotification script. Destroying ...\"\n print \"Firebase EndUserNotification script. Destroyed successfully\"\n return True\n\n def getApiVersion(self):\n return 1\n\n # Returns boolean true or false depending on the process, if the notification\n # is sent successfully or not.\n def notifyEndUser(self, context):\n print 'Sending push notification using Firebase Cloud Messaging'\n appConfiguration = context.getAppConfiguration()\n encryptionService = context.getEncryptionService()\n clientId = appConfiguration.getBackchannelClientId()\n redirectUri = appConfiguration.getBackchannelRedirectUri()\n url = appConfiguration.getCibaEndUserNotificationConfig().getNotificationUrl()\n key = encryptionService.decrypt(appConfiguration.getCibaEndUserNotificationConfig().getNotificationKey(), True)\n to = context.getDeviceRegistrationToken()\n title = \"oxAuth Authentication Request\"\n body = \"Client Initiated Backchannel Authentication (CIBA)\"\n\n authorizationRequestUri = RedirectUri(appConfiguration.getAuthorizationEndpoint())\n authorizationRequestUri.addResponseParameter(\"client_id\", clientId)\n authorizationRequestUri.addResponseParameter(\"response_type\", \"id_token\")\n authorizationRequestUri.addResponseParameter(\"scope\", context.getScope())\n authorizationRequestUri.addResponseParameter(\"acr_values\", context.getAcrValues())\n authorizationRequestUri.addResponseParameter(\"redirect_uri\", redirectUri)\n authorizationRequestUri.addResponseParameter(\"state\", UUID.randomUUID().toString())\n authorizationRequestUri.addResponseParameter(\"nonce\", UUID.randomUUID().toString())\n authorizationRequestUri.addResponseParameter(\"prompt\", \"consent\")\n authorizationRequestUri.addResponseParameter(\"auth_req_id\", context.getAuthReqId())\n\n clickAction = authorizationRequestUri.toString()\n\n firebaseCloudMessagingRequest = FirebaseCloudMessagingRequest(key, to, title, body, clickAction)\n firebaseCloudMessagingClient = FirebaseCloudMessagingClient(url)\n firebaseCloudMessagingClient.setRequest(firebaseCloudMessagingRequest)\n firebaseCloudMessagingResponse = firebaseCloudMessagingClient.exec()\n\n responseStatus = firebaseCloudMessagingResponse.getStatus()\n print \"CIBA: firebase cloud messaging result status \" + str(responseStatus)\n return (responseStatus >= 200 and responseStatus < 300 )\n\n", @@ -183,7 +183,7 @@ "revision": 1, "moduleProperties": [ { - "value2": "ldap", + "value2": "db", "value1": "location_type" } ], @@ -197,7 +197,7 @@ "level": 10, "programmingLanguage": "PYTHON", "description": "Sample authentication module", - "locationType": "LDAP", + "locationType": "db", "dn": "inum=A51E-76DA,ou=scripts,o=gluu", "inum": "A51E-76DA", "script": "# jans-auth is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text.\n# Copyright (c) 2016, Gluu\n#\n# Author: Yuriy Movchan\n#\n\nfrom org.gluu.service.cdi.util import CdiUtil\nfrom org.gluu.oxauth.security import Identity\nfrom org.gluu.model.custom.script.type.auth import PersonAuthenticationType\nfrom org.gluu.oxauth.service import AuthenticationService\nfrom org.gluu.util import StringHelper\n\nimport java\n\nclass PersonAuthentication(PersonAuthenticationType):\n def __init__(self, currentTimeMillis):\n self.currentTimeMillis = currentTimeMillis\n\n def init(self, customScript, configurationAttributes):\n print \"Basic. Initialization\"\n print \"Basic. Initialized successfully\"\n return True \n\n def destroy(self, configurationAttributes):\n print \"Basic. Destroy\"\n print \"Basic. Destroyed successfully\"\n return True\n \n def getAuthenticationMethodClaims(self, requestParameters):\n return None\n \n def getApiVersion(self):\n return 11\n\n def isValidAuthenticationMethod(self, usageType, configurationAttributes):\n return True\n\n def getAlternativeAuthenticationMethod(self, usageType, configurationAttributes):\n return None\n\n def authenticate(self, configurationAttributes, requestParameters, step):\n authenticationService = CdiUtil.bean(AuthenticationService)\n\n if (step == 1):\n print \"Basic. Authenticate for step 1\"\n\n identity = CdiUtil.bean(Identity)\n credentials = identity.getCredentials()\n\n user_name = credentials.getUsername()\n user_password = credentials.getPassword()\n\n logged_in = False\n if (StringHelper.isNotEmptyString(user_name) and StringHelper.isNotEmptyString(user_password)):\n logged_in = authenticationService.authenticate(user_name, user_password)\n\n if (not logged_in):\n return False\n\n return True\n else:\n return False\n\n def prepareForStep(self, configurationAttributes, requestParameters, step):\n if (step == 1):\n print \"Basic. Prepare for Step 1\"\n return True\n else:\n return False\n\n def getExtraParametersForStep(self, configurationAttributes, step):\n return None\n\n def getCountAuthenticationSteps(self, configurationAttributes):\n return 1\n\n def getPageForStep(self, configurationAttributes, step):\n return \"\"\n\n def getNextStep(self, configurationAttributes, requestParameters, step):\n return -1\n\n def getLogoutExternalUrl(self, configurationAttributes, requestParameters):\n print \"Get external logout URL call\"\n return None\n\n def logout(self, configurationAttributes, requestParameters):\n return True\n", @@ -209,7 +209,7 @@ "value1": "usage_type" }, { - "value2": "ldap", + "value2": "db", "value1": "location_type" } ], @@ -223,7 +223,7 @@ "level": 10, "programmingLanguage": "PYTHON", "description": "Consent Gathering script", - "locationType": "LDAP", + "locationType": "db", "dn": "inum=DAA9-BA60,ou=scripts,o=gluu", "inum": "DAA9-BA60", "script": "# jans-auth is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text.\n# Copyright (c) 2017, Gluu\n#\n# Author: Yuriy Movchan\n#\n\nfrom org.gluu.service.cdi.util import CdiUtil\nfrom org.gluu.oxauth.security import Identity\nfrom org.gluu.model.custom.script.type.authz import ConsentGatheringType\nfrom org.gluu.util import StringHelper\n\nimport java\nimport random\n\nclass ConsentGathering(ConsentGatheringType):\n\n def __init__(self, currentTimeMillis):\n self.currentTimeMillis = currentTimeMillis\n\n def init(self, customScript, configurationAttributes):\n print \"Consent-Gathering. Initializing ...\"\n print \"Consent-Gathering. Initialized successfully\"\n\n return True\n\n def destroy(self, configurationAttributes):\n print \"Consent-Gathering. Destroying ...\"\n print \"Consent-Gathering. Destroyed successfully\"\n\n return True\n\n def getApiVersion(self):\n return 1\n\n # Main consent-gather method. Must return True (if gathering performed successfully) or False (if fail).\n # All user entered values can be access via Map context.getPageAttributes()\n def authorize(self, step, context): # context is reference of org.gluu.oxauth.service.external.context.ConsentGatheringContext\n print \"Consent-Gathering. Authorizing...\"\n\n if step == 1:\n allowButton = context.getRequestParameters().get(\"authorizeForm:allowButton\")\n if (allowButton != None) and (len(allowButton) > 0):\n print \"Consent-Gathering. Authorization success for step 1\"\n return True\n\n print \"Consent-Gathering. Authorization declined for step 1\"\n elif step == 2:\n allowButton = context.getRequestParameters().get(\"authorizeForm:allowButton\")\n if (allowButton != None) and (len(allowButton) > 0):\n print \"Consent-Gathering. Authorization success for step 2\"\n return True\n\n print \"Consent-Gathering. Authorization declined for step 2\"\n\n return False\n\n def getNextStep(self, step, context):\n return -1\n\n def prepareForStep(self, step, context):\n if not context.isAuthenticated():\n print \"User is not authenticated. Aborting authorization flow ...\"\n return False\n\n if step == 2:\n pageAttributes = context.getPageAttributes()\n \n # Generate random consent gathering request\n consentRequest = \"Requested transaction #%s approval for the amount of sum $ %s.00\" % ( random.randint(100000, 1000000), random.randint(1, 100) )\n pageAttributes.put(\"consent_request\", consentRequest)\n return True\n\n return True\n\n def getStepsCount(self, context):\n return 11\n\n def getPageForStep(self, step, context):\n if step == 1:\n return \"/authz/authorize.xhtml\"\n elif step == 2:\n return \"/authz/transaction.xhtml\"\n\n return \"\"\n", @@ -231,7 +231,7 @@ "revision": 1, "moduleProperties": [ { - "value2": "ldap", + "value2": "db", "value1": "location_type" } ], @@ -245,7 +245,7 @@ "level": 20, "programmingLanguage": "PYTHON", "description": "Basic (with user locking) authentication module", - "locationType": "LDAP", + "locationType": "db", "dn": "inum=4BBE-C6A8,ou=scripts,o=gluu", "inum": "4BBE-C6A8", "script": "# jans-auth is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text.\n# Copyright (c) 2016, Gluu\n#\n# Author: Yuriy Movchan\n# Author: Gasmyr Mougang\n#\n\nfrom org.gluu.service.cdi.util import CdiUtil\nfrom org.gluu.oxauth.security import Identity\nfrom org.gluu.model.custom.script.type.auth import PersonAuthenticationType\nfrom org.gluu.oxauth.service import AuthenticationService\nfrom org.gluu.oxauth.service.common import UserService\nfrom org.gluu.service import CacheService\nfrom org.gluu.util import StringHelper\nfrom org.gluu.persist.exception import AuthenticationException\nfrom javax.faces.application import FacesMessage\nfrom org.gluu.jsf2.message import FacesMessages\nfrom java.time import LocalDateTime, Duration\nfrom java.time.format import DateTimeFormatter\n\nimport java\nimport datetime\nimport json\n\nclass PersonAuthentication(PersonAuthenticationType):\n def __init__(self, currentTimeMillis):\n self.currentTimeMillis = currentTimeMillis\n\n def init(self, customScript, configurationAttributes):\n print \"Basic (lock account). Initialization\"\n\n self.invalidLoginCountAttribute = \"oxCountInvalidLogin\"\n if configurationAttributes.containsKey(\"invalid_login_count_attribute\"):\n self.invalidLoginCountAttribute = configurationAttributes.get(\"invalid_login_count_attribute\").getValue2()\n else:\n print \"Basic (lock account). Initialization. Using default attribute\"\n\n self.maximumInvalidLoginAttemps = 3\n if configurationAttributes.containsKey(\"maximum_invalid_login_attemps\"):\n self.maximumInvalidLoginAttemps = StringHelper.toInteger(configurationAttributes.get(\"maximum_invalid_login_attemps\").getValue2())\n else:\n print \"Basic (lock account). Initialization. Using default number attempts\"\n\n self.lockExpirationTime = 180\n if configurationAttributes.containsKey(\"lock_expiration_time\"):\n self.lockExpirationTime = StringHelper.toInteger(configurationAttributes.get(\"lock_expiration_time\").getValue2())\n else:\n print \"Basic (lock account). Initialization. Using default lock expiration time\"\n\n\n print \"Basic (lock account). Initialized successfully. invalid_login_count_attribute: '%s', maximum_invalid_login_attemps: '%s', lock_expiration_time: '%s'\" % (self.invalidLoginCountAttribute, self.maximumInvalidLoginAttemps, self.lockExpirationTime)\n\n return True \n\n def destroy(self, configurationAttributes):\n print \"Basic (lock account). Destroy\"\n print \"Basic (lock account). Destroyed successfully\"\n return True\n\n def getApiVersion(self):\n return 11\n\n def getAuthenticationMethodClaims(self, requestParameters):\n return None\n \n def isValidAuthenticationMethod(self, usageType, configurationAttributes):\n return True\n\n def getAlternativeAuthenticationMethod(self, usageType, configurationAttributes):\n return None\n\n def authenticate(self, configurationAttributes, requestParameters, step):\n authenticationService = CdiUtil.bean(AuthenticationService)\n\n if step == 1:\n print \"Basic (lock account). Authenticate for step 1\"\n facesMessages = CdiUtil.bean(FacesMessages)\n facesMessages.setKeepMessages()\n identity = CdiUtil.bean(Identity)\n credentials = identity.getCredentials()\n user_name = credentials.getUsername()\n user_password = credentials.getPassword()\n cacheService = CdiUtil.bean(CacheService)\n userService = CdiUtil.bean(UserService)\n\n\n logged_in = False\n if (StringHelper.isNotEmptyString(user_name) and StringHelper.isNotEmptyString(user_password)):\n try:\n logged_in = authenticationService.authenticate(user_name, user_password)\n except AuthenticationException:\n print \"Basic (lock account). Authenticate. Failed to authenticate user '%s'\" % user_name\n\n if logged_in:\n self.setUserAttributeValue(user_name, self.invalidLoginCountAttribute, StringHelper.toString(0))\n else:\n countInvalidLoginArributeValue = self.getUserAttributeValue(user_name, self.invalidLoginCountAttribute)\n userSatus = self.getUserAttributeValue(user_name, \"gluuStatus\")\n print \"Current user '%s' status is '%s'\" % ( user_name, userSatus )\n\n countInvalidLogin = StringHelper.toInteger(countInvalidLoginArributeValue, 0)\n\n if countInvalidLogin < self.maximumInvalidLoginAttemps:\n countInvalidLogin = countInvalidLogin + 1\n remainingAttempts = self.maximumInvalidLoginAttemps - countInvalidLogin\n\n print \"Remaining login count attempts '%s' for user '%s'\" % ( remainingAttempts, user_name )\n\n self.setUserAttributeValue(user_name, self.invalidLoginCountAttribute, StringHelper.toString(countInvalidLogin))\n if remainingAttempts > 0 and userSatus == \"active\":\n facesMessages.add(FacesMessage.SEVERITY_INFO, StringHelper.toString(remainingAttempts)+\" more attempt(s) before account is LOCKED!\")\n\n if (countInvalidLogin >= self.maximumInvalidLoginAttemps) and ((userSatus == None) or (userSatus == \"active\")):\n print \"Basic (lock account). Locking '%s' for '%s' seconds\" % ( user_name, self.lockExpirationTime)\n self.lockUser(user_name)\n return False\n\n if (countInvalidLogin >= self.maximumInvalidLoginAttemps) and userSatus == \"inactive\":\n print \"Basic (lock account). User '%s' is locked. Checking if we can unlock him\" % user_name\n \n unlock_and_authenticate = False\n\n object_from_store = cacheService.get(None, \"lock_user_\" + user_name)\n if object_from_store == None:\n # Object in cache was expired. We need to unlock user\n print \"Basic (lock account). User locking details for user '%s' not exists\" % user_name\n unlock_and_authenticate = True\n else:\n # Analyze object from cache\n user_lock_details = json.loads(object_from_store)\n\n user_lock_details_locked = user_lock_details['locked']\n user_lock_details_created = user_lock_details['created']\n user_lock_details_created_date = LocalDateTime.parse(user_lock_details_created, DateTimeFormatter.ISO_LOCAL_DATE_TIME)\n user_lock_details_created_diff = Duration.between(user_lock_details_created_date, LocalDateTime.now()).getSeconds()\n print \"Basic (lock account). Get user '%s' locking details. locked: '%s', Created: '%s', Difference in seconds: '%s'\" % ( user_name, user_lock_details_locked, user_lock_details_created, user_lock_details_created_diff )\n\n if user_lock_details_locked and user_lock_details_created_diff >= self.lockExpirationTime:\n print \"Basic (lock account). Unlocking user '%s' after lock expiration\" % user_name\n unlock_and_authenticate = True\n\n if unlock_and_authenticate:\n self.unLockUser(user_name)\n self.setUserAttributeValue(user_name, self.invalidLoginCountAttribute, StringHelper.toString(0))\n logged_in = authenticationService.authenticate(user_name, user_password)\n if not logged_in:\n # Update number of attempts \n self.setUserAttributeValue(user_name, self.invalidLoginCountAttribute, StringHelper.toString(1))\n if self.maximumInvalidLoginAttemps == 1:\n # Lock user if maximum count login attempts is 1 \n self.lockUser(user_name)\n return False\n\n\n return logged_in\n else:\n return False\n\n def prepareForStep(self, configurationAttributes, requestParameters, step):\n if step == 1:\n print \"Basic (lock account). Prepare for Step 1\"\n return True\n else:\n return False\n\n def getExtraParametersForStep(self, configurationAttributes, step):\n return None\n\n def getCountAuthenticationSteps(self, configurationAttributes):\n return 1\n\n def getPageForStep(self, configurationAttributes, step):\n return \"\"\n \n def getNextStep(self, configurationAttributes, requestParameters, step):\n return -1\n\n def getLogoutExternalUrl(self, configurationAttributes, requestParameters):\n print \"Get external logout URL call\"\n return None\n\n def logout(self, configurationAttributes, requestParameters):\n return True\n\n def getUserAttributeValue(self, user_name, attribute_name):\n if StringHelper.isEmpty(user_name):\n return None\n\n userService = CdiUtil.bean(UserService)\n\n find_user_by_uid = userService.getUser(user_name, attribute_name)\n if find_user_by_uid == None:\n return None\n\n custom_attribute_value = userService.getCustomAttribute(find_user_by_uid, attribute_name)\n if custom_attribute_value == None:\n return None\n \n attribute_value = custom_attribute_value.getValue()\n\n print \"Basic (lock account). Get user attribute. User's '%s' attribute '%s' value is '%s'\" % (user_name, attribute_name, attribute_value)\n\n return attribute_value\n\n def setUserAttributeValue(self, user_name, attribute_name, attribute_value):\n if StringHelper.isEmpty(user_name):\n return None\n\n userService = CdiUtil.bean(UserService)\n\n find_user_by_uid = userService.getUser(user_name)\n if find_user_by_uid == None:\n return None\n \n userService.setCustomAttribute(find_user_by_uid, attribute_name, attribute_value)\n updated_user = userService.updateUser(find_user_by_uid)\n\n print \"Basic (lock account). Set user attribute. User's '%s' attribute '%s' value is '%s'\" % (user_name, attribute_name, attribute_value)\n\n return updated_user\n\n def lockUser(self, user_name):\n if StringHelper.isEmpty(user_name):\n return None\n\n userService = CdiUtil.bean(UserService)\n cacheService= CdiUtil.bean(CacheService)\n facesMessages = CdiUtil.bean(FacesMessages)\n facesMessages.setKeepMessages()\n\n find_user_by_uid = userService.getUser(user_name)\n if (find_user_by_uid == None):\n return None\n\n status_attribute_value = userService.getCustomAttribute(find_user_by_uid, \"gluuStatus\")\n if status_attribute_value != None:\n user_status = status_attribute_value.getValue()\n if StringHelper.equals(user_status, \"inactive\"):\n print \"Basic (lock account). Lock user. User '%s' locked already\" % user_name\n return\n \n userService.setCustomAttribute(find_user_by_uid, \"gluuStatus\", \"inactive\")\n updated_user = userService.updateUser(find_user_by_uid)\n\n object_to_store = json.dumps({'locked': True, 'created': LocalDateTime.now().toString()}, separators=(',',':'))\n\n cacheService.put(StringHelper.toString(self.lockExpirationTime), \"lock_user_\"+user_name, object_to_store);\n facesMessages.add(FacesMessage.SEVERITY_ERROR, \"Your account is locked. Please try again after \" + StringHelper.toString(self.lockExpirationTime) + \" secs\")\n\n print \"Basic (lock account). Lock user. User '%s' locked\" % user_name\n\n def unLockUser(self, user_name):\n if StringHelper.isEmpty(user_name):\n return None\n\n userService = CdiUtil.bean(UserService)\n cacheService= CdiUtil.bean(CacheService)\n\n find_user_by_uid = userService.getUser(user_name)\n if (find_user_by_uid == None):\n return None\n\n object_to_store = json.dumps({'locked': False, 'created': LocalDateTime.now().toString()}, separators=(',',':'))\n cacheService.put(StringHelper.toString(self.lockExpirationTime), \"lock_user_\"+user_name, object_to_store);\n\n userService.setCustomAttribute(find_user_by_uid, \"gluuStatus\", \"active\")\n userService.setCustomAttribute(find_user_by_uid, self.invalidLoginCountAttribute, None)\n updated_user = userService.updateUser(find_user_by_uid)\n\n\n print \"Basic (lock account). Lock user. User '%s' unlocked\" % user_name\n", @@ -253,7 +253,7 @@ "revision": 1, "moduleProperties": [ { - "value2": "ldap", + "value2": "db", "value1": "location_type" }, { @@ -288,7 +288,7 @@ "level": 30, "programmingLanguage": "PYTHON", "description": "Cert authentication module", - "locationType": "LDAP", + "locationType": "db", "dn": "inum=2124-0CF1,ou=scripts,o=gluu", "inum": "2124-0CF1", "script": "#\n# jans-auth is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text.\n# Copyright (c) 2016, Gluu\n#\n# Author: Yuriy Movchan\n#\n\nfrom org.gluu.service.cdi.util import CdiUtil\nfrom org.gluu.model.custom.script.type.auth import PersonAuthenticationType\nfrom javax.faces.context import FacesContext\nfrom org.gluu.oxauth.security import Identity\nfrom org.gluu.oxauth.service import AuthenticationService\nfrom org.gluu.oxauth.service.common import UserService\nfrom org.gluu.util import StringHelper\nfrom org.gluu.oxauth.util import ServerUtil\nfrom org.gluu.oxauth.service.common import EncryptionService\nfrom java.util import Arrays\nfrom org.gluu.oxauth.cert.fingerprint import FingerprintHelper\nfrom org.gluu.oxauth.cert.validation import GenericCertificateVerifier, PathCertificateVerifier, OCSPCertificateVerifier, CRLCertificateVerifier\nfrom org.gluu.oxauth.cert.validation.model import ValidationStatus\nfrom org.gluu.oxauth.util import CertUtil\nfrom org.gluu.oxauth.model.util import CertUtils\nfrom org.gluu.oxauth.service.net import HttpService\nfrom org.apache.http.params import CoreConnectionPNames\n\nimport sys\nimport base64\nimport urllib\n\nimport java\nimport json\n\nclass PersonAuthentication(PersonAuthenticationType):\n def __init__(self, currentTimeMillis):\n self.currentTimeMillis = currentTimeMillis\n\n def init(self, customScript, configurationAttributes):\n print \"Cert. Initialization\"\n\n if not (configurationAttributes.containsKey(\"chain_cert_file_path\")):\n print \"Cert. Initialization. Property chain_cert_file_path is mandatory\"\n return False\n\n if not (configurationAttributes.containsKey(\"map_user_cert\")):\n print \"Cert. Initialization. Property map_user_cert is mandatory\"\n return False\n\n chain_cert_file_path = configurationAttributes.get(\"chain_cert_file_path\").getValue2()\n\n self.chain_certs = CertUtil.loadX509CertificateFromFile(chain_cert_file_path)\n if self.chain_certs == None:\n print \"Cert. Initialization. Failed to load chain certificates from '%s'\" % chain_cert_file_path\n return False\n\n print \"Cert. Initialization. Loaded '%d' chain certificates\" % self.chain_certs.size()\n \n crl_max_response_size = 5 * 1024 * 1024 # 10Mb\n if configurationAttributes.containsKey(\"crl_max_response_size\"):\n crl_max_response_size = StringHelper.toInteger(configurationAttributes.get(\"crl_max_response_size\").getValue2(), crl_max_response_size)\n print \"Cert. Initialization. CRL max response size is '%d'\" % crl_max_response_size\n\n # Define array to order methods correctly\n self.validator_types = [ 'generic', 'path', 'ocsp', 'crl']\n self.validators = { 'generic' : [GenericCertificateVerifier(), False],\n 'path' : [PathCertificateVerifier(False), False],\n 'ocsp' : [OCSPCertificateVerifier(), False],\n 'crl' : [CRLCertificateVerifier(crl_max_response_size), False] }\n\n for type in self.validator_types:\n validator_param_name = \"use_%s_validator\" % type\n if configurationAttributes.containsKey(validator_param_name):\n validator_status = StringHelper.toBoolean(configurationAttributes.get(validator_param_name).getValue2(), False)\n self.validators[type][1] = validator_status\n\n print \"Cert. Initialization. Validation method '%s' status: '%s'\" % (type, self.validators[type][1])\n\n self.map_user_cert = StringHelper.toBoolean(configurationAttributes.get(\"map_user_cert\").getValue2(), False)\n print \"Cert. Initialization. map_user_cert: '%s'\" % self.map_user_cert\n\n self.enabled_recaptcha = self.initRecaptcha(configurationAttributes)\n print \"Cert. Initialization. enabled_recaptcha: '%s'\" % self.enabled_recaptcha\n\n print \"Cert. Initialized successfully\"\n\n return True \n\n def destroy(self, configurationAttributes):\n print \"Cert. Destroy\"\n\n for type in self.validator_types:\n self.validators[type][0].destroy()\n\n print \"Cert. Destroyed successfully\"\n\n return True\n\n def getApiVersion(self):\n return 11\n\n def getAuthenticationMethodClaims(self, requestParameters):\n return None\n\n def isValidAuthenticationMethod(self, usageType, configurationAttributes):\n return True\n\n def getAlternativeAuthenticationMethod(self, usageType, configurationAttributes):\n return None\n\n def authenticate(self, configurationAttributes, requestParameters, step):\n identity = CdiUtil.bean(Identity)\n credentials = identity.getCredentials()\n\n user_name = credentials.getUsername()\n\n userService = CdiUtil.bean(UserService)\n authenticationService = CdiUtil.bean(AuthenticationService)\n\n if step == 1:\n print \"Cert. Authenticate for step 1\"\n login_button = ServerUtil.getFirstValue(requestParameters, \"loginForm:loginButton\")\n if StringHelper.isEmpty(login_button):\n print \"Cert. Authenticate for step 1. Form were submitted incorrectly\"\n return False\n if self.enabled_recaptcha:\n print \"Cert. Authenticate for step 1. Validating recaptcha response\"\n recaptcha_response = ServerUtil.getFirstValue(requestParameters, \"g-recaptcha-response\")\n\n recaptcha_result = self.validateRecaptcha(recaptcha_response)\n print \"Cert. Authenticate for step 1. recaptcha_result: '%s'\" % recaptcha_result\n \n return recaptcha_result\n\n return True\n elif step == 2:\n print \"Cert. Authenticate for step 2\"\n\n # Validate if user selected certificate\n cert_x509 = self.getSessionAttribute(\"cert_x509\")\n if cert_x509 == None:\n print \"Cert. Authenticate for step 2. User not selected any certs\"\n identity.setWorkingParameter(\"cert_selected\", False)\n \n # Return True to inform user how to reset workflow\n return True\n else:\n identity.setWorkingParameter(\"cert_selected\", True)\n x509Certificate = self.certFromString(cert_x509)\n\n subjectX500Principal = x509Certificate.getSubjectX500Principal()\n print \"Cert. Authenticate for step 2. User selected certificate with DN '%s'\" % subjectX500Principal\n \n # Validate certificates which user selected\n valid = self.validateCertificate(x509Certificate)\n if not valid:\n print \"Cert. Authenticate for step 2. Certificate DN '%s' is not valid\" % subjectX500Principal\n identity.setWorkingParameter(\"cert_valid\", False)\n \n # Return True to inform user how to reset workflow\n return True\n\n identity.setWorkingParameter(\"cert_valid\", True)\n \n # Calculate certificate fingerprint\n x509CertificateFingerprint = self.calculateCertificateFingerprint(x509Certificate)\n identity.setWorkingParameter(\"cert_x509_fingerprint\", x509CertificateFingerprint)\n print \"Cert. Authenticate for step 2. Fingerprint is '%s' of certificate with DN '%s'\" % (x509CertificateFingerprint, subjectX500Principal)\n \n # Attempt to find user by certificate fingerprint\n cert_user_external_uid = \"cert:%s\" % x509CertificateFingerprint\n print \"Cert. Authenticate for step 2. Attempting to find user by oxExternalUid attribute value %s\" % cert_user_external_uid\n\n find_user_by_external_uid = userService.getUserByAttribute(\"oxExternalUid\", cert_user_external_uid)\n if find_user_by_external_uid == None:\n print \"Cert. Authenticate for step 2. Failed to find user\"\n \n if self.map_user_cert:\n print \"Cert. Authenticate for step 2. Storing cert_user_external_uid for step 3\"\n identity.setWorkingParameter(\"cert_user_external_uid\", cert_user_external_uid)\n return True\n else:\n print \"Cert. Authenticate for step 2. Mapping cert to user account is not allowed\"\n identity.setWorkingParameter(\"cert_count_login_steps\", 2)\n return False\n\n foundUserName = find_user_by_external_uid.getUserId()\n print \"Cert. Authenticate for step 2. foundUserName: \" + foundUserName\n\n logged_in = False\n userService = CdiUtil.bean(UserService)\n logged_in = authenticationService.authenticate(foundUserName)\n \n print \"Cert. Authenticate for step 2. Setting count steps to 2\"\n identity.setWorkingParameter(\"cert_count_login_steps\", 2)\n\n return logged_in\n elif step == 3:\n print \"Cert. Authenticate for step 3\"\n\n cert_user_external_uid = self.getSessionAttribute(\"cert_user_external_uid\")\n if cert_user_external_uid == None:\n print \"Cert. Authenticate for step 3. cert_user_external_uid is empty\"\n return False\n\n user_password = credentials.getPassword()\n\n logged_in = False\n if (StringHelper.isNotEmptyString(user_name) and StringHelper.isNotEmptyString(user_password)):\n logged_in = authenticationService.authenticate(user_name, user_password)\n\n if (not logged_in):\n return False\n\n # Double check just to make sure. We did checking in previous step\n # Check if there is user which has cert_user_external_uid\n # Avoid mapping user cert to more than one IDP account\n find_user_by_external_uid = userService.getUserByAttribute(\"oxExternalUid\", cert_user_external_uid)\n if find_user_by_external_uid == None:\n # Add cert_user_external_uid to user's external GUID list\n find_user_by_external_uid = userService.addUserAttribute(user_name, \"oxExternalUid\", cert_user_external_uid)\n if find_user_by_external_uid == None:\n print \"Cert. Authenticate for step 3. Failed to update current user\"\n return False\n\n return True\n \n return True\n else:\n return False\n\n def prepareForStep(self, configurationAttributes, requestParameters, step):\n print \"Cert. Prepare for step %d\" % step\n identity = CdiUtil.bean(Identity)\n \n if step == 1:\n if self.enabled_recaptcha:\n identity.setWorkingParameter(\"recaptcha_site_key\", self.recaptcha_creds['site_key'])\n elif step == 2:\n # Store certificate in session\n facesContext = CdiUtil.bean(FacesContext)\n externalContext = facesContext.getExternalContext()\n request = externalContext.getRequest()\n\n # Try to get certificate from header X-ClientCert\n clientCertificate = externalContext.getRequestHeaderMap().get(\"X-ClientCert\")\n if clientCertificate != None:\n x509Certificate = self.certFromPemString(clientCertificate)\n identity.setWorkingParameter(\"cert_x509\", self.certToString(x509Certificate))\n print \"Cert. Prepare for step 2. Storing user certificate obtained from 'X-ClientCert' header\"\n return True\n\n # Try to get certificate from attribute javax.servlet.request.X509Certificate\n x509Certificates = request.getAttribute('javax.servlet.request.X509Certificate')\n if (x509Certificates != None) and (len(x509Certificates) > 0):\n identity.setWorkingParameter(\"cert_x509\", self.certToString(x509Certificates[0]))\n print \"Cert. Prepare for step 2. Storing user certificate obtained from 'javax.servlet.request.X509Certificate' attribute\"\n return True\n\n if step < 4:\n return True\n else:\n return False\n\n def getExtraParametersForStep(self, configurationAttributes, step):\n return Arrays.asList(\"cert_selected\", \"cert_valid\", \"cert_x509\", \"cert_x509_fingerprint\", \"cert_count_login_steps\", \"cert_user_external_uid\")\n\n def getCountAuthenticationSteps(self, configurationAttributes):\n cert_count_login_steps = self.getSessionAttribute(\"cert_count_login_steps\")\n if cert_count_login_steps != None:\n return cert_count_login_steps\n else:\n return 3\n\n def getPageForStep(self, configurationAttributes, step):\n if step == 1:\n return \"/auth/cert/login.xhtml\"\n if step == 2:\n return \"/auth/cert/cert-login.xhtml\"\n elif step == 3:\n cert_selected = self.getSessionAttribute(\"cert_selected\")\n if True != cert_selected:\n return \"/auth/cert/cert-not-selected.xhtml\"\n\n cert_valid = self.getSessionAttribute(\"cert_valid\")\n if True != cert_valid:\n return \"/auth/cert/cert-invalid.xhtml\"\n \n return \"/login.xhtml\"\n\n return \"\"\n\n def logout(self, configurationAttributes, requestParameters):\n return True\n\n def processBasicAuthentication(self, credentials):\n userService = CdiUtil.bean(UserService)\n authenticationService = CdiUtil.bean(AuthenticationService)\n\n user_name = credentials.getUsername()\n user_password = credentials.getPassword()\n\n logged_in = False\n if (StringHelper.isNotEmptyString(user_name) and StringHelper.isNotEmptyString(user_password)):\n logged_in = authenticationService.authenticate(user_name, user_password)\n\n if (not logged_in):\n return None\n\n find_user_by_uid = authenticationService.getAuthenticatedUser()\n if (find_user_by_uid == None):\n print \"Cert. Process basic authentication. Failed to find user '%s'\" % user_name\n return None\n \n return find_user_by_uid\n\n def getSessionAttribute(self, attribute_name):\n identity = CdiUtil.bean(Identity)\n\n # Try to get attribute value from Seam event context\n if identity.isSetWorkingParameter(attribute_name):\n return identity.getWorkingParameter(attribute_name)\n \n # Try to get attribute from persistent session\n session_id = identity.getSessionId()\n if session_id == None:\n return None\n\n session_attributes = session_id.getSessionAttributes()\n if session_attributes == None:\n return None\n\n if session_attributes.containsKey(attribute_name):\n return session_attributes.get(attribute_name)\n\n return None\n\n def calculateCertificateFingerprint(self, x509Certificate):\n print \"Cert. Calculate fingerprint for certificate DN '%s'\" % x509Certificate.getSubjectX500Principal()\n \n publicKey = x509Certificate.getPublicKey()\n \n # Use oxAuth implementation\n fingerprint = FingerprintHelper.getPublicKeySshFingerprint(publicKey)\n \n return fingerprint \n\n def validateCertificate(self, x509Certificate):\n subjectX500Principal = x509Certificate.getSubjectX500Principal()\n\n print \"Cert. Validating certificate with DN '%s'\" % subjectX500Principal\n \n validation_date = java.util.Date()\n\n for type in self.validator_types:\n if self.validators[type][1]:\n result = self.validators[type][0].validate(x509Certificate, self.chain_certs, validation_date)\n print \"Cert. Validate certificate: '%s'. Validation method '%s' result: '%s'\" % (subjectX500Principal, type, result)\n \n if (result.getValidity() != ValidationStatus.CertificateValidity.VALID):\n print \"Cert. Certificate: '%s' is invalid\" % subjectX500Principal\n return False\n \n return True\n\n def certToString(self, x509Certificate):\n if x509Certificate == None:\n return None\n return base64.b64encode(x509Certificate.getEncoded())\n\n def certFromString(self, x509CertificateEncoded):\n x509CertificateDecoded = base64.b64decode(x509CertificateEncoded)\n return CertUtils.x509CertificateFromBytes(x509CertificateDecoded)\n\n def certFromPemString(self, pemCertificate):\n x509CertificateEncoded = pemCertificate.replace(\"-----BEGIN CERTIFICATE-----\", \"\").replace(\"-----END CERTIFICATE-----\", \"\").strip()\n return self.certFromString(x509CertificateEncoded)\n\n def initRecaptcha(self, configurationAttributes):\n print \"Cert. Initialize recaptcha\"\n if not configurationAttributes.containsKey(\"credentials_file\"):\n return False\n\n cert_creds_file = configurationAttributes.get(\"credentials_file\").getValue2()\n\n # Load credentials from file\n f = open(cert_creds_file, 'r')\n try:\n creds = json.loads(f.read())\n except:\n print \"Cert. Initialize recaptcha. Failed to load credentials from file: %s\" % cert_creds_file\n return False\n finally:\n f.close()\n \n try:\n recaptcha_creds = creds[\"recaptcha\"]\n except:\n print \"Cert. Initialize recaptcha. Invalid credentials file '%s' format:\" % cert_creds_file\n return False\n \n self.recaptcha_creds = None\n if recaptcha_creds[\"enabled\"]:\n print \"Cert. Initialize recaptcha. Recaptcha is enabled\"\n\n encryptionService = CdiUtil.bean(EncryptionService)\n\n site_key = recaptcha_creds[\"site_key\"]\n secret_key = recaptcha_creds[\"secret_key\"]\n\n try:\n site_key = encryptionService.decrypt(site_key)\n except:\n # Ignore exception. Value is not encrypted\n print \"Cert. Initialize recaptcha. Assuming that 'site_key' in not encrypted\"\n\n try:\n secret_key = encryptionService.decrypt(secret_key)\n except:\n # Ignore exception. Value is not encrypted\n print \"Cert. Initialize recaptcha. Assuming that 'secret_key' in not encrypted\"\n\n \n self.recaptcha_creds = { 'site_key' : site_key, \"secret_key\" : secret_key }\n print \"Cert. Initialize recaptcha. Recaptcha is configured correctly\"\n\n return True\n else:\n print \"Cert. Initialize recaptcha. Recaptcha is disabled\"\n\n return False\n\n def validateRecaptcha(self, recaptcha_response):\n print \"Cert. Validate recaptcha response\"\n\n facesContext = CdiUtil.bean(FacesContext)\n request = facesContext.getExternalContext().getRequest()\n\n remoteip = ServerUtil.getIpAddress(request)\n print \"Cert. Validate recaptcha response. remoteip: '%s'\" % remoteip\n\n httpService = CdiUtil.bean(HttpService)\n\n http_client = httpService.getHttpsClient()\n http_client_params = http_client.getParams()\n http_client_params.setIntParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 15 * 1000)\n \n recaptcha_validation_url = \"https://www.google.com/recaptcha/api/siteverify\"\n recaptcha_validation_request = urllib.urlencode({ \"secret\" : self.recaptcha_creds['secret_key'], \"response\" : recaptcha_response, \"remoteip\" : remoteip })\n recaptcha_validation_headers = { \"Content-type\" : \"application/x-www-form-urlencoded\", \"Accept\" : \"application/json\" }\n\n try:\n http_service_response = httpService.executePost(http_client, recaptcha_validation_url, None, recaptcha_validation_headers, recaptcha_validation_request)\n http_response = http_service_response.getHttpResponse()\n except:\n print \"Cert. Validate recaptcha response. Exception: \", sys.exc_info()[1]\n return False\n\n try:\n if not httpService.isResponseStastusCodeOk(http_response):\n print \"Cert. Validate recaptcha response. Get invalid response from validation server: \", str(http_response.getStatusLine().getStatusCode())\n httpService.consume(http_response)\n return False\n \n response_bytes = httpService.getResponseContent(http_response)\n response_string = httpService.convertEntityToString(response_bytes)\n httpService.consume(http_response)\n finally:\n http_service_response.closeConnection()\n\n if response_string == None:\n print \"Cert. Validate recaptcha response. Get empty response from validation server\"\n return False\n \n response = json.loads(response_string)\n \n return response[\"success\"]\n\n def getNextStep(self, configurationAttributes, requestParameters, step):\n return -1\n\n def getLogoutExternalUrl(self, configurationAttributes, requestParameters):\n print \"Get external logout URL call\"\n return None", @@ -296,7 +296,7 @@ "revision": 1, "moduleProperties": [ { - "value2": "ldap", + "value2": "db", "value1": "location_type" }, { @@ -356,7 +356,7 @@ "level": 40, "programmingLanguage": "PYTHON", "description": "OTP Validation of passwords using Yubicloud authentication module", - "locationType": "LDAP", + "locationType": "db", "dn": "inum=24FD-B96E,ou=scripts,o=gluu", "inum": "24FD-B96E", "script": "# jans-auth is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text.\n# Copyright (c) 2016, Gluu\n#\n# Author: Yuriy Movchan, Arunmozhi\n#\n\nfrom org.gluu.service.cdi.util import CdiUtil\nfrom org.gluu.oxauth.security import Identity\nfrom org.gluu.model.custom.script.type.auth import PersonAuthenticationType\nfrom org.gluu.oxauth.service import UserService\nfrom org.gluu.util import StringHelper\n\nimport java\n\nimport urllib2\nimport urllib\nimport uuid\n\n\nclass PersonAuthentication(PersonAuthenticationType):\n def __init__(self, currentTimeMillis):\n self.currentTimeMillis = currentTimeMillis\n\n def init(self, customScript, configurationAttributes):\n print \"Yubicloud. Initialization\"\n\n self.api_server = configurationAttributes.get(\"yubicloud_uri\").getValue2()\n self.api_key = configurationAttributes.get(\"yubicloud_api_key\").getValue2()\n self.client_id = configurationAttributes.get(\"yubicloud_id\").getValue2()\n\n return True\n\n def destroy(self, configurationAttributes):\n print \"Yubicloud. Destroyed successfully\"\n return True\n\n def getApiVersion(self):\n return 11\n \n def getAuthenticationMethodClaims(self, requestParameters):\n return None\n \n def isValidAuthenticationMethod(self, usageType, configurationAttributes):\n return True\n\n def getAlternativeAuthenticationMethod(self, usageType, configurationAttributes):\n return None\n\n def authenticate(self, configurationAttributes, requestParameters, step):\n if (step == 1):\n print \"Yubicloud. Authenticate for step 1\"\n\n identity = CdiUtil.bean(Identity)\n credentials = identity.getCredentials()\n\n username = credentials.getUsername()\n otp = credentials.getPassword()\n\n # Validate otp length\n if len(otp) < 32 or len(otp) > 48:\n print \"Yubicloud. Invalid OTP length\"\n return False\n\n user_service = CdiUtil.bean(UserService)\n user = user_service.getUser(username)\n\n public_key = user.getAttribute('yubikeyId')\n\n # Match the user with the yubikey\n if public_key not in otp:\n print \"Yubicloud. Public Key not matching OTP\"\n return False\n\n data = \"\"\n try:\n nonce = str(uuid.uuid4()).replace(\"-\", \"\")\n params = urllib.urlencode({\"id\": self.client_id, \"otp\": otp, \"nonce\": nonce})\n url = \"https://\" + self.api_server + \"/wsapi/2.0/verify/?\" + params\n f = urllib2.urlopen(url)\n data = f.read()\n except Exception as e:\n print \"Yubicloud. Exception \", e\n\n if 'status=OK' in data:\n user_service.authenticate(username)\n print \"Yubicloud. Authentication Successful\"\n return True\n\n print \"Yubicloud. End of Step 1. Returning False.\"\n return False\n else:\n return False\n\n def prepareForStep(self, configurationAttributes, requestParameters, step):\n if (step == 1):\n print \"Yubicloud. Prepare for Step 1\"\n return True\n else:\n return False\n\n def getExtraParametersForStep(self, configurationAttributes, step):\n return None\n\n def getCountAuthenticationSteps(self, configurationAttributes):\n return 1\n\n def getPageForStep(self, configurationAttributes, step):\n return \"\"\n\n def getNextStep(self, configurationAttributes, requestParameters, step):\n return -1\n\n def getLogoutExternalUrl(self, configurationAttributes, requestParameters):\n print \"Get external logout URL call\"\n return None\n\n def logout(self, configurationAttributes, requestParameters):\n return True\n", @@ -397,7 +397,7 @@ "level": 40, "programmingLanguage": "PYTHON", "description": "HOTP/TOPT authentication module", - "locationType": "LDAP", + "locationType": "db", "dn": "inum=5018-D4BF,ou=scripts,o=gluu", "inum": "5018-D4BF", "script": "# jans-auth is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text.\n# Copyright (c) 2016, Gluu\n#\n# Author: Yuriy Movchan\n#\n\n# Requires the following custom properties and values:\n# otp_type: totp/hotp\n# issuer: Gluu Inc\n# otp_conf_file: /etc/certs/otp_configuration.json\n#\n# These are non mandatory custom properties and values:\n# label: Gluu OTP\n# qr_options: { width: 400, height: 400 }\n# registration_uri: https://ce-dev.gluu.org/identity/register\n\nimport jarray\nimport json\nimport sys\nfrom com.google.common.io import BaseEncoding\nfrom com.lochbridge.oath.otp import HOTP\nfrom com.lochbridge.oath.otp import HOTPValidator\nfrom com.lochbridge.oath.otp import HmacShaAlgorithm\nfrom com.lochbridge.oath.otp import TOTP\nfrom com.lochbridge.oath.otp.keyprovisioning import OTPAuthURIBuilder\nfrom com.lochbridge.oath.otp.keyprovisioning import OTPKey\nfrom com.lochbridge.oath.otp.keyprovisioning.OTPKey import OTPType\nfrom java.security import SecureRandom\nfrom java.util import Arrays\nfrom java.util.concurrent import TimeUnit\nfrom javax.faces.application import FacesMessage\nfrom org.gluu.jsf2.message import FacesMessages\nfrom org.gluu.model.custom.script.type.auth import PersonAuthenticationType\nfrom org.gluu.oxauth.security import Identity\nfrom org.gluu.oxauth.service import AuthenticationService, SessionIdService\nfrom org.gluu.oxauth.service.common import UserService\nfrom org.gluu.oxauth.util import ServerUtil\nfrom org.gluu.service.cdi.util import CdiUtil\nfrom org.gluu.util import StringHelper\n\n\nclass PersonAuthentication(PersonAuthenticationType):\n def __init__(self, currentTimeMillis):\n self.currentTimeMillis = currentTimeMillis\n\n def init(self, customScript, configurationAttributes):\n print \"OTP. Initialization\"\n\n if not configurationAttributes.containsKey(\"otp_type\"):\n print \"OTP. Initialization. Property otp_type is mandatory\"\n return False\n self.otpType = configurationAttributes.get(\"otp_type\").getValue2()\n\n if not self.otpType in [\"hotp\", \"totp\"]:\n print \"OTP. Initialization. Property value otp_type is invalid\"\n return False\n\n if not configurationAttributes.containsKey(\"issuer\"):\n print \"OTP. Initialization. Property issuer is mandatory\"\n return False\n self.otpIssuer = configurationAttributes.get(\"issuer\").getValue2()\n\n self.customLabel = None\n if configurationAttributes.containsKey(\"label\"):\n self.customLabel = configurationAttributes.get(\"label\").getValue2()\n\n self.customQrOptions = {}\n if configurationAttributes.containsKey(\"qr_options\"):\n self.customQrOptions = configurationAttributes.get(\"qr_options\").getValue2()\n\n self.registrationUri = None\n if configurationAttributes.containsKey(\"registration_uri\"):\n self.registrationUri = configurationAttributes.get(\"registration_uri\").getValue2()\n\n validOtpConfiguration = self.loadOtpConfiguration(configurationAttributes)\n if not validOtpConfiguration:\n return False\n\n print \"OTP. Initialized successfully\"\n return True\n\n def destroy(self, configurationAttributes):\n print \"OTP. Destroy\"\n print \"OTP. Destroyed successfully\"\n return True\n\n def getApiVersion(self):\n return 11\n \n def getAuthenticationMethodClaims(self, requestParameters):\n return None\n\n def getNextStep(self, configurationAttributes, requestParameters, step):\n print \"getNextStep Invoked\"\n # If user not pass current step change step to previous\n identity = CdiUtil.bean(Identity)\n retry_current_step = identity.getWorkingParameter(\"retry_current_step\")\n if retry_current_step:\n print \"OTP. Get next step. Retrying current step %s\" % step\n # Remove old QR code\n #identity.setWorkingParameter(\"super_gluu_request\", \"timeout\")\n resultStep = step\n return resultStep\n return -1\n\n def isValidAuthenticationMethod(self, usageType, configurationAttributes):\n return True\n\n def getAlternativeAuthenticationMethod(self, usageType, configurationAttributes):\n return None\n\n def authenticate(self, configurationAttributes, requestParameters, step):\n authenticationService = CdiUtil.bean(AuthenticationService)\n\n identity = CdiUtil.bean(Identity)\n credentials = identity.getCredentials()\n\n self.setRequestScopedParameters(identity)\n\n if step == 1:\n print \"OTP. Authenticate for step 1\"\n authenticated_user = self.processBasicAuthentication(credentials)\n if authenticated_user == None:\n return False\n\n otp_auth_method = \"authenticate\"\n # Uncomment this block if you need to allow user second OTP registration\n #enrollment_mode = ServerUtil.getFirstValue(requestParameters, \"loginForm:registerButton\")\n #if StringHelper.isNotEmpty(enrollment_mode):\n # otp_auth_method = \"enroll\"\n\n if otp_auth_method == \"authenticate\":\n user_enrollments = self.findEnrollments(authenticated_user.getUserId())\n if len(user_enrollments) == 0:\n otp_auth_method = \"enroll\"\n print \"OTP. Authenticate for step 1. There is no OTP enrollment for user '%s'. Changing otp_auth_method to '%s'\" % (authenticated_user.getUserId(), otp_auth_method)\n\n if otp_auth_method == \"enroll\":\n print \"OTP. Authenticate for step 1. Setting count steps: '%s'\" % 3\n identity.setWorkingParameter(\"otp_count_login_steps\", 3)\n\n print \"OTP. Authenticate for step 1. otp_auth_method: '%s'\" % otp_auth_method\n identity.setWorkingParameter(\"otp_auth_method\", otp_auth_method)\n\n return True\n elif step == 2:\n print \"OTP. Authenticate for step 2\"\n\n authenticationService = CdiUtil.bean(AuthenticationService)\n user = authenticationService.getAuthenticatedUser()\n if user == None:\n print \"OTP. Authenticate for step 2. Failed to determine user name\"\n return False\n\n session_id_validation = self.validateSessionId(identity)\n if not session_id_validation:\n return False\n\n # Restore state from session\n identity.setWorkingParameter(\"retry_current_step\", False)\n otp_auth_method = identity.getWorkingParameter(\"otp_auth_method\")\n if otp_auth_method == 'enroll':\n auth_result = ServerUtil.getFirstValue(requestParameters, \"auth_result\")\n if not StringHelper.isEmpty(auth_result):\n # defect fix #1225 - Retry the step, show QR code again\n if auth_result == 'timeout':\n\t\t\t\t\t\tprint \"OTP. QR-code timeout. Authenticate for step %s. Reinitializing current step\" % step\n\t\t\t\t\t\tidentity.setWorkingParameter(\"retry_current_step\", True)\n\t\t\t\t\t\treturn True\n\n print \"OTP. Authenticate for step 2. User not enrolled OTP\"\n return False\n\n print \"OTP. Authenticate for step 2. Skipping this step during enrollment\"\n return True\n\n otp_auth_result = self.processOtpAuthentication(requestParameters, user.getUserId(), identity, otp_auth_method)\n print \"OTP. Authenticate for step 2. OTP authentication result: '%s'\" % otp_auth_result\n\n return otp_auth_result\n elif step == 3:\n print \"OTP. Authenticate for step 3\"\n\n authenticationService = CdiUtil.bean(AuthenticationService)\n user = authenticationService.getAuthenticatedUser()\n if user == None:\n print \"OTP. Authenticate for step 2. Failed to determine user name\"\n return False\n\n session_id_validation = self.validateSessionId(identity)\n if not session_id_validation:\n return False\n\n # Restore state from session\n otp_auth_method = identity.getWorkingParameter(\"otp_auth_method\")\n if otp_auth_method != 'enroll':\n return False\n\n otp_auth_result = self.processOtpAuthentication(requestParameters, user.getUserId(), identity, otp_auth_method)\n print \"OTP. Authenticate for step 3. OTP authentication result: '%s'\" % otp_auth_result\n\n return otp_auth_result\n else:\n return False\n\n def prepareForStep(self, configurationAttributes, requestParameters, step):\n identity = CdiUtil.bean(Identity)\n credentials = identity.getCredentials()\n\n self.setRequestScopedParameters(identity)\n\n if step == 1:\n print \"OTP. Prepare for step 1\"\n\n return True\n elif step == 2:\n print \"OTP. Prepare for step 2\"\n\n session_id_validation = self.validateSessionId(identity)\n if not session_id_validation:\n return False\n\n otp_auth_method = identity.getWorkingParameter(\"otp_auth_method\")\n print \"OTP. Prepare for step 2. otp_auth_method: '%s'\" % otp_auth_method\n\n if otp_auth_method == 'enroll':\n authenticationService = CdiUtil.bean(AuthenticationService)\n user = authenticationService.getAuthenticatedUser()\n if user == None:\n print \"OTP. Prepare for step 2. Failed to load user enty\"\n return False\n\n if self.otpType == \"hotp\":\n otp_secret_key = self.generateSecretHotpKey()\n otp_enrollment_request = self.generateHotpSecretKeyUri(otp_secret_key, self.otpIssuer, user.getAttribute(\"displayName\"))\n elif self.otpType == \"totp\":\n otp_secret_key = self.generateSecretTotpKey()\n otp_enrollment_request = self.generateTotpSecretKeyUri(otp_secret_key, self.otpIssuer, user.getAttribute(\"displayName\"))\n else:\n print \"OTP. Prepare for step 2. Unknown OTP type: '%s'\" % self.otpType\n return False\n\n print \"OTP. Prepare for step 2. Prepared enrollment request for user: '%s'\" % user.getUserId()\n identity.setWorkingParameter(\"otp_secret_key\", self.toBase64Url(otp_secret_key))\n identity.setWorkingParameter(\"otp_enrollment_request\", otp_enrollment_request)\n\n return True\n elif step == 3:\n print \"OTP. Prepare for step 3\"\n\n session_id_validation = self.validateSessionId(identity)\n if not session_id_validation:\n return False\n\n otp_auth_method = identity.getWorkingParameter(\"otp_auth_method\")\n print \"OTP. Prepare for step 3. otp_auth_method: '%s'\" % otp_auth_method\n\n if otp_auth_method == 'enroll':\n return True\n\n return False\n\n def getExtraParametersForStep(self, configurationAttributes, step):\n return Arrays.asList(\"otp_auth_method\", \"otp_count_login_steps\", \"otp_secret_key\", \"otp_enrollment_request\",\"retry_current_step\")\n\n def getCountAuthenticationSteps(self, configurationAttributes):\n identity = CdiUtil.bean(Identity)\n\n if identity.isSetWorkingParameter(\"otp_count_login_steps\"):\n return StringHelper.toInteger(\"%s\" % identity.getWorkingParameter(\"otp_count_login_steps\"))\n else:\n return 2\n\n def getPageForStep(self, configurationAttributes, step):\n if step == 2:\n identity = CdiUtil.bean(Identity)\n\n otp_auth_method = identity.getWorkingParameter(\"otp_auth_method\")\n print \"OTP. Gep page for step 2. otp_auth_method: '%s'\" % otp_auth_method\n\n if otp_auth_method == 'enroll':\n return \"/auth/otp/enroll.xhtml\"\n else:\n return \"/auth/otp/otplogin.xhtml\"\n elif step == 3:\n return \"/auth/otp/otplogin.xhtml\"\n\n return \"\"\n\n\n def getLogoutExternalUrl(self, configurationAttributes, requestParameters):\n print \"Get external logout URL call\"\n return None\n\n def logout(self, configurationAttributes, requestParameters):\n return True\n\n def setRequestScopedParameters(self, identity):\n if self.registrationUri != None:\n identity.setWorkingParameter(\"external_registration_uri\", self.registrationUri)\n\n if self.customLabel != None:\n identity.setWorkingParameter(\"qr_label\", self.customLabel)\n\n identity.setWorkingParameter(\"qr_options\", self.customQrOptions)\n\n def loadOtpConfiguration(self, configurationAttributes):\n print \"OTP. Load OTP configuration\"\n if not configurationAttributes.containsKey(\"otp_conf_file\"):\n return False\n\n otp_conf_file = configurationAttributes.get(\"otp_conf_file\").getValue2()\n\n # Load configuration from file\n f = open(otp_conf_file, 'r')\n try:\n otpConfiguration = json.loads(f.read())\n except:\n print \"OTP. Load OTP configuration. Failed to load configuration from file:\", otp_conf_file\n return False\n finally:\n f.close()\n\n # Check configuration file settings\n try:\n self.hotpConfiguration = otpConfiguration[\"hotp\"]\n self.totpConfiguration = otpConfiguration[\"totp\"]\n \n hmacShaAlgorithm = self.totpConfiguration[\"hmacShaAlgorithm\"]\n hmacShaAlgorithmType = None\n\n if StringHelper.equalsIgnoreCase(hmacShaAlgorithm, \"sha1\"):\n hmacShaAlgorithmType = HmacShaAlgorithm.HMAC_SHA_1\n elif StringHelper.equalsIgnoreCase(hmacShaAlgorithm, \"sha256\"):\n hmacShaAlgorithmType = HmacShaAlgorithm.HMAC_SHA_256\n elif StringHelper.equalsIgnoreCase(hmacShaAlgorithm, \"sha512\"):\n hmacShaAlgorithmType = HmacShaAlgorithm.HMAC_SHA_512\n else:\n print \"OTP. Load OTP configuration. Invalid TOTP HMAC SHA algorithm: '%s'\" % hmacShaAlgorithm\n \n self.totpConfiguration[\"hmacShaAlgorithmType\"] = hmacShaAlgorithmType\n except:\n print \"OTP. Load OTP configuration. Invalid configuration file '%s' format. Exception: '%s'\" % (otp_conf_file, sys.exc_info()[1])\n return False\n \n\n return True\n\n def processBasicAuthentication(self, credentials):\n userService = CdiUtil.bean(UserService)\n authenticationService = CdiUtil.bean(AuthenticationService)\n\n user_name = credentials.getUsername()\n user_password = credentials.getPassword()\n\n logged_in = False\n if StringHelper.isNotEmptyString(user_name) and StringHelper.isNotEmptyString(user_password):\n logged_in = authenticationService.authenticate(user_name, user_password)\n\n if not logged_in:\n return None\n\n find_user_by_uid = authenticationService.getAuthenticatedUser()\n if find_user_by_uid == None:\n print \"OTP. Process basic authentication. Failed to find user '%s'\" % user_name\n return None\n \n return find_user_by_uid\n\n def findEnrollments(self, user_name, skipPrefix = True):\n result = []\n\n userService = CdiUtil.bean(UserService)\n user = userService.getUser(user_name, \"oxExternalUid\")\n if user == None:\n print \"OTP. Find enrollments. Failed to find user\"\n return result\n \n user_custom_ext_attribute = userService.getCustomAttribute(user, \"oxExternalUid\")\n if user_custom_ext_attribute == None:\n return result\n\n otp_prefix = \"%s:\" % self.otpType\n \n otp_prefix_length = len(otp_prefix) \n for user_external_uid in user_custom_ext_attribute.getValues():\n index = user_external_uid.find(otp_prefix)\n if index != -1:\n if skipPrefix:\n enrollment_uid = user_external_uid[otp_prefix_length:]\n else:\n enrollment_uid = user_external_uid\n\n result.append(enrollment_uid)\n \n return result\n\n def validateSessionId(self, identity):\n session = CdiUtil.bean(SessionIdService).getSessionId()\n if session == None:\n print \"OTP. Validate session id. Failed to determine session_id\"\n return False\n\n otp_auth_method = identity.getWorkingParameter(\"otp_auth_method\")\n if not otp_auth_method in ['enroll', 'authenticate']:\n print \"OTP. Validate session id. Failed to authenticate user. otp_auth_method: '%s'\" % otp_auth_method\n return False\n\n return True\n\n def processOtpAuthentication(self, requestParameters, user_name, identity, otp_auth_method):\n facesMessages = CdiUtil.bean(FacesMessages)\n facesMessages.setKeepMessages()\n\n userService = CdiUtil.bean(UserService)\n\n otpCode = ServerUtil.getFirstValue(requestParameters, \"loginForm:otpCode\")\n if StringHelper.isEmpty(otpCode):\n facesMessages.add(FacesMessage.SEVERITY_ERROR, \"Failed to authenticate. OTP code is empty\")\n print \"OTP. Process OTP authentication. otpCode is empty\"\n\n return False\n \n if otp_auth_method == \"enroll\":\n # Get key from session\n otp_secret_key_encoded = identity.getWorkingParameter(\"otp_secret_key\")\n if otp_secret_key_encoded == None:\n print \"OTP. Process OTP authentication. OTP secret key is invalid\"\n return False\n \n otp_secret_key = self.fromBase64Url(otp_secret_key_encoded)\n\n if self.otpType == \"hotp\":\n validation_result = self.validateHotpKey(otp_secret_key, 1, otpCode)\n \n if (validation_result != None) and validation_result[\"result\"]:\n print \"OTP. Process HOTP authentication during enrollment. otpCode is valid\"\n # Store HOTP Secret Key and moving factor in user entry\n otp_user_external_uid = \"hotp:%s;%s\" % ( otp_secret_key_encoded, validation_result[\"movingFactor\"] )\n\n # Add otp_user_external_uid to user's external GUID list\n find_user_by_external_uid = userService.addUserAttribute(user_name, \"oxExternalUid\", otp_user_external_uid)\n if find_user_by_external_uid != None:\n return True\n\n print \"OTP. Process HOTP authentication during enrollment. Failed to update user entry\"\n elif self.otpType == \"totp\":\n validation_result = self.validateTotpKey(otp_secret_key, otpCode,user_name)\n if (validation_result != None) and validation_result[\"result\"]:\n print \"OTP. Process TOTP authentication during enrollment. otpCode is valid\"\n # Store TOTP Secret Key and moving factor in user entry\n otp_user_external_uid = \"totp:%s\" % otp_secret_key_encoded\n\n # Add otp_user_external_uid to user's external GUID list\n find_user_by_external_uid = userService.addUserAttribute(user_name, \"oxExternalUid\", otp_user_external_uid)\n if find_user_by_external_uid != None:\n return True\n\n print \"OTP. Process TOTP authentication during enrollment. Failed to update user entry\"\n elif otp_auth_method == \"authenticate\":\n user_enrollments = self.findEnrollments(user_name)\n\n if len(user_enrollments) == 0:\n print \"OTP. Process OTP authentication. There is no OTP enrollment for user '%s'\" % user_name\n facesMessages.add(FacesMessage.SEVERITY_ERROR, \"There is no valid OTP user enrollments\")\n return False\n\n if self.otpType == \"hotp\":\n for user_enrollment in user_enrollments:\n user_enrollment_data = user_enrollment.split(\";\")\n otp_secret_key_encoded = user_enrollment_data[0]\n\n # Get current moving factor from user entry\n moving_factor = StringHelper.toInteger(user_enrollment_data[1])\n otp_secret_key = self.fromBase64Url(otp_secret_key_encoded)\n\n # Validate TOTP\n validation_result = self.validateHotpKey(otp_secret_key, moving_factor, otpCode)\n if (validation_result != None) and validation_result[\"result\"]:\n print \"OTP. Process HOTP authentication during authentication. otpCode is valid\"\n otp_user_external_uid = \"hotp:%s;%s\" % ( otp_secret_key_encoded, moving_factor )\n new_otp_user_external_uid = \"hotp:%s;%s\" % ( otp_secret_key_encoded, validation_result[\"movingFactor\"] )\n \n # Update moving factor in user entry\n find_user_by_external_uid = userService.replaceUserAttribute(user_name, \"oxExternalUid\", otp_user_external_uid, new_otp_user_external_uid)\n if find_user_by_external_uid != None:\n return True\n \n print \"OTP. Process HOTP authentication during authentication. Failed to update user entry\"\n elif self.otpType == \"totp\":\n for user_enrollment in user_enrollments:\n otp_secret_key = self.fromBase64Url(user_enrollment)\n\n # Validate TOTP\n validation_result = self.validateTotpKey(otp_secret_key, otpCode, user_name)\n if (validation_result != None) and validation_result[\"result\"]:\n print \"OTP. Process TOTP authentication during authentication. otpCode is valid\"\n return True\n\n facesMessages.add(FacesMessage.SEVERITY_ERROR, \"Failed to authenticate. OTP code is invalid\")\n print \"OTP. Process OTP authentication. OTP code is invalid\"\n\n return False\n\n # Shared HOTP/TOTP methods\n def generateSecretKey(self, keyLength):\n bytes = jarray.zeros(keyLength, \"b\")\n secureRandom = SecureRandom()\n secureRandom.nextBytes(bytes)\n \n return bytes\n \n # HOTP methods\n def generateSecretHotpKey(self):\n keyLength = self.hotpConfiguration[\"keyLength\"]\n \n return self.generateSecretKey(keyLength)\n\n def generateHotpKey(self, secretKey, movingFactor):\n digits = self.hotpConfiguration[\"digits\"]\n\n hotp = HOTP.key(secretKey).digits(digits).movingFactor(movingFactor).build()\n \n return hotp.value()\n\n def validateHotpKey(self, secretKey, movingFactor, totpKey):\n lookAheadWindow = self.hotpConfiguration[\"lookAheadWindow\"]\n digits = self.hotpConfiguration[\"digits\"]\n\n htopValidationResult = HOTPValidator.lookAheadWindow(lookAheadWindow).validate(secretKey, movingFactor, digits, totpKey)\n if htopValidationResult.isValid():\n return { \"result\": True, \"movingFactor\": htopValidationResult.getNewMovingFactor() }\n\n return { \"result\": False, \"movingFactor\": None }\n\n def generateHotpSecretKeyUri(self, secretKey, issuer, userDisplayName):\n digits = self.hotpConfiguration[\"digits\"]\n\n secretKeyBase32 = self.toBase32(secretKey)\n otpKey = OTPKey(secretKeyBase32, OTPType.HOTP)\n label = issuer + \" %s\" % userDisplayName\n\n otpAuthURI = OTPAuthURIBuilder.fromKey(otpKey).label(label).issuer(issuer).digits(digits).build()\n\n return otpAuthURI.toUriString()\n\n # TOTP methods\n def generateSecretTotpKey(self):\n keyLength = self.totpConfiguration[\"keyLength\"]\n \n return self.generateSecretKey(keyLength)\n\n def generateTotpKey(self, secretKey):\n digits = self.totpConfiguration[\"digits\"]\n timeStep = self.totpConfiguration[\"timeStep\"]\n hmacShaAlgorithmType = self.totpConfiguration[\"hmacShaAlgorithmType\"]\n\n totp = TOTP.key(secretKey).digits(digits).timeStep(TimeUnit.SECONDS.toMillis(timeStep)).hmacSha(hmacShaAlgorithmType).build()\n \n return totp.value()\n\n def validateTotpKey(self, secretKey, totpKey, user_name):\n localTotpKey = self.generateTotpKey(secretKey)\n cachedOTP = self.getCachedOTP(user_name)\n\n if StringHelper.equals(localTotpKey, totpKey) and not StringHelper.equals(localTotpKey, cachedOTP):\n userService = CdiUtil.bean(UserService)\n if cachedOTP is None:\n userService.addUserAttribute(user_name, \"oxOTPCache\",localTotpKey)\n else :\n userService.replaceUserAttribute(user_name, \"oxOTPCache\", cachedOTP, localTotpKey)\n print \"OTP. Caching OTP: '%s'\" % localTotpKey\n return { \"result\": True }\n return { \"result\": False }\n\t\n def getCachedOTP(self, user_name):\n userService = CdiUtil.bean(UserService)\n user = userService.getUser(user_name, \"oxOTPCache\")\n if user is None:\n print \"OTP. Get Cached OTP. Failed to find OTP\"\n return None\n customAttribute = userService.getCustomAttribute(user, \"oxOTPCache\")\n \n if customAttribute is None:\n print \"OTP. Custom attribute is null\"\n return None\n user_cached_OTP = customAttribute.getValue()\n if user_cached_OTP is None:\n print \"OTP. no OTP is present in LDAP\"\n return None\n \n print \"OTP.Cached OTP: '%s'\" % user_cached_OTP\n return user_cached_OTP\n \n def generateTotpSecretKeyUri(self, secretKey, issuer, userDisplayName):\n digits = self.totpConfiguration[\"digits\"]\n timeStep = self.totpConfiguration[\"timeStep\"]\n\n secretKeyBase32 = self.toBase32(secretKey)\n otpKey = OTPKey(secretKeyBase32, OTPType.TOTP)\n label = issuer + \" %s\" % userDisplayName\n\n otpAuthURI = OTPAuthURIBuilder.fromKey(otpKey).label(label).issuer(issuer).digits(digits).timeStep(TimeUnit.SECONDS.toMillis(timeStep)).build()\n\n return otpAuthURI.toUriString()\n\n # Utility methods\n def toBase32(self, bytes):\n return BaseEncoding.base32().omitPadding().encode(bytes)\n\n def toBase64Url(self, bytes):\n return BaseEncoding.base64Url().encode(bytes)\n\n def fromBase64Url(self, chars):\n return BaseEncoding.base64Url().decode(chars)\n\n\n", @@ -455,7 +455,7 @@ "level": 40, "programmingLanguage": "PYTHON", "description": "Passport authentication module", - "locationType": "LDAP", + "locationType": "db", "dn": "inum=2FDB-CF02,ou=scripts,o=gluu", "inum": "2FDB-CF02", "script": "# jans-auth is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text.\n# Copyright (c) 2019, Gluu\n#\n# Author: Jose Gonzalez\n# Author: Yuriy Movchan\n#\nfrom org.gluu.jsf2.service import FacesService\nfrom org.gluu.jsf2.message import FacesMessages\n\nfrom org.gluu.oxauth.model.common import User, WebKeyStorage\nfrom org.gluu.oxauth.model.configuration import AppConfiguration\nfrom org.gluu.oxauth.model.crypto import CryptoProviderFactory\nfrom org.gluu.oxauth.model.jwt import Jwt, JwtClaimName\nfrom org.gluu.oxauth.model.util import Base64Util\nfrom org.gluu.oxauth.service import AppInitializer, AuthenticationService\nfrom org.gluu.oxauth.service.common import UserService, EncryptionService\nfrom org.gluu.oxauth.service.net import HttpService\nfrom org.gluu.oxauth.security import Identity\nfrom org.gluu.oxauth.util import ServerUtil\nfrom org.gluu.config.oxtrust import LdapOxPassportConfiguration\nfrom org.gluu.model.custom.script.type.auth import PersonAuthenticationType\nfrom org.gluu.persist import PersistenceEntryManager\nfrom org.gluu.service.cdi.util import CdiUtil\nfrom org.gluu.util import StringHelper\nfrom java.util import ArrayList, Arrays, Collections\n\nfrom javax.faces.application import FacesMessage\nfrom javax.faces.context import FacesContext\n\nimport json\nimport sys\nimport datetime\n\nclass PersonAuthentication(PersonAuthenticationType):\n def __init__(self, currentTimeMillis):\n self.currentTimeMillis = currentTimeMillis\n\n def init(self, customScript, configurationAttributes):\n print \"Passport. init called\"\n\n self.extensionModule = self.loadExternalModule(configurationAttributes.get(\"extension_module\"))\n extensionResult = self.extensionInit(configurationAttributes)\n if extensionResult != None:\n return extensionResult\n\n print \"Passport. init. Behaviour is social\"\n success = self.processKeyStoreProperties(configurationAttributes)\n\n if success:\n self.providerKey = \"provider\"\n self.customAuthzParameter = self.getCustomAuthzParameter(configurationAttributes.get(\"authz_req_param_provider\"))\n self.passportDN = self.getPassportConfigDN()\n print \"Passport. init. Initialization success\"\n else:\n print \"Passport. init. Initialization failed\"\n return success\n\n\n def destroy(self, configurationAttributes):\n print \"Passport. destroy called\"\n return True\n\n\n def getApiVersion(self):\n return 11\n \n def getAuthenticationMethodClaims(self, requestParameters):\n return None\n \n def isValidAuthenticationMethod(self, usageType, configurationAttributes):\n return True\n\n\n def getAlternativeAuthenticationMethod(self, usageType, configurationAttributes):\n return None\n\n\n def authenticate(self, configurationAttributes, requestParameters, step):\n\n extensionResult = self.extensionAuthenticate(configurationAttributes, requestParameters, step)\n if extensionResult != None:\n return extensionResult\n\n print \"Passport. authenticate for step %s called\" % str(step)\n identity = CdiUtil.bean(Identity)\n\n if step == 1:\n # Get JWT token\n jwt_param = ServerUtil.getFirstValue(requestParameters, \"user\")\n\n if jwt_param != None:\n print \"Passport. authenticate for step 1. JWT user profile token found\"\n\n # Parse JWT and validate\n jwt = Jwt.parse(jwt_param)\n if not self.validSignature(jwt):\n return False\n\n if self.jwtHasExpired(jwt):\n return False\n\n (user_profile, jsonp) = self.getUserProfile(jwt)\n if user_profile == None:\n return False\n\n return self.attemptAuthentication(identity, user_profile, jsonp)\n\n #See passportlogin.xhtml\n provider = ServerUtil.getFirstValue(requestParameters, \"loginForm:provider\")\n if StringHelper.isEmpty(provider):\n\n #it's username + passw auth\n print \"Passport. authenticate for step 1. Basic authentication detected\"\n logged_in = False\n\n credentials = identity.getCredentials()\n user_name = credentials.getUsername()\n user_password = credentials.getPassword()\n\n if StringHelper.isNotEmptyString(user_name) and StringHelper.isNotEmptyString(user_password):\n authenticationService = CdiUtil.bean(AuthenticationService)\n logged_in = authenticationService.authenticate(user_name, user_password)\n\n print \"Passport. authenticate for step 1. Basic authentication returned: %s\" % logged_in\n return logged_in\n\n elif provider in self.registeredProviders:\n #it's a recognized external IDP\n identity.setWorkingParameter(\"selectedProvider\", provider)\n print \"Passport. authenticate for step 1. Retrying step 1\"\n #see prepareForStep (step = 1)\n return True\n\n if step == 2:\n mail = ServerUtil.getFirstValue(requestParameters, \"loginForm:email\")\n jsonp = identity.getWorkingParameter(\"passport_user_profile\")\n\n if mail == None:\n self.setMessageError(FacesMessage.SEVERITY_ERROR, \"Email was missing in user profile\")\n elif jsonp != None:\n # Completion of profile takes place\n user_profile = json.loads(jsonp)\n user_profile[\"mail\"] = [ mail ]\n\n return self.attemptAuthentication(identity, user_profile, jsonp)\n\n print \"Passport. authenticate for step 2. Failed: expected mail value in HTTP request and json profile in session\"\n return False\n\n\n def prepareForStep(self, configurationAttributes, requestParameters, step):\n\n extensionResult = self.extensionPrepareForStep(configurationAttributes, requestParameters, step)\n if extensionResult != None:\n return extensionResult\n\n print \"Passport. prepareForStep called %s\" % str(step)\n identity = CdiUtil.bean(Identity)\n\n if step == 1:\n #re-read the strategies config (for instance to know which strategies have enabled the email account linking)\n self.parseProviderConfigs()\n identity.setWorkingParameter(\"externalProviders\", json.dumps(self.registeredProviders))\n\n providerParam = self.customAuthzParameter\n url = None\n\n sessionAttributes = identity.getSessionId().getSessionAttributes()\n self.skipProfileUpdate = StringHelper.equalsIgnoreCase(sessionAttributes.get(\"skipPassportProfileUpdate\"), \"true\")\n\n #this param could have been set previously in authenticate step if current step is being retried\n provider = identity.getWorkingParameter(\"selectedProvider\")\n if provider != None:\n url = self.getPassportRedirectUrl(provider)\n identity.setWorkingParameter(\"selectedProvider\", None)\n\n elif providerParam != None:\n paramValue = sessionAttributes.get(providerParam)\n\n if paramValue != None:\n print \"Passport. prepareForStep. Found value in custom param of authorization request: %s\" % paramValue\n provider = self.getProviderFromJson(paramValue)\n\n if provider == None:\n print \"Passport. prepareForStep. A provider value could not be extracted from custom authorization request parameter\"\n elif not provider in self.registeredProviders:\n print \"Passport. prepareForStep. Provider '%s' not part of known configured IDPs/OPs\" % provider\n else:\n url = self.getPassportRedirectUrl(provider)\n\n if url == None:\n print \"Passport. prepareForStep. A page to manually select an identity provider will be shown\"\n else:\n facesService = CdiUtil.bean(FacesService)\n facesService.redirectToExternalURL(url)\n\n return True\n\n\n def getExtraParametersForStep(self, configurationAttributes, step):\n print \"Passport. getExtraParametersForStep called\"\n if step == 1:\n return Arrays.asList(\"selectedProvider\", \"externalProviders\")\n elif step == 2:\n return Arrays.asList(\"passport_user_profile\")\n return None\n\n\n def getCountAuthenticationSteps(self, configurationAttributes):\n print \"Passport. getCountAuthenticationSteps called\"\n identity = CdiUtil.bean(Identity)\n if identity.getWorkingParameter(\"passport_user_profile\") != None:\n return 2\n return 1\n\n\n def getPageForStep(self, configurationAttributes, step):\n print \"Passport. getPageForStep called\"\n\n extensionResult = self.extensionGetPageForStep(configurationAttributes, step)\n if extensionResult != None:\n return extensionResult\n\n if step == 1:\n return \"/auth/passport/passportlogin.xhtml\"\n return \"/auth/passport/passportpostlogin.xhtml\"\n\n\n def getNextStep(self, configurationAttributes, requestParameters, step):\n\n if step == 1:\n identity = CdiUtil.bean(Identity)\n provider = identity.getWorkingParameter(\"selectedProvider\")\n if provider != None:\n return 1\n\n return -1\n\n def getLogoutExternalUrl(self, configurationAttributes, requestParameters):\n print \"Get external logout URL call\"\n return None\n\n def logout(self, configurationAttributes, requestParameters):\n return True\n\n# Extension module related functions\n\n def extensionInit(self, configurationAttributes):\n\n if self.extensionModule == None:\n return None\n return self.extensionModule.init(configurationAttributes)\n\n\n def extensionAuthenticate(self, configurationAttributes, requestParameters, step):\n\n if self.extensionModule == None:\n return None\n return self.extensionModule.authenticate(configurationAttributes, requestParameters, step)\n\n\n def extensionPrepareForStep(self, configurationAttributes, requestParameters, step):\n\n if self.extensionModule == None:\n return None\n return self.extensionModule.prepareForStep(configurationAttributes, requestParameters, step)\n\n\n def extensionGetPageForStep(self, configurationAttributes, step):\n\n if self.extensionModule == None:\n return None\n return self.extensionModule.getPageForStep(configurationAttributes, step)\n\n# Initalization routines\n\n def loadExternalModule(self, simpleCustProperty):\n\n if simpleCustProperty != None:\n print \"Passport. loadExternalModule. Loading passport extension module...\"\n moduleName = simpleCustProperty.getValue2()\n try:\n module = __import__(moduleName)\n return module\n except:\n print \"Passport. loadExternalModule. Failed to load module %s\" % moduleName\n print \"Exception: \", sys.exc_info()[1]\n print \"Passport. loadExternalModule. Flow will be driven entirely by routines of main passport script\"\n return None\n\n\n def processKeyStoreProperties(self, attrs):\n file = attrs.get(\"key_store_file\")\n password = attrs.get(\"key_store_password\")\n\n if file != None and password != None:\n file = file.getValue2()\n password = password.getValue2()\n\n if StringHelper.isNotEmpty(file) and StringHelper.isNotEmpty(password):\n self.keyStoreFile = file\n self.keyStorePassword = password\n return True\n\n print \"Passport. readKeyStoreProperties. Properties key_store_file or key_store_password not found or empty\"\n return False\n\n\n def getCustomAuthzParameter(self, simpleCustProperty):\n\n customAuthzParameter = None\n if simpleCustProperty != None:\n prop = simpleCustProperty.getValue2()\n if StringHelper.isNotEmpty(prop):\n customAuthzParameter = prop\n\n if customAuthzParameter == None:\n print \"Passport. getCustomAuthzParameter. No custom param for OIDC authz request in script properties\"\n print \"Passport. getCustomAuthzParameter. Passport flow cannot be initiated by doing an OpenID connect authorization request\"\n else:\n print \"Passport. getCustomAuthzParameter. Custom param for OIDC authz request in script properties: %s\" % customAuthzParameter\n\n return customAuthzParameter\n\n# Configuration parsing\n\n def getPassportConfigDN(self):\n\n f = open('/etc/gluu/conf/gluu.properties', 'r')\n for line in f:\n prop = line.split(\"=\")\n if prop[0] == \"oxpassport_ConfigurationEntryDN\":\n prop.pop(0)\n break\n\n f.close()\n return \"=\".join(prop).strip()\n\n\n def parseAllProviders(self):\n\n registeredProviders = {}\n print \"Passport. parseAllProviders. Adding providers\"\n entryManager = CdiUtil.bean(PersistenceEntryManager)\n\n config = LdapOxPassportConfiguration()\n config = entryManager.find(config.getClass(), self.passportDN).getPassportConfiguration()\n config = config.getProviders() if config != None else config\n\n if config != None and len(config) > 0:\n for prvdetails in config:\n if prvdetails.isEnabled():\n registeredProviders[prvdetails.getId()] = {\n \"emailLinkingSafe\": prvdetails.isEmailLinkingSafe(),\n \"requestForEmail\" : prvdetails.isRequestForEmail(),\n \"logo_img\": prvdetails.getLogoImg(),\n \"displayName\": prvdetails.getDisplayName(),\n \"type\": prvdetails.getType()\n }\n\n return registeredProviders\n\n\n def parseProviderConfigs(self):\n\n registeredProviders = {}\n try:\n registeredProviders = self.parseAllProviders()\n toRemove = []\n\n for provider in registeredProviders:\n if registeredProviders[provider][\"type\"] == \"saml\":\n toRemove.append(provider)\n else:\n registeredProviders[provider][\"saml\"] = False\n\n for provider in toRemove:\n registeredProviders.pop(provider)\n\n if len(registeredProviders.keys()) > 0:\n print \"Passport. parseProviderConfigs. Configured providers:\", registeredProviders\n else:\n print \"Passport. parseProviderConfigs. No providers registered yet\"\n except:\n print \"Passport. parseProviderConfigs. An error occurred while building the list of supported authentication providers\", sys.exc_info()[1]\n\n self.registeredProviders = registeredProviders\n\n# Auxiliary routines\n\n def getProviderFromJson(self, providerJson):\n\n provider = None\n try:\n obj = json.loads(Base64Util.base64urldecodeToString(providerJson))\n provider = obj[self.providerKey]\n except:\n print \"Passport. getProviderFromJson. Could not parse provided Json string. Returning None\"\n\n return provider\n\n\n def getPassportRedirectUrl(self, provider):\n\n # provider is assumed to exist in self.registeredProviders\n url = None\n try:\n facesContext = CdiUtil.bean(FacesContext)\n tokenEndpoint = \"https://%s/passport/token\" % facesContext.getExternalContext().getRequest().getServerName()\n\n httpService = CdiUtil.bean(HttpService)\n httpclient = httpService.getHttpsClient()\n\n print \"Passport. getPassportRedirectUrl. Obtaining token from passport at %s\" % tokenEndpoint\n resultResponse = httpService.executeGet(httpclient, tokenEndpoint, Collections.singletonMap(\"Accept\", \"text/json\"))\n httpResponse = resultResponse.getHttpResponse()\n bytes = httpService.getResponseContent(httpResponse)\n\n response = httpService.convertEntityToString(bytes)\n print \"Passport. getPassportRedirectUrl. Response was %s\" % httpResponse.getStatusLine().getStatusCode()\n\n tokenObj = json.loads(response)\n url = \"/passport/auth/%s/%s\" % (provider, tokenObj[\"token_\"])\n except:\n print \"Passport. getPassportRedirectUrl. Error building redirect URL: \", sys.exc_info()[1]\n\n return url\n\n\n def validSignature(self, jwt):\n\n print \"Passport. validSignature. Checking JWT token signature\"\n valid = False\n\n try:\n appConfiguration = AppConfiguration()\n appConfiguration.setWebKeysStorage(WebKeyStorage.KEYSTORE)\n appConfiguration.setKeyStoreFile(self.keyStoreFile)\n appConfiguration.setKeyStoreSecret(self.keyStorePassword)\n appConfiguration.setKeyRegenerationEnabled(False)\n\n cryptoProvider = CryptoProviderFactory.getCryptoProvider(appConfiguration)\n valid = cryptoProvider.verifySignature(jwt.getSigningInput(), jwt.getEncodedSignature(), jwt.getHeader().getKeyId(),\n None, None, jwt.getHeader().getSignatureAlgorithm())\n except:\n print \"Exception: \", sys.exc_info()[1]\n\n print \"Passport. validSignature. Validation result was %s\" % valid\n return valid\n\n\n def jwtHasExpired(self, jwt):\n # Check if jwt has expired\n jwt_claims = jwt.getClaims()\n try:\n exp_date = jwt_claims.getClaimAsDate(JwtClaimName.EXPIRATION_TIME)\n hasExpired = exp_date < datetime.datetime.now()\n except:\n print \"Exception: The JWT does not have '%s' attribute\" % JwtClaimName.EXPIRATION_TIME\n return False\n\n return hasExpired\n\n\n def getUserProfile(self, jwt):\n jwt_claims = jwt.getClaims()\n user_profile_json = None\n\n try:\n user_profile_json = CdiUtil.bean(EncryptionService).decrypt(jwt_claims.getClaimAsString(\"data\"))\n user_profile = json.loads(user_profile_json)\n except:\n print \"Passport. getUserProfile. Problem obtaining user profile json representation\"\n\n return (user_profile, user_profile_json)\n\n\n def attemptAuthentication(self, identity, user_profile, user_profile_json):\n\n uidKey = \"uid\"\n if not self.checkRequiredAttributes(user_profile, [uidKey, self.providerKey]):\n return False\n\n provider = user_profile[self.providerKey]\n if not provider in self.registeredProviders:\n print \"Passport. attemptAuthentication. Identity Provider %s not recognized\" % provider\n return False\n\n uid = user_profile[uidKey][0]\n externalUid = \"passport-%s:%s\" % (provider, uid)\n\n userService = CdiUtil.bean(UserService)\n userByUid = userService.getUserByAttribute(\"oxExternalUid\", externalUid)\n\n email = None\n if \"mail\" in user_profile:\n email = user_profile[\"mail\"]\n if len(email) == 0:\n email = None\n else:\n email = email[0]\n user_profile[\"mail\"] = [ email ]\n\n if email == None and self.registeredProviders[provider][\"requestForEmail\"]:\n print \"Passport. attemptAuthentication. Email was not received\"\n\n if userByUid != None:\n # This avoids asking for the email over every login attempt\n email = userByUid.getAttribute(\"mail\")\n if email != None:\n print \"Passport. attemptAuthentication. Filling missing email value with %s\" % email\n user_profile[\"mail\"] = [ email ]\n\n if email == None:\n # Store user profile in session and abort this routine\n identity.setWorkingParameter(\"passport_user_profile\", user_profile_json)\n return True\n\n userByMail = None if email == None else userService.getUserByAttribute(\"mail\", email)\n\n # Determine if we should add entry, update existing, or deny access\n doUpdate = False\n doAdd = False\n if userByUid != None:\n print \"User with externalUid '%s' already exists\" % externalUid\n if userByMail == None:\n doUpdate = True\n else:\n if userByMail.getUserId() == userByUid.getUserId():\n doUpdate = True\n else:\n print \"Users with externalUid '%s' and mail '%s' are different. Access will be denied. Impersonation attempt?\" % (externalUid, email)\n self.setMessageError(FacesMessage.SEVERITY_ERROR, \"Email value corresponds to an already existing provisioned account\")\n else:\n if userByMail == None:\n doAdd = True\n elif self.registeredProviders[provider][\"emailLinkingSafe\"]:\n\n tmpList = userByMail.getAttributeValues(\"oxExternalUid\")\n tmpList = ArrayList() if tmpList == None else ArrayList(tmpList)\n tmpList.add(externalUid)\n userByMail.setAttribute(\"oxExternalUid\", tmpList)\n\n userByUid = userByMail\n print \"External user supplying mail %s will be linked to existing account '%s'\" % (email, userByMail.getUserId())\n doUpdate = True\n else:\n print \"An attempt to supply an email of an existing user was made. Turn on 'emailLinkingSafe' if you want to enable linking\"\n self.setMessageError(FacesMessage.SEVERITY_ERROR, \"Email value corresponds to an already existing account. If you already have a username and password use those instead of an external authentication site to get access.\")\n\n username = None\n try:\n if doUpdate:\n username = userByUid.getUserId()\n print \"Passport. attemptAuthentication. Updating user %s\" % username\n self.updateUser(userByUid, user_profile, userService)\n elif doAdd:\n print \"Passport. attemptAuthentication. Creating user %s\" % externalUid\n newUser = self.addUser(externalUid, user_profile, userService)\n username = newUser.getUserId()\n except:\n print \"Exception: \", sys.exc_info()[1]\n print \"Passport. attemptAuthentication. Authentication failed\"\n return False\n\n if username == None:\n print \"Passport. attemptAuthentication. Authentication attempt was rejected\"\n return False\n else:\n logged_in = CdiUtil.bean(AuthenticationService).authenticate(username)\n print \"Passport. attemptAuthentication. Authentication for %s returned %s\" % (username, logged_in)\n return logged_in\n\n\n def setMessageError(self, severity, msg):\n facesMessages = CdiUtil.bean(FacesMessages)\n facesMessages.setKeepMessages()\n facesMessages.clear()\n facesMessages.add(severity, msg)\n\n\n def checkRequiredAttributes(self, profile, attrs):\n\n for attr in attrs:\n if (not attr in profile) or len(profile[attr]) == 0:\n print \"Passport. checkRequiredAttributes. Attribute '%s' is missing in profile\" % attr\n return False\n return True\n\n\n def addUser(self, externalUid, profile, userService):\n\n newUser = User()\n #Fill user attrs\n newUser.setAttribute(\"oxExternalUid\", externalUid)\n self.fillUser(newUser, profile)\n newUser = userService.addUser(newUser, True)\n return newUser\n\n\n def updateUser(self, foundUser, profile, userService):\n\n # when this is false, there might still some updates taking place (e.g. not related to profile attrs released by external provider)\n if (not self.skipProfileUpdate):\n self.fillUser(foundUser, profile)\n userService.updateUser(foundUser)\n\n\n def fillUser(self, foundUser, profile):\n\n for attr in profile:\n # \"provider\" is disregarded if part of mapping\n if attr != self.providerKey:\n values = profile[attr]\n print \"%s = %s\" % (attr, values)\n foundUser.setAttribute(attr, values)\n\n if attr == \"mail\":\n oxtrustMails = []\n for mail in values:\n oxtrustMails.append('{\"value\":\"%s\",\"primary\":false}' % mail)\n foundUser.setAttribute(\"oxTrustEmail\", oxtrustMails)\n", @@ -493,7 +493,7 @@ "level": 45, "programmingLanguage": "PYTHON", "description": "SMPP SMS authentication module", - "locationType": "LDAP", + "locationType": "db", "dn": "inum=09A0-93D7,ou=scripts,o=gluu", "inum": "09A0-93D7", "script": "# jans-auth is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text.\n# Copyright (c) 2018, Gluu\n# Copyright (c) 2019, Tele2\n\n# Author: Jose Gonzalez\n# Author: Gasmyr Mougang\n# Author: Stefan Andersson\n\nfrom java.util import Arrays, Date\nfrom java.io import IOException\nfrom java.lang import Enum\n\nfrom org.gluu.service.cdi.util import CdiUtil\nfrom org.gluu.oxauth.security import Identity\nfrom org.gluu.model.custom.script.type.auth import PersonAuthenticationType\nfrom org.gluu.oxauth.service import AuthenticationService\nfrom org.gluu.oxauth.service.common import UserService\nfrom org.gluu.oxauth.util import ServerUtil\nfrom org.gluu.util import StringHelper, ArrayHelper\nfrom javax.faces.application import FacesMessage\nfrom org.gluu.jsf2.message import FacesMessages\n\nfrom org.jsmpp import InvalidResponseException, PDUException\nfrom org.jsmpp.bean import Alphabet, BindType, ESMClass, GeneralDataCoding, MessageClass, NumberingPlanIndicator, RegisteredDelivery, SMSCDeliveryReceipt, TypeOfNumber\nfrom org.jsmpp.extra import NegativeResponseException, ResponseTimeoutException\nfrom org.jsmpp.session import BindParameter, SMPPSession\nfrom org.jsmpp.util import AbsoluteTimeFormatter, TimeFormatter\nimport random\n\n\nclass SmppAttributeError(Exception):\n pass\n\n\nclass PersonAuthentication(PersonAuthenticationType):\n def __init__(self, currentTimeMillis):\n self.currentTimeMillis = currentTimeMillis\n self.identity = CdiUtil.bean(Identity)\n\n def get_and_parse_smpp_config(self, config, attribute, _type = None, convert = False, optional = False, default_desc = None):\n try:\n value = config.get(attribute).getValue2()\n except:\n if default_desc:\n default_desc = \" using default '{}'\".format(default_desc)\n else:\n default_desc = \"\"\n\n if optional:\n raise SmppAttributeError(\"SMPP missing optional configuration attribute '{}'{}\".format(attribute, default_desc))\n else:\n raise SmppAttributeError(\"SMPP missing required configuration attribute '{}'\".format(attribute))\n\n if _type and issubclass(_type, Enum):\n try:\n return getattr(_type, value)\n except AttributeError:\n raise SmppAttributeError(\"SMPP could not find attribute '{}' in {}\".format(attribute, _type))\n\n if convert:\n try:\n value = int(value)\n except AttributeError:\n try:\n value = int(value, 16)\n except AttributeError:\n raise SmppAttributeError(\"SMPP could not parse value '{}' of attribute '{}'\".format(value, attribute))\n\n return value\n\n def init(self, customScript, configurationAttributes):\n print(\"SMPP Initialization\")\n\n self.TIME_FORMATTER = AbsoluteTimeFormatter()\n\n self.SMPP_SERVER = None\n self.SMPP_PORT = None\n\n self.SYSTEM_ID = None\n self.PASSWORD = None\n\n # Setup some good defaults for TON, NPI and source (from) address\n # TON (Type of Number), NPI (Number Plan Indicator)\n self.SRC_ADDR_TON = TypeOfNumber.ALPHANUMERIC # Alphanumeric\n self.SRC_ADDR_NPI = NumberingPlanIndicator.ISDN # ISDN (E163/E164)\n self.SRC_ADDR = \"Gluu OTP\"\n\n # Don't touch these unless you know what your doing, we don't handle number reformatting for\n # any other type than international.\n self.DST_ADDR_TON = TypeOfNumber.INTERNATIONAL # International\n self.DST_ADDR_NPI = NumberingPlanIndicator.ISDN # ISDN (E163/E164)\n\n # Priority flag and data_coding bits\n self.PRIORITY_FLAG = 3 # Very Urgent (ANSI-136), Emergency (IS-95)\n self.DATA_CODING_ALPHABET = Alphabet.ALPHA_DEFAULT # SMS default alphabet\n self.DATA_CODING_MESSAGE_CLASS = MessageClass.CLASS1 # EM (Mobile Equipment (mobile memory), normal message\n\n # Required server settings\n try:\n self.SMPP_SERVER = self.get_and_parse_smpp_config(configurationAttributes, \"smpp_server\")\n except SmppAttributeError as e:\n print(e)\n\n try:\n self.SMPP_PORT = self.get_and_parse_smpp_config(configurationAttributes, \"smpp_port\", convert = True)\n except SmppAttributeError as e:\n print(e)\n\n if None in (self.SMPP_SERVER, self.SMPP_PORT):\n print(\"SMPP smpp_server and smpp_port is empty, will not enable SMPP service\")\n return False\n\n # Optional system_id and password for bind auth\n try:\n self.SYSTEM_ID = self.get_and_parse_smpp_config(configurationAttributes, \"system_id\", optional = True)\n except SmppAttributeError as e:\n print(e)\n\n try:\n self.PASSWORD = self.get_and_parse_smpp_config(configurationAttributes, \"password\", optional = True)\n except SmppAttributeError as e:\n print(e)\n\n if None in (self.SYSTEM_ID, self.PASSWORD):\n print(\"SMPP Authentication disabled\")\n\n # From number and to number settings\n try:\n self.SRC_ADDR_TON = self.get_and_parse_smpp_config(\n configurationAttributes,\n \"source_addr_ton\",\n _type = TypeOfNumber,\n optional = True,\n default_desc = self.SRC_ADDR_TON\n )\n except SmppAttributeError as e:\n print(e)\n\n try:\n self.SRC_ADDR_NPI = self.get_and_parse_smpp_config(\n configurationAttributes,\n \"source_addr_npi\",\n _type = NumberingPlanIndicator,\n optional = True,\n default_desc = self.SRC_ADDR_NPI\n )\n except SmppAttributeError as e:\n print(e)\n\n try:\n self.SRC_ADDR = self.get_and_parse_smpp_config(\n configurationAttributes,\n \"source_addr\",\n optional = True,\n default_desc = self.SRC_ADDR\n )\n except SmppAttributeError as e:\n print(e)\n\n try:\n self.DST_ADDR_TON = self.get_and_parse_smpp_config(\n configurationAttributes,\n \"dest_addr_ton\",\n _type = TypeOfNumber,\n optional = True,\n default_desc = self.DST_ADDR_TON\n )\n except SmppAttributeError as e:\n print(e)\n\n try:\n self.DST_ADDR_NPI = self.get_and_parse_smpp_config(\n configurationAttributes,\n \"dest_addr_npi\",\n _type = NumberingPlanIndicator,\n optional = True,\n default_desc = self.DST_ADDR_NPI\n )\n except SmppAttributeError as e:\n print(e)\n\n # Priority flag and data coding, don't touch these unless you know what your doing...\n try:\n self.PRIORITY_FLAG = self.get_and_parse_smpp_config(\n configurationAttributes,\n \"priority_flag\",\n convert = True,\n optional = True,\n default_desc = \"3 (Very Urgent, Emergency)\"\n )\n except SmppAttributeError as e:\n print(e)\n\n try:\n self.DATA_CODING_ALPHABET = self.get_and_parse_smpp_config(\n configurationAttributes,\n \"data_coding_alphabet\",\n _type = Alphabet,\n optional = True,\n default_desc = self.DATA_CODING_ALPHABET\n )\n except SmppAttributeError as e:\n print(e)\n\n try:\n self.DATA_CODING_MESSAGE_CLASS = self.get_and_parse_smpp_config(\n configurationAttributes,\n \"data_coding_alphabet\",\n _type = MessageClass,\n optional = True,\n default_desc = self.DATA_CODING_MESSAGE_CLASS\n )\n except SmppAttributeError as e:\n print(e)\n\n print(\"SMPP Initialized successfully\")\n return True\n\n def destroy(self, configurationAttributes):\n print(\"SMPP Destroy\")\n print(\"SMPP Destroyed successfully\")\n return True\n\n def getApiVersion(self):\n return 11\n \n def getAuthenticationMethodClaims(self, requestParameters):\n return None\n \n def isValidAuthenticationMethod(self, usageType, configurationAttributes):\n return True\n\n def getAlternativeAuthenticationMethod(self, usageType, configurationAttributes):\n return None\n\n def authenticate(self, configurationAttributes, requestParameters, step):\n userService = CdiUtil.bean(UserService)\n authenticationService = CdiUtil.bean(AuthenticationService)\n\n facesMessages = CdiUtil.bean(FacesMessages)\n facesMessages.setKeepMessages()\n\n session_attributes = self.identity.getSessionId().getSessionAttributes()\n form_passcode = ServerUtil.getFirstValue(requestParameters, \"passcode\")\n\n print(\"SMPP form_response_passcode: {}\".format(str(form_passcode)))\n\n if step == 1:\n print(\"SMPP Step 1 Password Authentication\")\n credentials = self.identity.getCredentials()\n\n user_name = credentials.getUsername()\n user_password = credentials.getPassword()\n\n logged_in = False\n if StringHelper.isNotEmptyString(user_name) and StringHelper.isNotEmptyString(user_password):\n logged_in = authenticationService.authenticate(user_name, user_password)\n\n if not logged_in:\n return False\n\n # Get the Person's number and generate a code\n foundUser = None\n try:\n foundUser = authenticationService.getAuthenticatedUser()\n except:\n print(\"SMPP Error retrieving user {} from LDAP\".format(user_name))\n return False\n\n mobile_number = None\n try:\n isVerified = foundUser.getAttribute(\"phoneNumberVerified\")\n if isVerified:\n mobile_number = foundUser.getAttribute(\"employeeNumber\")\n if not mobile_number:\n mobile_number = foundUser.getAttribute(\"mobile\")\n if not mobile_number:\n mobile_number = foundUser.getAttribute(\"telephoneNumber\")\n if not mobile_number:\n facesMessages.add(FacesMessage.SEVERITY_ERROR, \"Failed to determine mobile phone number\")\n print(\"SMPP Error finding mobile number for user '{}'\".format(user_name))\n return False\n except Exception as e:\n facesMessages.add(FacesMessage.SEVERITY_ERROR, \"Failed to determine mobile phone number\")\n print(\"SMPP Error finding mobile number for {}: {}\".format(user_name, e))\n return False\n\n # Generate Random six digit code\n code = random.randint(100000, 999999)\n\n # Get code and save it in LDAP temporarily with special session entry\n self.identity.setWorkingParameter(\"code\", code)\n\n self.identity.setWorkingParameter(\"mobile_number\", mobile_number)\n self.identity.getSessionId().getSessionAttributes().put(\"mobile_number\", mobile_number)\n if not self.sendMessage(mobile_number, str(code)):\n facesMessages.add(FacesMessage.SEVERITY_ERROR, \"Failed to send message to mobile phone\")\n return False\n\n return True\n elif step == 2:\n # Retrieve the session attribute\n print(\"SMPP Step 2 SMS/OTP Authentication\")\n code = session_attributes.get(\"code\")\n print(\"SMPP Code: {}\".format(str(code)))\n\n if code is None:\n print(\"SMPP Failed to find previously sent code\")\n return False\n\n if form_passcode is None:\n print(\"SMPP Passcode is empty\")\n return False\n\n if len(form_passcode) != 6:\n print(\"SMPP Passcode from response is not 6 digits: {}\".format(form_passcode))\n return False\n\n if form_passcode == code:\n print(\"SMPP SUCCESS! User entered the same code!\")\n return True\n\n print(\"SMPP failed, user entered the wrong code! {} != {}\".format(form_passcode, code))\n facesMessages.add(facesMessage.SEVERITY_ERROR, \"Incorrect SMS code, please try again.\")\n return False\n\n print(\"SMPP ERROR: step param not found or != (1|2)\")\n return False\n\n def prepareForStep(self, configurationAttributes, requestParameters, step):\n if step == 1:\n print(\"SMPP Prepare for Step 1\")\n return True\n elif step == 2:\n print(\"SMPP Prepare for Step 2\")\n return True\n\n return False\n\n def getExtraParametersForStep(self, configurationAttributes, step):\n if step == 2:\n return Arrays.asList(\"code\")\n\n return None\n\n def getCountAuthenticationSteps(self, configurationAttributes):\n return 2\n\n def getPageForStep(self, configurationAttributes, step):\n if step == 2:\n return \"/auth/otp_sms/otp_sms.xhtml\"\n\n return \"\"\n\n def getNextStep(self, configurationAttributes, requestParameters, step):\n return -1\n\n def getLogoutExternalUrl(self, configurationAttributes, requestParameters):\n print \"Get external logout URL call\"\n return None\n\n def logout(self, configurationAttributes, requestParameters):\n return True\n\n def sendMessage(self, number, code):\n status = False\n session = SMPPSession()\n session.setTransactionTimer(10000)\n\n # We only handle international destination number reformatting.\n # All others may vary by configuration decisions taken on SMPP\n # server side which we have no clue about.\n if self.DST_ADDR_TON == TypeOfNumber.INTERNATIONAL and number.startswith(\"+\"):\n number = number[1:]\n\n try:\n print(\"SMPP Connecting\")\n reference_id = session.connectAndBind(\n self.SMPP_SERVER,\n self.SMPP_PORT,\n BindParameter(\n BindType.BIND_TX,\n self.SYSTEM_ID,\n self.PASSWORD,\n None,\n self.SRC_ADDR_TON,\n self.SRC_ADDR_NPI,\n None\n )\n )\n print(\"SMPP Connected to server with system id {}\".format(reference_id))\n\n try:\n message_id = session.submitShortMessage(\n \"CMT\",\n self.SRC_ADDR_TON,\n self.SRC_ADDR_NPI,\n self.SRC_ADDR,\n self.DST_ADDR_TON,\n self.DST_ADDR_NPI,\n number,\n ESMClass(),\n 0,\n self.PRIORITY_FLAG,\n self.TIME_FORMATTER.format(Date()),\n None,\n RegisteredDelivery(SMSCDeliveryReceipt.DEFAULT),\n 0,\n GeneralDataCoding(\n self.DATA_CODING_ALPHABET,\n self.DATA_CODING_MESSAGE_CLASS,\n False\n ),\n 0,\n code\n )\n print(\"SMPP Message '{}' sent to #{} with message id {}\".format(code, number, message_id))\n status = True\n except PDUException as e:\n print(\"SMPP Invalid PDU parameter: {}\".format(e))\n except ResponseTimeoutException as e:\n print(\"SMPP Response timeout: {}\".format(e))\n except InvalidResponseException as e:\n print(\"SMPP Receive invalid response: {}\".format(e))\n except NegativeResponseException as e:\n print(\"SMPP Receive negative response: {}\".format(e))\n except IOException as e:\n print(\"SMPP IO error occured: {}\".format(e))\n finally:\n session.unbindAndClose()\n except IOException as e:\n print(\"SMPP Failed connect and bind to host: {}\".format(e))\n\n return status\n", @@ -551,7 +551,7 @@ "level": 50, "programmingLanguage": "PYTHON", "description": "ThumbSignIn authentication module", - "locationType": "LDAP", + "locationType": "db", "dn": "inum=92F0-759E,ou=scripts,o=gluu", "inum": "92F0-759E", "script": "# Author: ThumbSignIn\n\nfrom org.gluu.service.cdi.util import CdiUtil\nfrom org.gluu.oxauth.security import Identity\nfrom org.gluu.model.custom.script.type.auth import PersonAuthenticationType\nfrom org.gluu.oxauth.service import AuthenticationService\nfrom org.gluu.util import StringHelper\nfrom org.gluu.oxauth.util import ServerUtil\nfrom com.pramati.ts.thumbsignin_java_sdk import ThumbsigninApiController\nfrom org.json import JSONObject\nfrom org.gluu.oxauth.model.util import Base64Util\nfrom java.lang import String\n\nimport java\n\n\nclass PersonAuthentication(PersonAuthenticationType):\n\n def __init__(self, current_time_millis):\n self.currentTimeMillis = current_time_millis\n self.thumbsigninApiController = ThumbsigninApiController()\n\n def init(self, customScript, configuration_attributes):\n print \"ThumbSignIn. Initialization\"\n\n global ts_host\n ts_host = configuration_attributes.get(\"ts_host\").getValue2()\n print \"ThumbSignIn. Initialization. Value of ts_host is %s\" % ts_host\n\n global ts_api_key\n ts_api_key = configuration_attributes.get(\"ts_apiKey\").getValue2()\n print \"ThumbSignIn. Initialization. Value of ts_api_key is %s\" % ts_api_key\n\n global ts_api_secret\n ts_api_secret = configuration_attributes.get(\"ts_apiSecret\").getValue2()\n\n global ts_statusPath\n ts_statusPath = \"/ts/secure/txn-status/\"\n\n global AUTHENTICATE\n AUTHENTICATE = \"authenticate\"\n\n global REGISTER\n REGISTER = \"register\"\n\n global TRANSACTION_ID\n TRANSACTION_ID = \"transactionId\"\n\n global USER_ID\n USER_ID = \"userId\"\n\n global USER_LOGIN_FLOW\n USER_LOGIN_FLOW = \"userLoginFlow\"\n\n global THUMBSIGNIN_AUTHENTICATION\n THUMBSIGNIN_AUTHENTICATION = \"ThumbSignIn_Authentication\"\n\n global THUMBSIGNIN_REGISTRATION\n THUMBSIGNIN_REGISTRATION = \"ThumbSignIn_Registration\"\n\n global THUMBSIGNIN_LOGIN_POST_REGISTRATION\n THUMBSIGNIN_LOGIN_POST_REGISTRATION = \"ThumbSignIn_RegistrationSucess\"\n\n global RELYING_PARTY_ID\n RELYING_PARTY_ID = \"relyingPartyId\"\n\n global RELYING_PARTY_LOGIN_URL\n RELYING_PARTY_LOGIN_URL = \"relyingPartyLoginUrl\"\n\n global TSI_LOGIN_PAGE\n TSI_LOGIN_PAGE = \"/auth/thumbsignin/tsLogin.xhtml\"\n\n global TSI_REGISTER_PAGE\n TSI_REGISTER_PAGE = \"/auth/thumbsignin/tsRegister.xhtml\"\n\n global TSI_LOGIN_POST_REGISTRATION_PAGE\n TSI_LOGIN_POST_REGISTRATION_PAGE = \"/auth/thumbsignin/tsRegistrationSuccess.xhtml\"\n\n print \"ThumbSignIn. Initialized successfully\"\n return True\n\n @staticmethod\n def set_relying_party_login_url(identity):\n print \"ThumbSignIn. Inside set_relying_party_login_url...\"\n session_id = identity.getSessionId()\n session_attribute = session_id.getSessionAttributes()\n state_jwt_token = session_attribute.get(\"state\")\n print \"ThumbSignIn. Value of state_jwt_token is %s\" % state_jwt_token\n relying_party_login_url = \"\"\n if (state_jwt_token is None) or (\".\" not in state_jwt_token):\n print \"ThumbSignIn. Value of state parameter is not in the format of JWT Token\"\n identity.setWorkingParameter(RELYING_PARTY_LOGIN_URL, relying_party_login_url)\n return None\n\n state_jwt_token_array = String(state_jwt_token).split(\"\\\\.\")\n state_jwt_token_payload = state_jwt_token_array[1]\n state_payload_str = String(Base64Util.base64urldecode(state_jwt_token_payload), \"UTF-8\")\n state_payload_json = JSONObject(state_payload_str)\n print \"ThumbSignIn. Value of state JWT token Payload is %s\" % state_payload_json\n if state_payload_json.has(\"additional_claims\"):\n additional_claims = state_payload_json.get(\"additional_claims\")\n relying_party_id = additional_claims.get(RELYING_PARTY_ID)\n print \"ThumbSignIn. Value of relying_party_id is %s\" % relying_party_id\n identity.setWorkingParameter(RELYING_PARTY_ID, relying_party_id)\n\n if String(relying_party_id).startsWith(\"google.com\"):\n # google.com/a/unphishableenterprise.com\n relying_party_id_array = String(relying_party_id).split(\"/\")\n google_domain = relying_party_id_array[2]\n print \"ThumbSignIn. Value of google_domain is %s\" % google_domain\n relying_party_login_url = \"https://www.google.com/accounts/AccountChooser?hd=\"+ google_domain + \"%26continue=https://apps.google.com/user/hub\"\n # elif (String(relying_party_id).startsWith(\"xyz\")):\n # relying_party_login_url = \"xyz.com\"\n else:\n # If relying_party_login_url is empty, Gluu's default login URL will be used\n relying_party_login_url = \"\"\n\n print \"ThumbSignIn. Value of relying_party_login_url is %s\" % relying_party_login_url\n identity.setWorkingParameter(RELYING_PARTY_LOGIN_URL, relying_party_login_url)\n return None\n\n def initialize_thumbsignin(self, identity, request_path):\n # Invoking the authenticate/register ThumbSignIn API via the Java SDK\n thumbsignin_response = self.thumbsigninApiController.handleThumbSigninRequest(request_path, ts_api_key, ts_api_secret)\n print \"ThumbSignIn. Value of thumbsignin_response is %s\" % thumbsignin_response\n\n thumbsignin_response_json = JSONObject(thumbsignin_response)\n transaction_id = thumbsignin_response_json.get(TRANSACTION_ID)\n status_request_type = \"authStatus\" if request_path == AUTHENTICATE else \"regStatus\"\n status_request = status_request_type + \"/\" + transaction_id\n print \"ThumbSignIn. Value of status_request is %s\" % status_request\n\n authorization_header = self.thumbsigninApiController.getAuthorizationHeaderJsonStr(status_request, ts_api_key, ts_api_secret)\n print \"ThumbSignIn. Value of authorization_header is %s\" % authorization_header\n # {\"authHeader\":\"HmacSHA256 Credential=X,SignedHeaders=accept;content-type;x-ts-date,Signature=X\",\"XTsDate\":\"X\"}\n authorization_header_json = JSONObject(authorization_header)\n auth_header = authorization_header_json.get(\"authHeader\")\n x_ts_date = authorization_header_json.get(\"XTsDate\")\n\n tsi_response_key = \"authenticateResponseJsonStr\" if request_path == AUTHENTICATE else \"registerResponseJsonStr\"\n identity.setWorkingParameter(tsi_response_key, thumbsignin_response)\n identity.setWorkingParameter(\"authorizationHeader\", auth_header)\n identity.setWorkingParameter(\"xTsDate\", x_ts_date)\n return None\n\n def prepareForStep(self, configuration_attributes, request_parameters, step):\n print \"ThumbSignIn. Inside prepareForStep. Step %d\" % step\n identity = CdiUtil.bean(Identity)\n authentication_service = CdiUtil.bean(AuthenticationService)\n\n identity.setWorkingParameter(\"ts_host\", ts_host)\n identity.setWorkingParameter(\"ts_statusPath\", ts_statusPath)\n\n self.set_relying_party_login_url(identity)\n\n if step == 1 or step == 3:\n print \"ThumbSignIn. Prepare for step 1\"\n self.initialize_thumbsignin(identity, AUTHENTICATE)\n return True\n\n elif step == 2:\n print \"ThumbSignIn. Prepare for step 2\"\n if identity.isSetWorkingParameter(USER_LOGIN_FLOW):\n user_login_flow = identity.getWorkingParameter(USER_LOGIN_FLOW)\n print \"ThumbSignIn. Value of user_login_flow is %s\" % user_login_flow\n user = authentication_service.getAuthenticatedUser()\n if user is None:\n print \"ThumbSignIn. Prepare for step 2. Failed to determine user name\"\n return False\n user_name = user.getUserId()\n print \"ThumbSignIn. Prepare for step 2. user_name: \" + user_name\n if user_name is None:\n return False\n identity.setWorkingParameter(USER_ID, user_name)\n self.initialize_thumbsignin(identity, REGISTER + \"/\" + user_name)\n return True\n else:\n return False\n\n def get_user_id_from_thumbsignin(self, request_parameters):\n transaction_id = ServerUtil.getFirstValue(request_parameters, TRANSACTION_ID)\n print \"ThumbSignIn. Value of transaction_id is %s\" % transaction_id\n get_user_request = \"getUser/\" + transaction_id\n print \"ThumbSignIn. Value of get_user_request is %s\" % get_user_request\n\n get_user_response = self.thumbsigninApiController.handleThumbSigninRequest(get_user_request, ts_api_key, ts_api_secret)\n print \"ThumbSignIn. Value of get_user_response is %s\" % get_user_response\n get_user_response_json = JSONObject(get_user_response)\n thumbsignin_user_id = get_user_response_json.get(USER_ID)\n print \"ThumbSignIn. Value of thumbsignin_user_id is %s\" % thumbsignin_user_id\n return thumbsignin_user_id\n\n def authenticate(self, configuration_attributes, request_parameters, step):\n print \"ThumbSignIn. Inside authenticate. Step %d\" % step\n authentication_service = CdiUtil.bean(AuthenticationService)\n identity = CdiUtil.bean(Identity)\n\n identity.setWorkingParameter(\"ts_host\", ts_host)\n identity.setWorkingParameter(\"ts_statusPath\", ts_statusPath)\n\n if step == 1 or step == 3:\n print \"ThumbSignIn. Authenticate for Step %d\" % step\n\n login_flow = ServerUtil.getFirstValue(request_parameters, \"login_flow\")\n print \"ThumbSignIn. Value of login_flow parameter is %s\" % login_flow\n\n # Logic for ThumbSignIn Authentication Flow (Either step 1 or step 3)\n if login_flow == THUMBSIGNIN_AUTHENTICATION or login_flow == THUMBSIGNIN_LOGIN_POST_REGISTRATION:\n identity.setWorkingParameter(USER_LOGIN_FLOW, login_flow)\n print \"ThumbSignIn. Value of userLoginFlow is %s\" % identity.getWorkingParameter(USER_LOGIN_FLOW)\n logged_in_status = authentication_service.authenticate(self.get_user_id_from_thumbsignin(request_parameters))\n print \"ThumbSignIn. logged_in status : %r\" % logged_in_status\n return logged_in_status\n\n # Logic for traditional login flow (step 1)\n print \"ThumbSignIn. User credentials login flow\"\n identity.setWorkingParameter(USER_LOGIN_FLOW, THUMBSIGNIN_REGISTRATION)\n print \"ThumbSignIn. Value of userLoginFlow is %s\" % identity.getWorkingParameter(USER_LOGIN_FLOW)\n logged_in = self.authenticate_user_credentials(identity, authentication_service)\n print \"ThumbSignIn. Status of User Credentials based Authentication : %r\" % logged_in\n\n # When the traditional login fails, reinitialize the ThumbSignIn data before sending error response to UI\n if not logged_in:\n self.initialize_thumbsignin(identity, AUTHENTICATE)\n return False\n\n print \"ThumbSignIn. Authenticate successful for step %d\" % step\n return True\n\n elif step == 2:\n print \"ThumbSignIn. Registration flow (step 2)\"\n self.verify_user_login_flow(identity)\n\n user = self.get_authenticated_user_from_gluu(authentication_service)\n if user is None:\n print \"ThumbSignIn. Registration flow (step 2). Failed to determine user name\"\n return False\n\n user_name = user.getUserId()\n print \"ThumbSignIn. Registration flow (step 2) successful. user_name: %s\" % user_name\n return True\n\n else:\n return False\n\n def authenticate_user_credentials(self, identity, authentication_service):\n credentials = identity.getCredentials()\n user_name = credentials.getUsername()\n user_password = credentials.getPassword()\n print \"ThumbSignIn. user_name: \" + user_name\n logged_in = False\n if StringHelper.isNotEmptyString(user_name) and StringHelper.isNotEmptyString(user_password):\n logged_in = self.authenticate_user_in_gluu_ldap(authentication_service, user_name, user_password)\n return logged_in\n\n @staticmethod\n def authenticate_user_in_gluu_ldap(authentication_service, user_name, user_password):\n return authentication_service.authenticate(user_name, user_password)\n\n @staticmethod\n def get_authenticated_user_from_gluu(authentication_service):\n return authentication_service.getAuthenticatedUser()\n\n @staticmethod\n def verify_user_login_flow(identity):\n if identity.isSetWorkingParameter(USER_LOGIN_FLOW):\n user_login_flow = identity.getWorkingParameter(USER_LOGIN_FLOW)\n print \"ThumbSignIn. Value of user_login_flow is %s\" % user_login_flow\n else:\n identity.setWorkingParameter(USER_LOGIN_FLOW, THUMBSIGNIN_REGISTRATION)\n print \"ThumbSignIn. Setting the value of user_login_flow to %s\" % identity.getWorkingParameter(USER_LOGIN_FLOW)\n\n def getExtraParametersForStep(self, configuration_attributes, step):\n return None\n\n def getCountAuthenticationSteps(self, configuration_attributes):\n print \"ThumbSignIn. Inside getCountAuthenticationSteps..\"\n identity = CdiUtil.bean(Identity)\n\n user_login_flow = identity.getWorkingParameter(USER_LOGIN_FLOW)\n print \"ThumbSignIn. Value of userLoginFlow is %s\" % user_login_flow\n if user_login_flow == THUMBSIGNIN_AUTHENTICATION:\n print \"ThumbSignIn. Total Authentication Steps is: 1\"\n return 1\n print \"ThumbSignIn. Total Authentication Steps is: 3\"\n return 3\n\n def getPageForStep(self, configuration_attributes, step):\n print \"ThumbSignIn. Inside getPageForStep. Step %d\" % step\n if step == 3:\n return TSI_LOGIN_POST_REGISTRATION_PAGE\n thumbsignin_page = TSI_REGISTER_PAGE if step == 2 else TSI_LOGIN_PAGE\n return thumbsignin_page\n\n def destroy(self, configurationAttributes):\n print \"ThumbSignIn. Destroy\"\n return True\n\n def getApiVersion(self):\n return 11\n \n def getAuthenticationMethodClaims(self, requestParameters):\n return None\n \n def isValidAuthenticationMethod(self, usageType, configurationAttributes):\n return True\n\n def getAlternativeAuthenticationMethod(self, usageType, configurationAttributes):\n return None\n\n def getNextStep(self, configurationAttributes, requestParameters, step):\n return -1\n\n def getLogoutExternalUrl(self, configurationAttributes, requestParameters):\n print \"Get external logout URL call\"\n return None\n\n def logout(self, configurationAttributes, requestParameters):\n return True\n", @@ -594,7 +594,7 @@ "level": 50, "programmingLanguage": "PYTHON", "description": "DUO authentication module", - "locationType": "LDAP", + "locationType": "db", "dn": "inum=5018-F9CF,ou=scripts,o=gluu", "inum": "5018-F9CF", "script": "# jans-auth is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text.\n# Copyright (c) 2016, Gluu\n#\n# Author: Yuriy Movchan\n#\n\nfrom org.gluu.service.cdi.util import CdiUtil\nfrom org.gluu.oxauth.security import Identity\nfrom org.gluu.model.custom.script.type.auth import PersonAuthenticationType\nfrom org.gluu.oxauth.service import AuthenticationService\nfrom org.gluu.oxauth.service.common import UserService\nfrom org.gluu.service import MailService\nfrom org.gluu.util import ArrayHelper\nfrom org.gluu.util import StringHelper\nfrom java.util import Arrays\n\nimport duo_web\nimport json\n\nclass PersonAuthentication(PersonAuthenticationType):\n def __init__(self, currentTimeMillis):\n self.currentTimeMillis = currentTimeMillis\n\n def init(self, customScript, configurationAttributes):\n print \"Duo. Initialization\"\n\n duo_creds_file = configurationAttributes.get(\"duo_creds_file\").getValue2()\n # Load credentials from file\n f = open(duo_creds_file, 'r')\n try:\n creds = json.loads(f.read())\n except:\n print \"Duo. Initialization. Failed to load creds from file:\", duo_creds_file\n return False\n finally:\n f.close()\n\n self.ikey = str(creds[\"ikey\"])\n self.skey = str(creds[\"skey\"])\n self.akey = str(creds[\"akey\"])\n\n self.use_duo_group = False\n if (configurationAttributes.containsKey(\"duo_group\")):\n self.duo_group = configurationAttributes.get(\"duo_group\").getValue2()\n self.use_duo_group = True\n print \"Duo. Initialization. Using Duo only if user belong to group:\", self.duo_group\n\n self.use_audit_group = False\n if (configurationAttributes.containsKey(\"audit_group\")):\n self.audit_group = configurationAttributes.get(\"audit_group\").getValue2()\n\n if (not configurationAttributes.containsKey(\"audit_group_email\")):\n print \"Duo. Initialization. Property audit_group_email is not specified\"\n return False\n\n self.audit_email = configurationAttributes.get(\"audit_group_email\").getValue2()\n self.use_audit_group = True\n\n print \"Duo. Initialization. Using audito group:\", self.audit_group\n \n if (self.use_duo_group or self.use_audit_group):\n if (not configurationAttributes.containsKey(\"audit_attribute\")):\n print \"Duo. Initialization. Property audit_attribute is not specified\"\n return False\n else:\n self.audit_attribute = configurationAttributes.get(\"audit_attribute\").getValue2()\n\n print \"Duo. Initialized successfully\"\n return True \n\n def destroy(self, configurationAttributes):\n print \"Duo. Destroy\"\n print \"Duo. Destroyed successfully\"\n return True\n\n def getApiVersion(self):\n return 11\n \n def getAuthenticationMethodClaims(self, requestParameters):\n return None\n \n def isValidAuthenticationMethod(self, usageType, configurationAttributes):\n return True\n\n def getAlternativeAuthenticationMethod(self, usageType, configurationAttributes):\n return None\n\n def authenticate(self, configurationAttributes, requestParameters, step):\n duo_host = configurationAttributes.get(\"duo_host\").getValue2()\n\n authenticationService = CdiUtil.bean(AuthenticationService)\n\n identity = CdiUtil.bean(Identity)\n\n if (step == 1):\n print \"Duo. Authenticate for step 1\"\n\n # Check if user authenticated already in another custom script\n user = authenticationService.getAuthenticatedUser()\n if user == None:\n credentials = identity.getCredentials()\n user_name = credentials.getUsername()\n user_password = credentials.getPassword()\n \n logged_in = False\n if (StringHelper.isNotEmptyString(user_name) and StringHelper.isNotEmptyString(user_password)):\n userService = CdiUtil.bean(UserService)\n logged_in = authenticationService.authenticate(user_name, user_password)\n \n if (not logged_in):\n return False\n \n user = authenticationService.getAuthenticatedUser()\n\n if (self.use_duo_group):\n print \"Duo. Authenticate for step 1. Checking if user belong to Duo group\"\n is_member_duo_group = self.isUserMemberOfGroup(user, self.audit_attribute, self.duo_group)\n if (is_member_duo_group):\n print \"Duo. Authenticate for step 1. User '\" + user.getUserId() + \"' member of Duo group\"\n duo_count_login_steps = 2\n else:\n self.processAuditGroup(user)\n duo_count_login_steps = 1\n\n identity.setWorkingParameter(\"duo_count_login_steps\", duo_count_login_steps)\n\n return True\n elif (step == 2):\n print \"Duo. Authenticate for step 2\"\n user = authenticationService.getAuthenticatedUser()\n if user == None:\n print \"Duo. Authenticate for step 2. Failed to determine user name\"\n return False\n\n user_name = user.getUserId()\n\n sig_response_array = requestParameters.get(\"sig_response\")\n if ArrayHelper.isEmpty(sig_response_array):\n print \"Duo. Authenticate for step 2. sig_response is empty\"\n return False\n\n duo_sig_response = sig_response_array[0]\n\n print \"Duo. Authenticate for step 2. duo_sig_response: \" + duo_sig_response\n\n authenticated_username = duo_web.verify_response(self.ikey, self.skey, self.akey, duo_sig_response)\n\n print \"Duo. Authenticate for step 2. authenticated_username: \" + authenticated_username + \", expected user_name: \" + user_name\n\n if (not StringHelper.equals(user_name, authenticated_username)):\n return False\n\n self.processAuditGroup(user)\n\n return True\n else:\n return False\n\n def prepareForStep(self, configurationAttributes, requestParameters, step):\n identity = CdiUtil.bean(Identity)\n authenticationService = CdiUtil.bean(AuthenticationService)\n\n duo_host = configurationAttributes.get(\"duo_host\").getValue2()\n\n if (step == 1):\n print \"Duo. Prepare for step 1\"\n\n return True\n elif (step == 2):\n print \"Duo. Prepare for step 2\"\n\n user = authenticationService.getAuthenticatedUser()\n if (user == None):\n print \"Duo. Prepare for step 2. Failed to determine user name\"\n return False\n user_name = user.getUserId()\n\n duo_sig_request = duo_web.sign_request(self.ikey, self.skey, self.akey, user_name)\n print \"Duo. Prepare for step 2. duo_sig_request: \" + duo_sig_request\n \n identity.setWorkingParameter(\"duo_host\", duo_host)\n identity.setWorkingParameter(\"duo_sig_request\", duo_sig_request)\n\n return True\n else:\n return False\n\n def getExtraParametersForStep(self, configurationAttributes, step):\n if step == 2:\n return Arrays.asList(\"duo_count_login_steps\", \"cas2_user_uid\")\n\n return None\n\n def getCountAuthenticationSteps(self, configurationAttributes):\n identity = CdiUtil.bean(Identity)\n if (identity.isSetWorkingParameter(\"duo_count_login_steps\")):\n return int(identity.getWorkingParameter(\"duo_count_login_steps\"))\n\n return 2\n\n def getPageForStep(self, configurationAttributes, step):\n if (step == 2):\n return \"/auth/duo/duologin.xhtml\"\n return \"\"\n\n def getNextStep(self, configurationAttributes, requestParameters, step):\n return -1\n\n def getLogoutExternalUrl(self, configurationAttributes, requestParameters):\n print \"Get external logout URL call\"\n return None\n\n def logout(self, configurationAttributes, requestParameters):\n return True\n\n def isUserMemberOfGroup(self, user, attribute, group):\n is_member = False\n member_of_list = user.getAttributeValues(attribute)\n if (member_of_list != None):\n for member_of in member_of_list:\n if StringHelper.equalsIgnoreCase(group, member_of) or member_of.endswith(group):\n is_member = True\n break\n\n return is_member\n\n def processAuditGroup(self, user):\n if (self.use_audit_group):\n is_member = self.isUserMemberOfGroup(user, self.audit_attribute, self.audit_group)\n if (is_member):\n print \"Duo. Authenticate for processAuditGroup. User '\" + user.getUserId() + \"' member of audit group\"\n print \"Duo. Authenticate for processAuditGroup. Sending e-mail about user '\" + user.getUserId() + \"' login to\", self.audit_email\n \n # Send e-mail to administrator\n user_id = user.getUserId()\n mailService = CdiUtil.bean(MailService)\n subject = \"User log in: \" + user_id\n body = \"User log in: \" + user_id\n mailService.sendMail(self.audit_email, subject, body)\n", @@ -632,7 +632,7 @@ "level": 50, "programmingLanguage": "PYTHON", "description": "Twilio SMS authentication module", - "locationType": "LDAP", + "locationType": "db", "dn": "inum=09A0-93D6,ou=scripts,o=gluu", "inum": "09A0-93D6", "script": "# jans-auth is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text.\r\n# Copyright (c) 2018, Gluu\r\n#\r\n# Author: Jose Gonzalez\r\n# Author: Gasmyr Mougang\r\n\r\nfrom org.gluu.service.cdi.util import CdiUtil\r\nfrom org.gluu.oxauth.security import Identity\r\nfrom org.gluu.model.custom.script.type.auth import PersonAuthenticationType\r\nfrom org.gluu.oxauth.service import AuthenticationService\r\nfrom org.gluu.oxauth.service.common import UserService\r\nfrom org.gluu.oxauth.util import ServerUtil\r\nfrom org.gluu.util import StringHelper, ArrayHelper\r\nfrom java.util import Arrays\r\nfrom javax.faces.application import FacesMessage\r\nfrom org.gluu.jsf2.message import FacesMessages\r\n\r\nimport com.twilio.Twilio as Twilio\r\nimport com.twilio.rest.api.v2010.account.Message as Message\r\nimport com.twilio.type.PhoneNumber as PhoneNumber\r\nimport org.codehaus.jettison.json.JSONArray as JSONArray\r\n\r\n\r\nimport java\r\nimport random\r\nimport jarray\r\n\r\nclass PersonAuthentication(PersonAuthenticationType):\r\n def __init__(self, currentTimeMillis):\r\n self.currentTimeMillis = currentTimeMillis\r\n self.mobile_number = None\r\n self.identity = CdiUtil.bean(Identity)\r\n\r\n def init(self, customScript, configurationAttributes):\r\n print \"Twilio SMS. Initialization\"\r\n self.ACCOUNT_SID = None\r\n self.AUTH_TOKEN = None\r\n self.FROM_NUMBER = None\r\n\r\n # Get Custom Properties\r\n try:\r\n self.ACCOUNT_SID = configurationAttributes.get(\"twilio_sid\").getValue2()\r\n except:\r\n print 'TwilioSMS, Missing required configuration attribute \"twilio_sid\"'\r\n\r\n try:\r\n self.AUTH_TOKEN = configurationAttributes.get(\"twilio_token\").getValue2()\r\n except:\r\n print'TwilioSMS, Missing required configuration attribute \"twilio_token\"'\r\n try:\r\n self.FROM_NUMBER = configurationAttributes.get(\"from_number\").getValue2()\r\n except:\r\n print'TwilioSMS, Missing required configuration attribute \"from_number\"'\r\n\r\n if None in (self.ACCOUNT_SID, self.AUTH_TOKEN, self.FROM_NUMBER):\r\n print \"twilio_sid, twilio_token, from_number is empty ... returning False\"\r\n return False\r\n\r\n print \"Twilio SMS. Initialized successfully\"\r\n\r\n return True\r\n\r\n def destroy(self, configurationAttributes):\r\n print \"Twilio SMS. Destroy\"\r\n print \"Twilio SMS. Destroyed successfully\"\r\n return True\r\n\r\n def getApiVersion(self):\r\n return 11\r\n \r\n def getAuthenticationMethodClaims(self, requestParameters):\r\n return None\r\n \r\n def isValidAuthenticationMethod(self, usageType, configurationAttributes):\r\n return True\r\n\r\n def getAlternativeAuthenticationMethod(self, usageType, configurationAttributes):\r\n return None\r\n\r\n def authenticate(self, configurationAttributes, requestParameters, step):\r\n userService = CdiUtil.bean(UserService)\r\n authenticationService = CdiUtil.bean(AuthenticationService)\r\n\r\n facesMessages = CdiUtil.bean(FacesMessages)\r\n facesMessages.setKeepMessages()\r\n\r\n session_attributes = self.identity.getSessionId().getSessionAttributes()\r\n form_passcode = ServerUtil.getFirstValue(requestParameters, \"passcode\")\r\n form_name = ServerUtil.getFirstValue(requestParameters, \"TwilioSmsloginForm\")\r\n\r\n print \"TwilioSMS. form_response_passcode: %s\" % str(form_passcode)\r\n\r\n if step == 1:\r\n print \"TwilioSMS. Step 1 Password Authentication\"\r\n credentials = self.identity.getCredentials()\r\n\r\n user_name = credentials.getUsername()\r\n user_password = credentials.getPassword()\r\n\r\n logged_in = False\r\n if StringHelper.isNotEmptyString(user_name) and StringHelper.isNotEmptyString(user_password):\r\n logged_in = authenticationService.authenticate(user_name, user_password)\r\n\r\n if not logged_in:\r\n return False\r\n\r\n # Get the Person's number and generate a code\r\n foundUser = None\r\n try:\r\n foundUser = authenticationService.getAuthenticatedUser()\r\n except:\r\n print 'TwilioSMS, Error retrieving user %s from LDAP' % (user_name)\r\n return False\r\n\r\n try:\r\n isVerified = foundUser.getAttribute(\"phoneNumberVerified\")\r\n if isVerified:\r\n self.mobile_number = foundUser.getAttribute(\"employeeNumber\")\r\n if self.mobile_number == None:\r\n self.mobile_number = foundUser.getAttribute(\"mobile\")\r\n if self.mobile_number == None:\r\n self.mobile_number = foundUser.getAttribute(\"telephoneNumber\")\r\n if self.mobile_number == None:\r\n print \"TwilioSMS, Error finding mobile number for user '%s'\" % user_name \r\n \r\n except:\r\n facesMessages.add(FacesMessage.SEVERITY_ERROR, \"Failed to determine mobile phone number\")\r\n print 'TwilioSMS, Error finding mobile number for \"%s\". Exception: %s` % (user_name, sys.exc_info()[1])`'\r\n return False\r\n\r\n # Generate Random six digit code and store it in array\r\n code = random.randint(100000, 999999)\r\n\r\n # Get code and save it in LDAP temporarily with special session entry\r\n self.identity.setWorkingParameter(\"code\", code)\r\n\r\n try:\r\n Twilio.init(self.ACCOUNT_SID, self.AUTH_TOKEN);\r\n message = Message.creator(PhoneNumber(self.mobile_number), PhoneNumber(self.FROM_NUMBER), str(code)).create();\r\n print \"++++++++++++++++++++++++++++++++++++++++++++++\"\r\n print 'TwilioSMs, Message Sid: %s' % (message.getSid())\r\n print 'TwilioSMs, User phone: %s' % (self.mobile_number)\r\n print \"++++++++++++++++++++++++++++++++++++++++++++++\"\r\n self.identity.setWorkingParameter(\"mobile_number\", self.mobile_number)\r\n self.identity.getSessionId().getSessionAttributes().put(\"mobile_number\",self.mobile_number)\r\n self.identity.setWorkingParameter(\"mobile\", self.mobile_number)\r\n self.identity.getSessionId().getSessionAttributes().put(\"mobile\",self.mobile_number)\r\n print \"++++++++++++++++++++++++++++++++++++++++++++++\"\r\n print \"Number: %s\" % (self.identity.getWorkingParameter(\"mobile_number\"))\r\n print \"Mobile: %s\" % (self.identity.getWorkingParameter(\"mobile\"))\r\n print \"++++++++++++++++++++++++++++++++++++++++++++++\"\r\n return True\r\n except Exception, ex:\r\n facesMessages.add(FacesMessage.SEVERITY_ERROR, \"Failed to send message to mobile phone\")\r\n print \"TwilioSMS. Error sending message to Twilio\"\r\n print \"TwilioSMS. Unexpected error:\", ex\r\n\r\n return False\r\n elif step == 2:\r\n # Retrieve the session attribute\r\n print \"TwilioSMS. Step 2 SMS/OTP Authentication\"\r\n code = session_attributes.get(\"code\")\r\n print \"----------------------------------\"\r\n print \"TwilioSMS. Code: %s\" % str(code)\r\n print \"----------------------------------\"\r\n\r\n if code is None:\r\n print \"TwilioSMS. Failed to find previously sent code\"\r\n return False\r\n\r\n if form_passcode is None:\r\n print \"TwilioSMS. Passcode is empty\"\r\n return False\r\n\r\n if len(form_passcode) != 6:\r\n print \"TwilioSMS. Passcode from response is not 6 digits: %s\" % form_passcode\r\n return False\r\n\r\n if form_passcode == code:\r\n print \"TiwlioSMS, SUCCESS! User entered the same code!\"\r\n return True\r\n\r\n print \"+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\" \r\n print \"TwilioSMS. FAIL! User entered the wrong code! %s != %s\" % (form_passcode, code)\r\n print \"+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\" \r\n facesMessages.add(FacesMessage.SEVERITY_ERROR, \"Incorrect Twilio code, please try again.\")\r\n\r\n return False\r\n\r\n print \"TwilioSMS. ERROR: step param not found or != (1|2)\"\r\n\r\n return False\r\n\r\n def prepareForStep(self, configurationAttributes, requestParameters, step):\r\n if step == 1:\r\n print \"TwilioSMS. Prepare for Step 1\"\r\n return True\r\n elif step == 2:\r\n print \"TwilioSMS. Prepare for Step 2\"\r\n return True\r\n return False\r\n\r\n def getExtraParametersForStep(self, configurationAttributes, step):\r\n if step == 2:\r\n return Arrays.asList(\"code\")\r\n\r\n return None\r\n\r\n def getCountAuthenticationSteps(self, configurationAttributes):\r\n return 2\r\n\r\n def getPageForStep(self, configurationAttributes, step):\r\n if step == 2:\r\n return \"/auth/otp_sms/otp_sms.xhtml\"\r\n\r\n return \"\"\r\n \r\n def getNextStep(self, configurationAttributes, requestParameters, step):\r\n return -1\r\n\r\n def getLogoutExternalUrl(self, configurationAttributes, requestParameters):\r\n print \"Get external logout URL call\"\r\n return None\r\n \r\n def logout(self, configurationAttributes, requestParameters):\r\n return True\r\n", @@ -675,7 +675,7 @@ "level": 50, "programmingLanguage": "PYTHON", "description": "Fido U2F authentication module", - "locationType": "LDAP", + "locationType": "db", "dn": "inum=8BAF-80D6,ou=scripts,o=gluu", "inum": "8BAF-80D6", "script": "# jans-auth is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text.\r\n# Copyright (c) 2016, Gluu\r\n#\r\n# Author: Yuriy Movchan\r\n#\r\n\r\nimport java\r\nimport sys\r\nfrom javax.ws.rs.core import Response\r\nfrom org.jboss.resteasy.client import ClientResponseFailure\r\nfrom org.jboss.resteasy.client.exception import ResteasyClientException\r\nfrom org.gluu.model.custom.script.type.auth import PersonAuthenticationType\r\nfrom org.gluu.oxauth.client.fido.u2f import FidoU2fClientFactory\r\nfrom org.gluu.oxauth.model.config import Constants\r\nfrom org.gluu.oxauth.security import Identity\r\nfrom org.gluu.oxauth.service import AuthenticationService, SessionIdService\r\nfrom org.gluu.oxauth.service.common import UserService\r\nfrom org.gluu.oxauth.service.fido.u2f import DeviceRegistrationService\r\nfrom org.gluu.oxauth.util import ServerUtil\r\nfrom org.gluu.service.cdi.util import CdiUtil\r\nfrom org.gluu.util import StringHelper\r\n\r\n\r\nclass PersonAuthentication(PersonAuthenticationType):\r\n def __init__(self, currentTimeMillis):\r\n self.currentTimeMillis = currentTimeMillis\r\n\r\n def init(self, customScript, configurationAttributes):\r\n print \"U2F. Initialization\"\r\n\r\n print \"U2F. Initialization. Downloading U2F metadata\"\r\n u2f_server_uri = configurationAttributes.get(\"u2f_server_uri\").getValue2()\r\n u2f_server_metadata_uri = u2f_server_uri + \"/.well-known/fido-u2f-configuration\"\r\n\r\n metaDataConfigurationService = FidoU2fClientFactory.instance().createMetaDataConfigurationService(u2f_server_metadata_uri)\r\n\r\n max_attempts = 20\r\n for attempt in range(1, max_attempts + 1):\r\n try:\r\n self.metaDataConfiguration = metaDataConfigurationService.getMetadataConfiguration()\r\n break\r\n except ClientResponseFailure, ex:\r\n # Detect if last try or we still get Service Unavailable HTTP error\r\n if (attempt == max_attempts) or (ex.getResponse().getResponseStatus() != Response.Status.SERVICE_UNAVAILABLE):\r\n raise ex\r\n\r\n java.lang.Thread.sleep(3000)\r\n print \"Attempting to load metadata: %d\" % attempt\r\n except ResteasyClientException, ex:\r\n # Detect if last try or we still get Service Unavailable HTTP error\r\n if attempt == max_attempts:\r\n raise ex\r\n\r\n java.lang.Thread.sleep(3000)\r\n print \"Attempting to load metadata: %d\" % attempt\r\n \r\n print \"U2F. Initialized successfully\"\r\n return True \r\n\r\n def destroy(self, configurationAttributes):\r\n print \"U2F. Destroy\"\r\n print \"U2F. Destroyed successfully\"\r\n return True\r\n\r\n def getApiVersion(self):\r\n return 11\r\n \r\n def getAuthenticationMethodClaims(self, requestParameters):\r\n return None\r\n \r\n def isValidAuthenticationMethod(self, usageType, configurationAttributes):\r\n return True\r\n\r\n def getAlternativeAuthenticationMethod(self, usageType, configurationAttributes):\r\n return None\r\n\r\n def authenticate(self, configurationAttributes, requestParameters, step):\r\n authenticationService = CdiUtil.bean(AuthenticationService)\r\n\r\n identity = CdiUtil.bean(Identity)\r\n credentials = identity.getCredentials()\r\n\r\n user_name = credentials.getUsername()\r\n\r\n if (step == 1):\r\n print \"U2F. Authenticate for step 1\"\r\n\r\n user_password = credentials.getPassword()\r\n logged_in = False\r\n if (StringHelper.isNotEmptyString(user_name) and StringHelper.isNotEmptyString(user_password)):\r\n userService = CdiUtil.bean(UserService)\r\n logged_in = authenticationService.authenticate(user_name, user_password)\r\n\r\n if (not logged_in):\r\n return False\r\n\r\n return True\r\n elif (step == 2):\r\n print \"U2F. Authenticate for step 2\"\r\n\r\n token_response = ServerUtil.getFirstValue(requestParameters, \"tokenResponse\")\r\n if token_response == None:\r\n print \"U2F. Authenticate for step 2. tokenResponse is empty\"\r\n return False\r\n\r\n auth_method = ServerUtil.getFirstValue(requestParameters, \"authMethod\")\r\n if auth_method == None:\r\n print \"U2F. Authenticate for step 2. authMethod is empty\"\r\n return False\r\n\r\n authenticationService = CdiUtil.bean(AuthenticationService)\r\n user = authenticationService.getAuthenticatedUser()\r\n if (user == None):\r\n print \"U2F. Prepare for step 2. Failed to determine user name\"\r\n return False\r\n\r\n if (auth_method == 'authenticate'):\r\n print \"U2F. Prepare for step 2. Call FIDO U2F in order to finish authentication workflow\"\r\n authenticationRequestService = FidoU2fClientFactory.instance().createAuthenticationRequestService(self.metaDataConfiguration)\r\n authenticationStatus = authenticationRequestService.finishAuthentication(user.getUserId(), token_response)\r\n\r\n if (authenticationStatus.getStatus() != Constants.RESULT_SUCCESS):\r\n print \"U2F. Authenticate for step 2. Get invalid authentication status from FIDO U2F server\"\r\n return False\r\n\r\n return True\r\n elif (auth_method == 'enroll'):\r\n print \"U2F. Prepare for step 2. Call FIDO U2F in order to finish registration workflow\"\r\n registrationRequestService = FidoU2fClientFactory.instance().createRegistrationRequestService(self.metaDataConfiguration)\r\n registrationStatus = registrationRequestService.finishRegistration(user.getUserId(), token_response)\r\n\r\n if (registrationStatus.getStatus() != Constants.RESULT_SUCCESS):\r\n print \"U2F. Authenticate for step 2. Get invalid registration status from FIDO U2F server\"\r\n return False\r\n\r\n return True\r\n else:\r\n print \"U2F. Prepare for step 2. Authenticatiod method is invalid\"\r\n return False\r\n\r\n return False\r\n else:\r\n return False\r\n\r\n def prepareForStep(self, configurationAttributes, requestParameters, step):\r\n identity = CdiUtil.bean(Identity)\r\n\r\n if (step == 1):\r\n return True\r\n elif (step == 2):\r\n print \"U2F. Prepare for step 2\"\r\n\r\n session = CdiUtil.bean(SessionIdService).getSessionId()\r\n if session == None:\r\n print \"U2F. Prepare for step 2. Failed to determine session_id\"\r\n return False\r\n\r\n authenticationService = CdiUtil.bean(AuthenticationService)\r\n user = authenticationService.getAuthenticatedUser()\r\n if (user == None):\r\n print \"U2F. Prepare for step 2. Failed to determine user name\"\r\n return False\r\n\r\n u2f_application_id = configurationAttributes.get(\"u2f_application_id\").getValue2()\r\n\r\n # Check if user have registered devices\r\n deviceRegistrationService = CdiUtil.bean(DeviceRegistrationService)\r\n\r\n userInum = user.getAttribute(\"inum\")\r\n\r\n registrationRequest = None\r\n authenticationRequest = None\r\n\r\n deviceRegistrations = deviceRegistrationService.findUserDeviceRegistrations(userInum, u2f_application_id)\r\n if (deviceRegistrations.size() > 0):\r\n print \"U2F. Prepare for step 2. Call FIDO U2F in order to start authentication workflow\"\r\n\r\n try:\r\n authenticationRequestService = FidoU2fClientFactory.instance().createAuthenticationRequestService(self.metaDataConfiguration)\r\n authenticationRequest = authenticationRequestService.startAuthentication(user.getUserId(), None, u2f_application_id, session.getId())\r\n except ClientResponseFailure, ex:\r\n if (ex.getResponse().getResponseStatus() != Response.Status.NOT_FOUND):\r\n print \"U2F. Prepare for step 2. Failed to start authentication workflow. Exception:\", sys.exc_info()[1]\r\n return False\r\n else:\r\n print \"U2F. Prepare for step 2. Call FIDO U2F in order to start registration workflow\"\r\n registrationRequestService = FidoU2fClientFactory.instance().createRegistrationRequestService(self.metaDataConfiguration)\r\n registrationRequest = registrationRequestService.startRegistration(user.getUserId(), u2f_application_id, session.getId())\r\n\r\n identity.setWorkingParameter(\"fido_u2f_authentication_request\", ServerUtil.asJson(authenticationRequest))\r\n identity.setWorkingParameter(\"fido_u2f_registration_request\", ServerUtil.asJson(registrationRequest))\r\n\r\n return True\r\n elif (step == 3):\r\n print \"U2F. Prepare for step 3\"\r\n\r\n return True\r\n else:\r\n return False\r\n\r\n def getExtraParametersForStep(self, configurationAttributes, step):\r\n return None\r\n\r\n def getCountAuthenticationSteps(self, configurationAttributes):\r\n return 2\r\n\r\n def getPageForStep(self, configurationAttributes, step):\r\n if (step == 2):\r\n return \"/auth/u2f/login.xhtml\"\r\n\r\n return \"\"\r\n\r\n def getNextStep(self, configurationAttributes, requestParameters, step):\r\n return -1\r\n\r\n def getLogoutExternalUrl(self, configurationAttributes, requestParameters):\r\n print \"Get external logout URL call\"\r\n return None\r\n\r\n def logout(self, configurationAttributes, requestParameters):\r\n return True\r\n", @@ -713,7 +713,7 @@ "level": 60, "programmingLanguage": "PYTHON", "description": "Passport SAML authentication module", - "locationType": "LDAP", + "locationType": "db", "dn": "inum=D40C-1CA4,ou=scripts,o=gluu", "inum": "D40C-1CA4", "script": "# jans-auth is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text.\n# Copyright (c) 2019, Gluu\n#\n# Author: Jose Gonzalez\n# Author: Yuriy Movchan\n# Author: Christian Eland\n#\n\nfrom org.gluu.jsf2.service import FacesService\nfrom org.gluu.jsf2.message import FacesMessages\n\nfrom org.gluu.oxauth.model.common import User, WebKeyStorage\nfrom org.gluu.oxauth.model.configuration import AppConfiguration\nfrom org.gluu.oxauth.model.crypto import CryptoProviderFactory\nfrom org.gluu.oxauth.model.jwt import Jwt, JwtClaimName\nfrom org.gluu.oxauth.model.util import Base64Util\nfrom org.gluu.oxauth.service import AppInitializer, AuthenticationService\nfrom org.gluu.oxauth.service.common import UserService, EncryptionService\nfrom org.gluu.oxauth.model.authorize import AuthorizeRequestParam\nfrom org.gluu.oxauth.service.net import HttpService\nfrom org.gluu.oxauth.security import Identity\nfrom org.gluu.oxauth.util import ServerUtil\nfrom org.gluu.config.oxtrust import LdapOxPassportConfiguration\nfrom org.gluu.model.custom.script.type.auth import PersonAuthenticationType\nfrom org.gluu.persist import PersistenceEntryManager\nfrom org.gluu.service.cdi.util import CdiUtil\nfrom org.gluu.util import StringHelper\nfrom java.util import ArrayList, Arrays, Collections, HashSet\nfrom org.gluu.oxauth.model.exception import InvalidJwtException\nfrom javax.faces.application import FacesMessage\nfrom javax.faces.context import FacesContext\n\nimport json\nimport sys\nimport datetime\nimport base64\n\n\nclass PersonAuthentication(PersonAuthenticationType):\n def __init__(self, currentTimeMillis):\n self.currentTimeMillis = currentTimeMillis\n\n def init(self, customScript, configurationAttributes):\n\n print \"Passport. init called\"\n\n self.extensionModule = self.loadExternalModule(configurationAttributes.get(\"extension_module\"))\n extensionResult = self.extensionInit(configurationAttributes)\n if extensionResult != None:\n return extensionResult\n\n print \"Passport. init. Behaviour is inbound SAML\"\n success = self.processKeyStoreProperties(configurationAttributes)\n\n if success:\n self.providerKey = \"provider\"\n self.customAuthzParameter = self.getCustomAuthzParameter(configurationAttributes.get(\"authz_req_param_provider\"))\n self.passportDN = self.getPassportConfigDN()\n print \"Passport. init. Initialization success\"\n else:\n print \"Passport. init. Initialization failed\"\n return success\n\n\n def destroy(self, configurationAttributes):\n print \"Passport. destroy called\"\n return True\n\n\n def getApiVersion(self):\n return 11\n\n def getAuthenticationMethodClaims(self, requestParameters):\n return None\n\n def isValidAuthenticationMethod(self, usageType, configurationAttributes):\n return True\n\n\n def getAlternativeAuthenticationMethod(self, usageType, configurationAttributes):\n return None\n\n\n def authenticate(self, configurationAttributes, requestParameters, step):\n\n extensionResult = self.extensionAuthenticate(configurationAttributes, requestParameters, step)\n if extensionResult != None:\n return extensionResult\n\n print \"Passport. authenticate for step %s called\" % str(step)\n identity = CdiUtil.bean(Identity)\n\n # Loading self.registeredProviders in case passport destroyed\n if not hasattr(self,'registeredProviders'):\n print \"Passport. Fetching registered providers.\"\n self.parseProviderConfigs()\n\n if step == 1:\n\n jwt_param = None\n\n if self.isInboundFlow(identity):\n # if is idp-initiated inbound flow\n print \"Passport. authenticate for step 1. Detected idp-initiated inbound Saml flow\"\n # get request from session attributes\n jwt_param = identity.getSessionId().getSessionAttributes().get(AuthorizeRequestParam.STATE)\n print \"Passport. authenticate. step ==1. if self.isInboundFlow(identity):.\"\n print \"jwt_param = %s\" % jwt_param\n # now jwt_param != None\n\n\n\n if jwt_param == None:\n print \"Entered if jwt_param == None\"\n # gets jwt parameter \"user\" sent after authentication by passport (if exists)\n jwt_param = ServerUtil.getFirstValue(requestParameters, \"user\")\n\n\n if jwt_param != None:\n # and now that the jwt_param user exists...\n print \"Entered if jwt_param != None\"\n print \"Passport. authenticate for step 1. JWT user profile token found\"\n\n if self.isInboundFlow(identity):\n jwt_param = base64.urlsafe_b64decode(str(jwt_param+'=='))\n\n # Parse JWT and validate\n jwt = Jwt.parse(jwt_param)\n\n if not self.validSignature(jwt):\n return False\n\n if self.jwtHasExpired(jwt):\n return False\n\n # Gets user profile as string and json using the information on JWT\n (user_profile, jsonp) = self.getUserProfile(jwt)\n\n if user_profile == None:\n return False\n\n sessionAttributes = identity.getSessionId().getSessionAttributes()\n self.skipProfileUpdate = StringHelper.equalsIgnoreCase(sessionAttributes.get(\"skipPassportProfileUpdate\"), \"true\")\n\n return self.attemptAuthentication(identity, user_profile, jsonp)\n\n #See passportlogin.xhtml\n print \"-------------============------------\"\n provider = ServerUtil.getFirstValue(requestParameters, \"loginForm:provider\")\n print \"authenticate() - provider = %s\" % str(provider)\n\n\n print \"authenticate - self.registeredProviders: %s\" % str(self.registeredProviders)\n if StringHelper.isEmpty(provider):\n\n #it's username + passw auth\n print \"Passport. authenticate for step 1. Basic authentication detected\"\n logged_in = False\n\n credentials = identity.getCredentials()\n user_name = credentials.getUsername()\n user_password = credentials.getPassword()\n\n if StringHelper.isNotEmptyString(user_name) and StringHelper.isNotEmptyString(user_password):\n authenticationService = CdiUtil.bean(AuthenticationService)\n logged_in = authenticationService.authenticate(user_name, user_password)\n\n print \"Passport. authenticate for step 1. Basic authentication returned: %s\" % logged_in\n return logged_in\n\n\n\n elif provider in self.registeredProviders:\n # user selected provider\n # it's a recognized external IDP\n\n identity.setWorkingParameter(\"selectedProvider\", provider)\n print \"Passport. authenticate for step 1. Retrying step 1\"\n\n #see prepareForStep (step = 1)\n return True\n\n if step == 2:\n mail = ServerUtil.getFirstValue(requestParameters, \"loginForm:email\")\n jsonp = identity.getWorkingParameter(\"passport_user_profile\")\n\n if mail == None:\n self.setMessageError(FacesMessage.SEVERITY_ERROR, \"Email was missing in user profile\")\n elif jsonp != None:\n # Completion of profile takes place\n user_profile = json.loads(jsonp)\n user_profile[\"mail\"] = [ mail ]\n\n return self.attemptAuthentication(identity, user_profile, jsonp)\n\n print \"Passport. authenticate for step 2. Failed: expected mail value in HTTP request and json profile in session\"\n return False\n\n\n def prepareForStep(self, configurationAttributes, requestParameters, step):\n\n extensionResult = self.extensionPrepareForStep(configurationAttributes, requestParameters, step)\n if extensionResult != None:\n return extensionResult\n\n print \"Passport. prepareForStep called %s\" % str(step)\n identity = CdiUtil.bean(Identity)\n\n if step == 1:\n #re-read the strategies config (for instance to know which strategies have enabled the email account linking)\n self.parseProviderConfigs()\n identity.setWorkingParameter(\"externalProviders\", json.dumps(self.registeredProviders))\n\n providerParam = self.customAuthzParameter\n url = None\n\n sessionAttributes = identity.getSessionId().getSessionAttributes()\n self.skipProfileUpdate = StringHelper.equalsIgnoreCase(sessionAttributes.get(\"skipPassportProfileUpdate\"), \"true\")\n\n #this param could have been set previously in authenticate step if current step is being retried\n provider = identity.getWorkingParameter(\"selectedProvider\")\n print \"prepareForStep %s - provider = %s\" % (str(step), str(provider))\n\n # if there is a selectedProvider\n if provider != None:\n\n # get the redirect URL to use at facesService.redirectToExternalURL() that sends /passport/auth//\n url = self.getPassportRedirectUrl(provider)\n print \"prepareForStep %s - url = %s\" % (str(step), url)\n\n # sets selectedProvider back to None\n identity.setWorkingParameter(\"selectedProvider\", None)\n\n # if there is customAuthzParameter\n elif providerParam != None:\n\n\n # get it from sessionAtributes\n paramValue = sessionAttributes.get(providerParam)\n\n #if exists\n if paramValue != None:\n print \"Passport. prepareForStep. Found value in custom param of authorization request: %s\" % paramValue\n provider = self.getProviderFromJson(paramValue)\n\n if provider == None:\n print \"Passport. prepareForStep. A provider value could not be extracted from custom authorization request parameter\"\n elif not provider in self.registeredProviders:\n print \"Passport. prepareForStep. Provider '%s' not part of known configured IDPs/OPs\" % provider\n else:\n url = self.getPassportRedirectUrl(provider)\n\n\n # if no provider selected yet...\n if url == None:\n print \"Passport. prepareForStep. A page to manually select an identity provider will be shown\"\n\n # else already got the /passport/auth// url...\n else:\n\n facesService = CdiUtil.bean(FacesService)\n\n # redirects to Passport getRedirectURL - sends browser to IDP.\n print \"Passport. Redirecting to external url: %s\" + url\n\n facesService.redirectToExternalURL(url)\n\n return True\n\n\n def getExtraParametersForStep(self, configurationAttributes, step):\n print \"Passport. getExtraParametersForStep called for step %s\" % str(step)\n if step == 1:\n return Arrays.asList(\"selectedProvider\", \"externalProviders\")\n elif step == 2:\n return Arrays.asList(\"passport_user_profile\")\n return None\n\n\n def getCountAuthenticationSteps(self, configurationAttributes):\n print \"Passport. getCountAuthenticationSteps called\"\n identity = CdiUtil.bean(Identity)\n if identity.getWorkingParameter(\"passport_user_profile\") != None:\n return 2\n return 1\n\n\n def getPageForStep(self, configurationAttributes, step):\n print \"Passport. getPageForStep called\"\n\n extensionResult = self.extensionGetPageForStep(configurationAttributes, step)\n if extensionResult != None:\n return extensionResult\n\n if step == 1:\n identity = CdiUtil.bean(Identity)\n print \"Passport. getPageForStep. Entered if step ==1\"\n if self.isInboundFlow(identity):\n print \"Passport. getPageForStep for step 1. Detected inbound Saml flow\"\n return \"/postlogin.xhtml\"\n print \"Passport. getPageForStep 1. NormalFlow, returning passportlogin.xhtml\"\n return \"/auth/passport/passportlogin.xhtml\"\n\n return \"/auth/passport/passportpostlogin.xhtml\"\n\n\n def getNextStep(self, configurationAttributes, requestParameters, step):\n if step == 1:\n identity = CdiUtil.bean(Identity)\n provider = identity.getWorkingParameter(\"selectedProvider\")\n if provider != None:\n return 1\n\n return -1\n\n\n def logout(self, configurationAttributes, requestParameters):\n return True\n\n# Extension module related functions\n\n def extensionInit(self, configurationAttributes):\n\n if self.extensionModule == None:\n return None\n return self.extensionModule.init(configurationAttributes)\n\n\n def extensionAuthenticate(self, configurationAttributes, requestParameters, step):\n\n if self.extensionModule == None:\n return None\n return self.extensionModule.authenticate(configurationAttributes, requestParameters, step)\n\n\n def extensionPrepareForStep(self, configurationAttributes, requestParameters, step):\n\n if self.extensionModule == None:\n return None\n return self.extensionModule.prepareForStep(configurationAttributes, requestParameters, step)\n\n\n def extensionGetPageForStep(self, configurationAttributes, step):\n\n if self.extensionModule == None:\n return None\n return self.extensionModule.getPageForStep(configurationAttributes, step)\n\n# Initalization routines\n\n def loadExternalModule(self, simpleCustProperty):\n\n if simpleCustProperty != None:\n print \"Passport. loadExternalModule. Loading passport extension module...\"\n moduleName = simpleCustProperty.getValue2()\n try:\n module = __import__(moduleName)\n return module\n except:\n print \"Passport. loadExternalModule. Failed to load module %s\" % moduleName\n print \"Exception: \", sys.exc_info()[1]\n print \"Passport. loadExternalModule. Flow will be driven entirely by routines of main passport script\"\n return None\n\n\n def processKeyStoreProperties(self, attrs):\n file = attrs.get(\"key_store_file\")\n password = attrs.get(\"key_store_password\")\n\n if file != None and password != None:\n file = file.getValue2()\n password = password.getValue2()\n\n if StringHelper.isNotEmpty(file) and StringHelper.isNotEmpty(password):\n self.keyStoreFile = file\n self.keyStorePassword = password\n return True\n\n print \"Passport. readKeyStoreProperties. Properties key_store_file or key_store_password not found or empty\"\n return False\n\n\n def getCustomAuthzParameter(self, simpleCustProperty):\n\n customAuthzParameter = None\n if simpleCustProperty != None:\n prop = simpleCustProperty.getValue2()\n if StringHelper.isNotEmpty(prop):\n customAuthzParameter = prop\n\n if customAuthzParameter == None:\n print \"Passport. getCustomAuthzParameter. No custom param for OIDC authz request in script properties\"\n print \"Passport. getCustomAuthzParameter. Passport flow cannot be initiated by doing an OpenID connect authorization request\"\n else:\n print \"Passport. getCustomAuthzParameter. Custom param for OIDC authz request in script properties: %s\" % customAuthzParameter\n\n return customAuthzParameter\n\n# Configuration parsing\n\n def getPassportConfigDN(self):\n\n f = open('/etc/gluu/conf/gluu.properties', 'r')\n for line in f:\n prop = line.split(\"=\")\n if prop[0] == \"oxpassport_ConfigurationEntryDN\":\n prop.pop(0)\n break\n\n f.close()\n return \"=\".join(prop).strip()\n\n\n def parseAllProviders(self):\n\n registeredProviders = {}\n print \"Passport. parseAllProviders. Adding providers\"\n entryManager = CdiUtil.bean(PersistenceEntryManager)\n\n config = LdapOxPassportConfiguration()\n config = entryManager.find(config.getClass(), self.passportDN).getPassportConfiguration()\n config = config.getProviders() if config != None else config\n\n if config != None and len(config) > 0:\n for prvdetails in config:\n if prvdetails.isEnabled():\n registeredProviders[prvdetails.getId()] = {\n \"emailLinkingSafe\": prvdetails.isEmailLinkingSafe(),\n \"requestForEmail\" : prvdetails.isRequestForEmail(),\n \"logo_img\": prvdetails.getLogoImg(),\n \"displayName\": prvdetails.getDisplayName(),\n \"type\": prvdetails.getType()\n }\n\n return registeredProviders\n\n\n def parseProviderConfigs(self):\n\n registeredProviders = {}\n try:\n registeredProviders = self.parseAllProviders()\n toRemove = []\n\n for provider in registeredProviders:\n if registeredProviders[provider][\"type\"] != \"saml\":\n toRemove.append(provider)\n else:\n registeredProviders[provider][\"saml\"] = True\n\n for provider in toRemove:\n registeredProviders.pop(provider)\n\n\n if len(registeredProviders.keys()) > 0:\n print \"Passport. parseProviderConfigs. Configured providers:\", registeredProviders\n else:\n print \"Passport. parseProviderConfigs. No providers registered yet\"\n except:\n print \"Passport. parseProviderConfigs. An error occurred while building the list of supported authentication providers\", sys.exc_info()[1]\n\n\n print \"parseProviderConfigs - registeredProviders = %s\" % str(registeredProviders)\n self.registeredProviders = registeredProviders\n print \"parseProviderConfigs - self.registeredProviders = %s\" % str(self.registeredProviders)\n\n# Auxiliary routines\n\n def getProviderFromJson(self, providerJson):\n\n provider = None\n try:\n obj = json.loads(Base64Util.base64urldecodeToString(providerJson))\n provider = obj[self.providerKey]\n except:\n print \"Passport. getProviderFromJson. Could not parse provided Json string. Returning None\"\n\n return provider\n\n\n def getPassportRedirectUrl(self, provider):\n\n # provider is assumed to exist in self.registeredProviders\n url = None\n try:\n facesContext = CdiUtil.bean(FacesContext)\n tokenEndpoint = \"https://%s/passport/token\" % facesContext.getExternalContext().getRequest().getServerName()\n\n httpService = CdiUtil.bean(HttpService)\n httpclient = httpService.getHttpsClient()\n\n print \"Passport. getPassportRedirectUrl. Obtaining token from passport at %s\" % tokenEndpoint\n resultResponse = httpService.executeGet(httpclient, tokenEndpoint, Collections.singletonMap(\"Accept\", \"text/json\"))\n httpResponse = resultResponse.getHttpResponse()\n\n bytes = httpService.getResponseContent(httpResponse)\n\n response = httpService.convertEntityToString(bytes)\n print \"Passport. getPassportRedirectUrl. Response was %s\" % httpResponse.getStatusLine().getStatusCode()\n\n tokenObj = json.loads(response)\n\n url = \"/passport/auth/%s/%s\" % (provider, tokenObj[\"token_\"])\n\n except:\n print \"Passport. getPassportRedirectUrl. Error building redirect URL: \", sys.exc_info()[1]\n\n return url\n\n\n def validSignature(self, jwt):\n\n print \"Passport. validSignature. Checking JWT token signature\"\n valid = False\n\n try:\n\n appConfiguration = AppConfiguration()\n appConfiguration.setWebKeysStorage(WebKeyStorage.KEYSTORE)\n appConfiguration.setKeyStoreFile(self.keyStoreFile)\n appConfiguration.setKeyStoreSecret(self.keyStorePassword)\n appConfiguration.setKeyRegenerationEnabled(False)\n\n cryptoProvider = CryptoProviderFactory.getCryptoProvider(appConfiguration)\n\n\n alg_string = str(jwt.getHeader().getSignatureAlgorithm())\n signature_string = str(jwt.getEncodedSignature())\n\n if alg_string == \"none\" or alg_string == \"None\" or alg_string == \"NoNe\" or alg_string == \"nONE\" or alg_string == \"NONE\" or alg_string == \"NonE\" or alg_string == \"nOnE\":\n # blocks none attack\n\n print \"WARNING: JWT Signature algorithm is none\"\n valid = False\n\n elif alg_string != \"RS512\":\n # blocks anything that's not RS512\n\n print \"WARNING: JWT Signature algorithm is NOT RS512\"\n valid = False\n\n elif signature_string == \"\" :\n # blocks empty signature string\n print \"WARNING: JWT Signature not sent\"\n valid = False\n\n else:\n\n # class extends AbstractCryptoProvider\n ''' on version 4.2 .getAlgorithm() method was renamed to .getSignatureAlgorithm()\n for older versions:\n valid = cryptoProvider.verifySignature(jwt.getSigningInput(), jwt.getEncodedSignature(), jwt.getHeader().getKeyId(),\n None, None, jwt.getHeader().getAlgorithm())\n '''\n\n # working on 4.2:\n valid = cryptoProvider.verifySignature(jwt.getSigningInput(), jwt.getEncodedSignature(), jwt.getHeader().getKeyId(),\n None, None, jwt.getHeader().getSignatureAlgorithm())\n\n except:\n print \"Exception: \", sys.exc_info()[1]\n\n print \"Passport. validSignature. Validation result was %s\" % valid\n\n return valid\n\n\n def jwtHasExpired(self, jwt):\n # Check if jwt has expired\n jwt_claims = jwt.getClaims()\n try:\n exp_date = jwt_claims.getClaimAsDate(JwtClaimName.EXPIRATION_TIME)\n hasExpired = exp_date < datetime.datetime.now()\n except:\n print \"Exception: The JWT does not have '%s' attribute\" % JwtClaimName.EXPIRATION_TIME\n return False\n\n return hasExpired\n\n\n def getUserProfile(self, jwt):\n\n # getClaims method located at org.gluu.oxauth.model.token.JsonWebResponse.java as a org.gluu.oxauth.model.jwt.JwtClaims object\n jwt_claims = jwt.getClaims()\n\n user_profile_json = None\n\n try:\n # public String getClaimAsString(String key)\n user_profile_json = CdiUtil.bean(EncryptionService).decrypt(jwt_claims.getClaimAsString(\"data\"))\n\n user_profile = json.loads(user_profile_json)\n except:\n print \"Passport. getUserProfile. Problem obtaining user profile json representation\"\n\n return (user_profile, user_profile_json)\n\n\n def attemptAuthentication(self, identity, user_profile, user_profile_json):\n\n print \"Entered attemptAuthentication...\"\n uidKey = \"uid\"\n if not self.checkRequiredAttributes(user_profile, [uidKey, self.providerKey]):\n return False\n\n provider = user_profile[self.providerKey]\n print \"user_profile[self.providerKey] = %s\" % str(user_profile[self.providerKey])\n if not provider in self.registeredProviders:\n print \"Entered if note provider in self.registeredProviers:\"\n print \"Passport. attemptAuthentication. Identity Provider %s not recognized\" % provider\n return False\n\n print \"attemptAuthentication. user_profile = %s\" % user_profile\n print \"user_profile[uidKey] = %s\" % user_profile[uidKey]\n uid = user_profile[uidKey][0]\n print \"attemptAuthentication - uid = %s\" % uid\n externalUid = \"passport-%s:%s:%s\" % (\"saml\", provider, uid)\n\n userService = CdiUtil.bean(UserService)\n userByUid = self.getUserByExternalUid(uid, provider, userService)\n\n email = None\n if \"mail\" in user_profile:\n email = user_profile[\"mail\"]\n if len(email) == 0:\n email = None\n else:\n email = email[0]\n user_profile[\"mail\"] = [ email ]\n\n if email == None and self.registeredProviders[provider][\"requestForEmail\"]:\n print \"Passport. attemptAuthentication. Email was not received\"\n\n if userByUid != None:\n # This avoids asking for the email over every login attempt\n email = userByUid.getAttribute(\"mail\")\n if email != None:\n print \"Passport. attemptAuthentication. Filling missing email value with %s\" % email\n user_profile[\"mail\"] = [ email ]\n\n if email == None:\n # Store user profile in session and abort this routine\n identity.setWorkingParameter(\"passport_user_profile\", user_profile_json)\n return True\n\n userByMail = None if email == None else userService.getUserByAttribute(\"mail\", email)\n\n # Determine if we should add entry, update existing, or deny access\n doUpdate = False\n doAdd = False\n if userByUid != None:\n print \"User with externalUid '%s' already exists\" % externalUid\n if userByMail == None:\n doUpdate = True\n else:\n if userByMail.getUserId() == userByUid.getUserId():\n doUpdate = True\n else:\n print \"Users with externalUid '%s' and mail '%s' are different. Access will be denied. Impersonation attempt?\" % (externalUid, email)\n self.setMessageError(FacesMessage.SEVERITY_ERROR, \"Email value corresponds to an already existing provisioned account\")\n else:\n if userByMail == None:\n doAdd = True\n elif self.registeredProviders[provider][\"emailLinkingSafe\"]:\n\n tmpList = userByMail.getAttributeValues(\"oxExternalUid\")\n tmpList = ArrayList() if tmpList == None else ArrayList(tmpList)\n tmpList.add(externalUid)\n userByMail.setAttribute(\"oxExternalUid\", tmpList)\n\n userByUid = userByMail\n print \"External user supplying mail %s will be linked to existing account '%s'\" % (email, userByMail.getUserId())\n doUpdate = True\n else:\n print \"An attempt to supply an email of an existing user was made. Turn on 'emailLinkingSafe' if you want to enable linking\"\n self.setMessageError(FacesMessage.SEVERITY_ERROR, \"Email value corresponds to an already existing account. If you already have a username and password use those instead of an external authentication site to get access.\")\n\n username = None\n try:\n if doUpdate:\n username = userByUid.getUserId()\n print \"Passport. attemptAuthentication. Updating user %s\" % username\n self.updateUser(userByUid, user_profile, userService)\n elif doAdd:\n print \"Passport. attemptAuthentication. Creating user %s\" % externalUid\n newUser = self.addUser(externalUid, user_profile, userService)\n username = newUser.getUserId()\n except:\n print \"Exception: \", sys.exc_info()[1]\n print \"Passport. attemptAuthentication. Authentication failed\"\n return False\n\n if username == None:\n print \"Passport. attemptAuthentication. Authentication attempt was rejected\"\n return False\n else:\n logged_in = CdiUtil.bean(AuthenticationService).authenticate(username)\n print \"Passport. attemptAuthentication. Authentication for %s returned %s\" % (username, logged_in)\n return logged_in\n\n\n def getUserByExternalUid(self, uid, provider, userService):\n newFormat = \"passport-%s:%s:%s\" % (\"saml\", provider, uid)\n user = userService.getUserByAttribute(\"oxExternalUid\", newFormat)\n\n if user == None:\n oldFormat = \"passport-%s:%s\" % (\"saml\", uid)\n user = userService.getUserByAttribute(\"oxExternalUid\", oldFormat)\n\n if user != None:\n # Migrate to newer format\n list = HashSet(user.getAttributeValues(\"oxExternalUid\"))\n list.remove(oldFormat)\n list.add(newFormat)\n user.setAttribute(\"oxExternalUid\", ArrayList(list))\n print \"Migrating user's oxExternalUid to newer format 'passport-saml:provider:uid'\"\n userService.updateUser(user)\n\n return user\n\n\n def setMessageError(self, severity, msg):\n facesMessages = CdiUtil.bean(FacesMessages)\n facesMessages.setKeepMessages()\n facesMessages.clear()\n facesMessages.add(severity, msg)\n\n\n def checkRequiredAttributes(self, profile, attrs):\n\n for attr in attrs:\n if (not attr in profile) or len(profile[attr]) == 0:\n print \"Passport. checkRequiredAttributes. Attribute '%s' is missing in profile\" % attr\n return False\n return True\n\n\n def addUser(self, externalUid, profile, userService):\n print \"Passport. Entered addUser().\"\n print \"Passport. addUser. externalUid = %s\" % externalUid\n print \"Passport. addUser. profile = %s\" % profile\n newUser = User()\n #Fill user attrs\n newUser.setAttribute(\"oxExternalUid\", externalUid)\n self.fillUser(newUser, profile)\n newUser = userService.addUser(newUser, True)\n return newUser\n\n\n def updateUser(self, foundUser, profile, userService):\n # when this is false, there might still some updates taking place (e.g. not related to profile attrs released by external provider)\n if (not self.skipProfileUpdate):\n self.fillUser(foundUser, profile)\n userService.updateUser(foundUser)\n\n\n def fillUser(self, foundUser, profile):\n print\n print \"Passport. Entered fillUser().\"\n print \"Passport. fillUser. foundUser = %s\" % foundUser\n print \"Passport. fillUser. profile = %s\" % profile\n for attr in profile:\n # \"provider\" is disregarded if part of mapping\n if attr != self.providerKey:\n values = profile[attr]\n print \"%s = %s\" % (attr, values)\n foundUser.setAttribute(attr, values)\n\n if attr == \"mail\":\n print \"Passport. fillUser. entered if attr == mail\"\n oxtrustMails = []\n for mail in values:\n oxtrustMails.append('{\"value\":\"%s\",\"primary\":false}' % mail)\n foundUser.setAttribute(\"oxTrustEmail\", oxtrustMails)\n\n# IDP-initiated flow routines\n\n def isInboundFlow(self, identity):\n print \"passport. entered isInboundFlow\"\n\n sessionId = identity.getSessionId()\n print \"passport. isInboundFlow. sessionId = %s\" % sessionId\n if sessionId == None:\n print \"passport. isInboundFlow. sessionId not found yet...\"\n # Detect mode if there is no session yet. It's needed for getPageForStep method\n facesContext = CdiUtil.bean(FacesContext)\n requestParameters = facesContext.getExternalContext().getRequestParameterMap()\n print \"passport. isInboundFlow. requestParameters = %s\" % requestParameters\n\n authz_state = requestParameters.get(AuthorizeRequestParam.STATE)\n print \"passport. isInboundFlow. authz_state = %s\" % authz_state\n else:\n authz_state = identity.getSessionId().getSessionAttributes().get(AuthorizeRequestParam.STATE)\n\n print \"passport. IsInboundFlow. authz_state = %s\" % authz_state\n\n # the replace above is workaround due a problem reported\n # on issue: https://github.com/GluuFederation/gluu-passport/issues/95\n # TODO: Remove after fixed on JSF side\n\n b64url_decoded_auth_state = base64.urlsafe_b64decode(str(authz_state+'=='))\n\n # print \"passport. IsInboundFlow. b64url_decoded_auth_state = %s\" % str(b64url_decoded_auth_state)\n print \"passport. IsInboundFlow. self.isInboundJwt() = %s\" % str(self.isInboundJwt(b64url_decoded_auth_state))\n if self.isInboundJwt(b64url_decoded_auth_state):\n return True\n\n return False\n\n\n def isInboundJwt(self, value):\n if value == None:\n return False\n\n try:\n\n print(\"passport.isInboundJwt. value = %s\" % value)\n # value = value.replace(\"_\", \".\")\n # print(\"passport.isInboundJwt. value = %s\" % value)\n\n jwt = Jwt.parse(value)\n print \"passport.isInboundJwt. jwt = %s\" % jwt\n\n # user_profile_json = jwt.getClaims().getClaimAsString(\"data\")\n\n user_profile_json = CdiUtil.bean(EncryptionService).decrypt(jwt.getClaims().getClaimAsString(\"data\"))\n print \"passport.isInboundJwt. user_profile_json = %s\" % user_profile_json\n if StringHelper.isEmpty(user_profile_json):\n return False\n except InvalidJwtException:\n return False\n\n except:\n print(\"Unexpected error:\", sys.exc_info()[0])\n return False\n\n return True\n\n def getLogoutExternalUrl(self, configurationAttributes, requestParameters):\n print \"Get external logout URL call\"\n return None\n", @@ -751,7 +751,7 @@ "level": 60, "programmingLanguage": "PYTHON", "description": "Super Gluu authentication module", - "locationType": "LDAP", + "locationType": "db", "dn": "inum=92F0-BF9E,ou=scripts,o=gluu", "inum": "92F0-BF9E", "script": "# jans-auth is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text.\n# Copyright (c) 2016, Gluu\n#\n# Author: Yuriy Movchan\n#\n\nfrom com.google.android.gcm.server import Sender, Message\nfrom com.notnoop.apns import APNS\nfrom java.util import Arrays\nfrom org.apache.http.params import CoreConnectionPNames\nfrom org.gluu.service.cdi.util import CdiUtil\nfrom org.gluu.oxauth.security import Identity\nfrom org.gluu.model.custom.script.type.auth import PersonAuthenticationType\nfrom org.gluu.oxauth.model.config import ConfigurationFactory\nfrom org.gluu.oxauth.service import AuthenticationService, SessionIdService\nfrom org.gluu.oxauth.service.fido.u2f import DeviceRegistrationService\nfrom org.gluu.oxauth.service.net import HttpService\nfrom org.gluu.oxauth.util import ServerUtil\nfrom org.gluu.util import StringHelper\nfrom org.gluu.oxauth.service.common import EncryptionService, UserService\nfrom org.gluu.service import MailService\nfrom org.gluu.oxauth.service.push.sns import PushPlatform, PushSnsService \nfrom org.gluu.oxnotify.client import NotifyClientFactory \nfrom java.util import Arrays, HashMap, IdentityHashMap, Date\nfrom java.time import ZonedDateTime\nfrom java.time.format import DateTimeFormatter\n\ntry:\n from org.gluu.oxd.license.client.js import Product\n from org.gluu.oxd.license.validator import LicenseValidator\n has_license_api = True\nexcept ImportError:\n print \"Super-Gluu. Load. Failed to load licensing API\"\n has_license_api = False\n\nimport datetime\nimport urllib\n\nimport sys\nimport json\n\nclass PersonAuthentication(PersonAuthenticationType):\n def __init__(self, currentTimeMillis):\n self.currentTimeMillis = currentTimeMillis\n\n def init(self, customScript, configurationAttributes):\n print \"Super-Gluu. Initialization\"\n\n if not configurationAttributes.containsKey(\"authentication_mode\"):\n print \"Super-Gluu. Initialization. Property authentication_mode is mandatory\"\n return False\n\n self.applicationId = None\n if configurationAttributes.containsKey(\"application_id\"):\n self.applicationId = configurationAttributes.get(\"application_id\").getValue2()\n\n self.registrationUri = None\n if configurationAttributes.containsKey(\"registration_uri\"):\n self.registrationUri = configurationAttributes.get(\"registration_uri\").getValue2()\n\n authentication_mode = configurationAttributes.get(\"authentication_mode\").getValue2()\n if StringHelper.isEmpty(authentication_mode):\n print \"Super-Gluu. Initialization. Failed to determine authentication_mode. authentication_mode configuration parameter is empty\"\n return False\n \n self.oneStep = StringHelper.equalsIgnoreCase(authentication_mode, \"one_step\")\n self.twoStep = StringHelper.equalsIgnoreCase(authentication_mode, \"two_step\")\n\n if not (self.oneStep or self.twoStep):\n print \"Super-Gluu. Initialization. Valid authentication_mode values are one_step and two_step\"\n return False\n \n self.enabledPushNotifications = self.initPushNotificationService(configurationAttributes)\n\n self.androidUrl = None\n if configurationAttributes.containsKey(\"supergluu_android_download_url\"):\n self.androidUrl = configurationAttributes.get(\"supergluu_android_download_url\").getValue2()\n\n self.IOSUrl = None\n if configurationAttributes.containsKey(\"supergluu_ios_download_url\"):\n self.IOSUrl = configurationAttributes.get(\"supergluu_ios_download_url\").getValue2()\n\n self.customLabel = None\n if configurationAttributes.containsKey(\"label\"):\n self.customLabel = configurationAttributes.get(\"label\").getValue2()\n\n self.customQrOptions = {}\n if configurationAttributes.containsKey(\"qr_options\"):\n self.customQrOptions = configurationAttributes.get(\"qr_options\").getValue2()\n\n self.use_super_gluu_group = False\n if configurationAttributes.containsKey(\"super_gluu_group\"):\n self.super_gluu_group = configurationAttributes.get(\"super_gluu_group\").getValue2()\n self.use_super_gluu_group = True\n print \"Super-Gluu. Initialization. Using super_gluu only if user belong to group: %s\" % self.super_gluu_group\n\n self.use_audit_group = False\n if configurationAttributes.containsKey(\"audit_group\"):\n self.audit_group = configurationAttributes.get(\"audit_group\").getValue2()\n\n if (not configurationAttributes.containsKey(\"audit_group_email\")):\n print \"Super-Gluu. Initialization. Property audit_group_email is not specified\"\n return False\n\n self.audit_email = configurationAttributes.get(\"audit_group_email\").getValue2()\n self.use_audit_group = True\n\n print \"Super-Gluu. Initialization. Using audit group: %s\" % self.audit_group\n \n if self.use_super_gluu_group or self.use_audit_group:\n if not configurationAttributes.containsKey(\"audit_attribute\"):\n print \"Super-Gluu. Initialization. Property audit_attribute is not specified\"\n return False\n else:\n self.audit_attribute = configurationAttributes.get(\"audit_attribute\").getValue2()\n\n self.valid_license = False\n # Removing or altering this block validation is against the terms of the license. \n if has_license_api and configurationAttributes.containsKey(\"license_file\"):\n license_file = configurationAttributes.get(\"license_file\").getValue2()\n\n # Load license from file\n f = open(license_file, 'r')\n try:\n license = json.loads(f.read())\n except:\n print \"Super-Gluu. Initialization. Failed to load license from file: %s\" % license_file\n return False\n finally:\n f.close()\n \n # Validate license\n try:\n self.license_content = LicenseValidator.validate(license[\"public_key\"], license[\"public_password\"], license[\"license_password\"], license[\"license\"],\n Product.SUPER_GLUU, Date())\n self.valid_license = self.license_content.isValid()\n except:\n print \"Super-Gluu. Initialization. Failed to validate license. Exception: \", sys.exc_info()[1]\n return False\n\n print \"Super-Gluu. Initialization. License status: '%s'. License metadata: '%s'\" % (self.valid_license, self.license_content.getMetadata())\n\n print \"Super-Gluu. Initialized successfully. oneStep: '%s', twoStep: '%s', pushNotifications: '%s', customLabel: '%s'\" % (self.oneStep, self.twoStep, self.enabledPushNotifications, self.customLabel)\n\n return True \n\n def destroy(self, configurationAttributes):\n print \"Super-Gluu. Destroy\"\n\n self.pushAndroidService = None\n self.pushAppleService = None\n\n print \"Super-Gluu. Destroyed successfully\"\n return True\n\n def getApiVersion(self):\n return 11\n \n def getAuthenticationMethodClaims(self, requestParameters):\n return None\n \n def isValidAuthenticationMethod(self, usageType, configurationAttributes):\n return True\n\n def getAlternativeAuthenticationMethod(self, usageType, configurationAttributes):\n return None\n\n def authenticate(self, configurationAttributes, requestParameters, step):\n authenticationService = CdiUtil.bean(AuthenticationService)\n\n identity = CdiUtil.bean(Identity)\n credentials = identity.getCredentials()\n\n session_attributes = identity.getSessionId().getSessionAttributes()\n\n client_redirect_uri = self.getApplicationUri(session_attributes)\n if client_redirect_uri == None:\n print \"Super-Gluu. Authenticate. redirect_uri is not set\"\n return False\n\n self.setRequestScopedParameters(identity, step)\n\n # Validate form result code and initialize QR code regeneration if needed (retry_current_step = True)\n identity.setWorkingParameter(\"retry_current_step\", False)\n form_auth_result = ServerUtil.getFirstValue(requestParameters, \"auth_result\")\n if StringHelper.isNotEmpty(form_auth_result):\n print \"Super-Gluu. Authenticate for step %s. Get auth_result: '%s'\" % (step, form_auth_result)\n if form_auth_result in ['error']:\n return False\n\n if form_auth_result in ['timeout']:\n if ((step == 1) and self.oneStep) or ((step == 2) and self.twoStep): \n print \"Super-Gluu. Authenticate for step %s. Reinitializing current step\" % step\n identity.setWorkingParameter(\"retry_current_step\", True)\n return False\n\n userService = CdiUtil.bean(UserService)\n deviceRegistrationService = CdiUtil.bean(DeviceRegistrationService)\n if step == 1:\n print \"Super-Gluu. Authenticate for step 1\"\n\n user_name = credentials.getUsername()\n if self.oneStep:\n session_device_status = self.getSessionDeviceStatus(session_attributes, user_name)\n if session_device_status == None:\n return False\n\n u2f_device_id = session_device_status['device_id']\n\n validation_result = self.validateSessionDeviceStatus(client_redirect_uri, session_device_status)\n if validation_result:\n print \"Super-Gluu. Authenticate for step 1. User successfully authenticated with u2f_device '%s'\" % u2f_device_id\n else:\n return False\n \n if not session_device_status['one_step']:\n print \"Super-Gluu. Authenticate for step 1. u2f_device '%s' is not one step device\" % u2f_device_id\n return False\n \n # There are two steps only in enrollment mode\n if session_device_status['enroll']:\n return validation_result\n\n identity.setWorkingParameter(\"super_gluu_count_login_steps\", 1)\n\n user_inum = session_device_status['user_inum']\n\n u2f_device = deviceRegistrationService.findUserDeviceRegistration(user_inum, u2f_device_id, \"oxId\")\n if u2f_device == None:\n print \"Super-Gluu. Authenticate for step 1. Failed to load u2f_device '%s'\" % u2f_device_id\n return False\n\n logged_in = authenticationService.authenticate(user_name)\n if not logged_in:\n print \"Super-Gluu. Authenticate for step 1. Failed to authenticate user '%s'\" % user_name\n return False\n\n print \"Super-Gluu. Authenticate for step 1. User '%s' successfully authenticated with u2f_device '%s'\" % (user_name, u2f_device_id)\n \n return True\n elif self.twoStep:\n authenticated_user = self.processBasicAuthentication(credentials)\n if authenticated_user == None:\n return False\n\n if (self.use_super_gluu_group):\n print \"Super-Gluu. Authenticate for step 1. Checking if user belong to super_gluu group\"\n is_member_super_gluu_group = self.isUserMemberOfGroup(authenticated_user, self.audit_attribute, self.super_gluu_group)\n if (is_member_super_gluu_group):\n print \"Super-Gluu. Authenticate for step 1. User '%s' member of super_gluu group\" % authenticated_user.getUserId()\n super_gluu_count_login_steps = 2\n else:\n if self.use_audit_group:\n self.processAuditGroup(authenticated_user, self.audit_attribute, self.audit_group)\n super_gluu_count_login_steps = 1\n \n identity.setWorkingParameter(\"super_gluu_count_login_steps\", super_gluu_count_login_steps)\n \n if super_gluu_count_login_steps == 1:\n return True\n \n auth_method = 'authenticate'\n enrollment_mode = ServerUtil.getFirstValue(requestParameters, \"loginForm:registerButton\")\n if StringHelper.isNotEmpty(enrollment_mode):\n auth_method = 'enroll'\n \n if auth_method == 'authenticate':\n user_inum = userService.getUserInum(authenticated_user)\n u2f_devices_list = deviceRegistrationService.findUserDeviceRegistrations(user_inum, client_redirect_uri, \"oxId\")\n if u2f_devices_list.size() == 0:\n auth_method = 'enroll'\n print \"Super-Gluu. Authenticate for step 1. There is no U2F '%s' user devices associated with application '%s'. Changing auth_method to '%s'\" % (user_name, client_redirect_uri, auth_method)\n \n print \"Super-Gluu. Authenticate for step 1. auth_method: '%s'\" % auth_method\n \n identity.setWorkingParameter(\"super_gluu_auth_method\", auth_method)\n\n return True\n\n return False\n elif step == 2:\n print \"Super-Gluu. Authenticate for step 2\"\n\n user = authenticationService.getAuthenticatedUser()\n if (user == None):\n print \"Super-Gluu. Authenticate for step 2. Failed to determine user name\"\n return False\n user_name = user.getUserId()\n\n session_attributes = identity.getSessionId().getSessionAttributes()\n\n session_device_status = self.getSessionDeviceStatus(session_attributes, user_name)\n if session_device_status == None:\n return False\n\n u2f_device_id = session_device_status['device_id']\n\n # There are two steps only in enrollment mode\n if self.oneStep and session_device_status['enroll']:\n authenticated_user = self.processBasicAuthentication(credentials)\n if authenticated_user == None:\n return False\n\n user_inum = userService.getUserInum(authenticated_user)\n \n attach_result = deviceRegistrationService.attachUserDeviceRegistration(user_inum, u2f_device_id)\n\n print \"Super-Gluu. Authenticate for step 2. Result after attaching u2f_device '%s' to user '%s': '%s'\" % (u2f_device_id, user_name, attach_result) \n\n return attach_result\n elif self.twoStep:\n if user_name == None:\n print \"Super-Gluu. Authenticate for step 2. Failed to determine user name\"\n return False\n\n validation_result = self.validateSessionDeviceStatus(client_redirect_uri, session_device_status, user_name)\n if validation_result:\n print \"Super-Gluu. Authenticate for step 2. User '%s' successfully authenticated with u2f_device '%s'\" % (user_name, u2f_device_id)\n else:\n return False\n \n super_gluu_request = json.loads(session_device_status['super_gluu_request'])\n auth_method = super_gluu_request['method']\n if auth_method in ['enroll', 'authenticate']:\n if validation_result and self.use_audit_group:\n user = authenticationService.getAuthenticatedUser()\n self.processAuditGroup(user, self.audit_attribute, self.audit_group)\n\n return validation_result\n\n print \"Super-Gluu. Authenticate for step 2. U2F auth_method is invalid\"\n\n return False\n else:\n return False\n\n def prepareForStep(self, configurationAttributes, requestParameters, step):\n identity = CdiUtil.bean(Identity)\n session_attributes = identity.getSessionId().getSessionAttributes()\n\n client_redirect_uri = self.getApplicationUri(session_attributes)\n if client_redirect_uri == None:\n print \"Super-Gluu. Prepare for step. redirect_uri is not set\"\n return False\n\n self.setRequestScopedParameters(identity, step)\n\n if step == 1:\n print \"Super-Gluu. Prepare for step 1\"\n if self.oneStep:\n session = CdiUtil.bean(SessionIdService).getSessionId()\n if session == None:\n print \"Super-Gluu. Prepare for step 2. Failed to determine session_id\"\n return False\n\n issuer = CdiUtil.bean(ConfigurationFactory).getConfiguration().getIssuer()\n super_gluu_request_dictionary = {'app': client_redirect_uri,\n 'issuer': issuer,\n 'state': session.getId(),\n 'licensed': self.valid_license,\n 'created': DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(ZonedDateTime.now().withNano(0))}\n\n self.addGeolocationData(session_attributes, super_gluu_request_dictionary)\n\n super_gluu_request = json.dumps(super_gluu_request_dictionary, separators=(',',':'))\n print \"Super-Gluu. Prepare for step 1. Prepared super_gluu_request:\", super_gluu_request\n \n identity.setWorkingParameter(\"super_gluu_request\", super_gluu_request)\n elif self.twoStep:\n identity.setWorkingParameter(\"display_register_action\", True)\n\n return True\n elif step == 2:\n print \"Super-Gluu. Prepare for step 2\"\n if self.oneStep:\n return True\n\n authenticationService = CdiUtil.bean(AuthenticationService)\n user = authenticationService.getAuthenticatedUser()\n if user == None:\n print \"Super-Gluu. Prepare for step 2. Failed to determine user name\"\n return False\n\n if session_attributes.containsKey(\"super_gluu_request\"):\n super_gluu_request = session_attributes.get(\"super_gluu_request\")\n if not StringHelper.equalsIgnoreCase(super_gluu_request, \"timeout\"):\n print \"Super-Gluu. Prepare for step 2. Request was generated already\"\n return True\n \n session = CdiUtil.bean(SessionIdService).getSessionId()\n if session == None:\n print \"Super-Gluu. Prepare for step 2. Failed to determine session_id\"\n return False\n\n auth_method = session_attributes.get(\"super_gluu_auth_method\")\n if StringHelper.isEmpty(auth_method):\n print \"Super-Gluu. Prepare for step 2. Failed to determine auth_method\"\n return False\n\n print \"Super-Gluu. Prepare for step 2. auth_method: '%s'\" % auth_method\n \n issuer = CdiUtil.bean(ConfigurationFactory).getAppConfiguration().getIssuer()\n super_gluu_request_dictionary = {'username': user.getUserId(),\n 'app': client_redirect_uri,\n 'issuer': issuer,\n 'method': auth_method,\n 'state': session.getId(),\n 'licensed': self.valid_license,\n 'created': DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(ZonedDateTime.now().withNano(0))}\n\n self.addGeolocationData(session_attributes, super_gluu_request_dictionary)\n\n super_gluu_request = json.dumps(super_gluu_request_dictionary, separators=(',',':'))\n print \"Super-Gluu. Prepare for step 2. Prepared super_gluu_request:\", super_gluu_request\n\n identity.setWorkingParameter(\"super_gluu_request\", super_gluu_request)\n identity.setWorkingParameter(\"super_gluu_auth_method\", auth_method)\n\n if auth_method in ['authenticate']:\n self.sendPushNotification(client_redirect_uri, user, super_gluu_request)\n\n return True\n else:\n return False\n\n def getNextStep(self, configurationAttributes, requestParameters, step):\n # If user not pass current step change step to previous\n identity = CdiUtil.bean(Identity)\n retry_current_step = identity.getWorkingParameter(\"retry_current_step\")\n if retry_current_step:\n print \"Super-Gluu. Get next step. Retrying current step\"\n\n # Remove old QR code\n identity.setWorkingParameter(\"super_gluu_request\", \"timeout\")\n\n resultStep = step\n return resultStep\n\n return -1\n\n def getExtraParametersForStep(self, configurationAttributes, step):\n if step == 1:\n if self.oneStep: \n return Arrays.asList(\"super_gluu_request\")\n elif self.twoStep:\n return Arrays.asList(\"display_register_action\")\n elif step == 2:\n return Arrays.asList(\"super_gluu_auth_method\", \"super_gluu_request\")\n \n return None\n\n def getCountAuthenticationSteps(self, configurationAttributes):\n identity = CdiUtil.bean(Identity)\n if identity.isSetWorkingParameter(\"super_gluu_count_login_steps\"):\n return identity.getWorkingParameter(\"super_gluu_count_login_steps\")\n else:\n return 2\n\n def getPageForStep(self, configurationAttributes, step):\n if step == 1:\n if self.oneStep: \n return \"/auth/super-gluu/login.xhtml\"\n elif step == 2:\n if self.oneStep:\n return \"/login.xhtml\"\n else:\n identity = CdiUtil.bean(Identity)\n authmethod = identity.getWorkingParameter(\"super_gluu_auth_method\")\n print \"Super-Gluu. authmethod '%s'\" % authmethod\n if authmethod == \"enroll\":\n return \"/auth/super-gluu/login.xhtml\"\n else:\n return \"/auth/super-gluu/login.xhtml\"\n\n return \"\"\n\n def getLogoutExternalUrl(self, configurationAttributes, requestParameters):\n print \"Get external logout URL call\"\n return None\n\n def logout(self, configurationAttributes, requestParameters):\n return True\n\n def processBasicAuthentication(self, credentials):\n authenticationService = CdiUtil.bean(AuthenticationService)\n\n user_name = credentials.getUsername()\n user_password = credentials.getPassword()\n\n logged_in = False\n if StringHelper.isNotEmptyString(user_name) and StringHelper.isNotEmptyString(user_password):\n logged_in = authenticationService.authenticate(user_name, user_password)\n\n if not logged_in:\n return None\n\n find_user_by_uid = authenticationService.getAuthenticatedUser()\n if find_user_by_uid == None:\n print \"Super-Gluu. Process basic authentication. Failed to find user '%s'\" % user_name\n return None\n \n return find_user_by_uid\n\n def validateSessionDeviceStatus(self, client_redirect_uri, session_device_status, user_name = None):\n userService = CdiUtil.bean(UserService)\n deviceRegistrationService = CdiUtil.bean(DeviceRegistrationService)\n\n u2f_device_id = session_device_status['device_id']\n\n u2f_device = None\n if session_device_status['enroll'] and session_device_status['one_step']:\n u2f_device = deviceRegistrationService.findOneStepUserDeviceRegistration(u2f_device_id)\n if u2f_device == None:\n print \"Super-Gluu. Validate session device status. There is no one step u2f_device '%s'\" % u2f_device_id\n return False\n else:\n # Validate if user has specified device_id enrollment\n user_inum = userService.getUserInum(user_name)\n\n if session_device_status['one_step']:\n user_inum = session_device_status['user_inum']\n \n u2f_device = deviceRegistrationService.findUserDeviceRegistration(user_inum, u2f_device_id)\n if u2f_device == None:\n print \"Super-Gluu. Validate session device status. There is no u2f_device '%s' associated with user '%s'\" % (u2f_device_id, user_inum)\n return False\n\n if not StringHelper.equalsIgnoreCase(client_redirect_uri, u2f_device.application):\n print \"Super-Gluu. Validate session device status. u2f_device '%s' associated with other application '%s'\" % (u2f_device_id, u2f_device.application)\n return False\n \n return True\n\n def getSessionDeviceStatus(self, session_attributes, user_name):\n print \"Super-Gluu. Get session device status\"\n\n if not session_attributes.containsKey(\"super_gluu_request\"):\n print \"Super-Gluu. Get session device status. There is no Super-Gluu request in session attributes\"\n return None\n\n # Check session state extended\n if not session_attributes.containsKey(\"session_custom_state\"):\n print \"Super-Gluu. Get session device status. There is no session_custom_state in session attributes\"\n return None\n\n session_custom_state = session_attributes.get(\"session_custom_state\")\n if not StringHelper.equalsIgnoreCase(\"approved\", session_custom_state):\n print \"Super-Gluu. Get session device status. User '%s' not approve or not pass U2F authentication. session_custom_state: '%s'\" % (user_name, session_custom_state)\n return None\n\n # Try to find device_id in session attribute\n if not session_attributes.containsKey(\"oxpush2_u2f_device_id\"):\n print \"Super-Gluu. Get session device status. There is no u2f_device associated with this request\"\n return None\n\n # Try to find user_inum in session attribute\n if not session_attributes.containsKey(\"oxpush2_u2f_device_user_inum\"):\n print \"Super-Gluu. Get session device status. There is no user_inum associated with this request\"\n return None\n \n enroll = False\n if session_attributes.containsKey(\"oxpush2_u2f_device_enroll\"):\n enroll = StringHelper.equalsIgnoreCase(\"true\", session_attributes.get(\"oxpush2_u2f_device_enroll\"))\n\n one_step = False\n if session_attributes.containsKey(\"oxpush2_u2f_device_one_step\"):\n one_step = StringHelper.equalsIgnoreCase(\"true\", session_attributes.get(\"oxpush2_u2f_device_one_step\"))\n \n super_gluu_request = session_attributes.get(\"super_gluu_request\")\n u2f_device_id = session_attributes.get(\"oxpush2_u2f_device_id\")\n user_inum = session_attributes.get(\"oxpush2_u2f_device_user_inum\")\n\n session_device_status = {\"super_gluu_request\": super_gluu_request, \"device_id\": u2f_device_id, \"user_inum\" : user_inum, \"enroll\" : enroll, \"one_step\" : one_step}\n print \"Super-Gluu. Get session device status. session_device_status: '%s'\" % (session_device_status)\n \n return session_device_status\n\n def initPushNotificationService(self, configurationAttributes):\n print \"Super-Gluu. Initialize Native/SNS/Gluu notification services\"\n\n self.pushSnsMode = False\n self.pushGluuMode = False\n if configurationAttributes.containsKey(\"notification_service_mode\"):\n notificationServiceMode = configurationAttributes.get(\"notification_service_mode\").getValue2()\n if StringHelper.equalsIgnoreCase(notificationServiceMode, \"sns\"):\n return self.initSnsPushNotificationService(configurationAttributes)\n elif StringHelper.equalsIgnoreCase(notificationServiceMode, \"gluu\"):\n return self.initGluuPushNotificationService(configurationAttributes)\n\n return self.initNativePushNotificationService(configurationAttributes)\n\n def initNativePushNotificationService(self, configurationAttributes):\n print \"Super-Gluu. Initialize native notification services\"\n \n creds = self.loadPushNotificationCreds(configurationAttributes)\n if creds == None:\n return False\n \n try:\n android_creds = creds[\"android\"][\"gcm\"]\n ios_creds = creds[\"ios\"][\"apns\"]\n except:\n print \"Super-Gluu. Initialize native notification services. Invalid credentials file format\"\n return False\n \n self.pushAndroidService = None\n self.pushAppleService = None\n if android_creds[\"enabled\"]:\n self.pushAndroidService = Sender(android_creds[\"api_key\"]) \n print \"Super-Gluu. Initialize native notification services. Created Android notification service\"\n \n if ios_creds[\"enabled\"]:\n p12_file_path = ios_creds[\"p12_file_path\"]\n p12_password = ios_creds[\"p12_password\"]\n\n try:\n encryptionService = CdiUtil.bean(EncryptionService)\n p12_password = encryptionService.decrypt(p12_password)\n except:\n # Ignore exception. Password is not encrypted\n print \"Super-Gluu. Initialize native notification services. Assuming that 'p12_password' password in not encrypted\"\n\n apnsServiceBuilder = APNS.newService().withCert(p12_file_path, p12_password)\n if ios_creds[\"production\"]:\n self.pushAppleService = apnsServiceBuilder.withProductionDestination().build()\n else:\n self.pushAppleService = apnsServiceBuilder.withSandboxDestination().build()\n\n self.pushAppleServiceProduction = ios_creds[\"production\"]\n\n print \"Super-Gluu. Initialize native notification services. Created iOS notification service\"\n\n enabled = self.pushAndroidService != None or self.pushAppleService != None\n\n return enabled\n\n def initSnsPushNotificationService(self, configurationAttributes):\n print \"Super-Gluu. Initialize SNS notification services\"\n self.pushSnsMode = True\n\n creds = self.loadPushNotificationCreds(configurationAttributes)\n if creds == None:\n return False\n \n try:\n sns_creds = creds[\"sns\"]\n android_creds = creds[\"android\"][\"sns\"]\n ios_creds = creds[\"ios\"][\"sns\"]\n except:\n print \"Super-Gluu. Initialize SNS notification services. Invalid credentials file format\"\n return False\n \n self.pushAndroidService = None\n self.pushAppleService = None\n if not (android_creds[\"enabled\"] or ios_creds[\"enabled\"]):\n print \"Super-Gluu. Initialize SNS notification services. SNS disabled for all platforms\"\n return False\n\n sns_access_key = sns_creds[\"access_key\"]\n sns_secret_access_key = sns_creds[\"secret_access_key\"]\n sns_region = sns_creds[\"region\"]\n\n encryptionService = CdiUtil.bean(EncryptionService)\n\n try:\n sns_secret_access_key = encryptionService.decrypt(sns_secret_access_key)\n except:\n # Ignore exception. Password is not encrypted\n print \"Super-Gluu. Initialize SNS notification services. Assuming that 'sns_secret_access_key' in not encrypted\"\n \n pushSnsService = CdiUtil.bean(PushSnsService)\n pushClient = pushSnsService.createSnsClient(sns_access_key, sns_secret_access_key, sns_region)\n\n if android_creds[\"enabled\"]:\n self.pushAndroidService = pushClient\n self.pushAndroidPlatformArn = android_creds[\"platform_arn\"]\n print \"Super-Gluu. Initialize SNS notification services. Created Android notification service\"\n\n if ios_creds[\"enabled\"]:\n self.pushAppleService = pushClient \n self.pushApplePlatformArn = ios_creds[\"platform_arn\"]\n self.pushAppleServiceProduction = ios_creds[\"production\"]\n print \"Super-Gluu. Initialize SNS notification services. Created iOS notification service\"\n\n enabled = self.pushAndroidService != None or self.pushAppleService != None\n\n return enabled\n\n def initGluuPushNotificationService(self, configurationAttributes):\n print \"Super-Gluu. Initialize Gluu notification services\"\n\n self.pushGluuMode = True\n\n creds = self.loadPushNotificationCreds(configurationAttributes)\n if creds == None:\n return False\n \n try:\n gluu_conf = creds[\"gluu\"]\n android_creds = creds[\"android\"][\"gluu\"]\n ios_creds = creds[\"ios\"][\"gluu\"]\n except:\n print \"Super-Gluu. Initialize Gluu notification services. Invalid credentials file format\"\n return False\n \n self.pushAndroidService = None\n self.pushAppleService = None\n if not (android_creds[\"enabled\"] or ios_creds[\"enabled\"]):\n print \"Super-Gluu. Initialize Gluu notification services. Gluu disabled for all platforms\"\n return False\n\n gluu_server_uri = gluu_conf[\"server_uri\"]\n notifyClientFactory = NotifyClientFactory.instance()\n metadataConfiguration = None\n try:\n metadataConfiguration = notifyClientFactory.createMetaDataConfigurationService(gluu_server_uri).getMetadataConfiguration()\n except:\n print \"Super-Gluu. Initialize Gluu notification services. Failed to load metadata. Exception: \", sys.exc_info()[1]\n return False\n\n gluuClient = notifyClientFactory.createNotifyService(metadataConfiguration)\n encryptionService = CdiUtil.bean(EncryptionService)\n\n if android_creds[\"enabled\"]:\n gluu_access_key = android_creds[\"access_key\"]\n gluu_secret_access_key = android_creds[\"secret_access_key\"]\n \n try:\n gluu_secret_access_key = encryptionService.decrypt(gluu_secret_access_key)\n except:\n # Ignore exception. Password is not encrypted\n print \"Super-Gluu. Initialize Gluu notification services. Assuming that 'gluu_secret_access_key' in not encrypted\"\n \n self.pushAndroidService = gluuClient \n self.pushAndroidServiceAuth = notifyClientFactory.getAuthorization(gluu_access_key, gluu_secret_access_key);\n print \"Super-Gluu. Initialize Gluu notification services. Created Android notification service\"\n\n if ios_creds[\"enabled\"]:\n gluu_access_key = ios_creds[\"access_key\"]\n gluu_secret_access_key = ios_creds[\"secret_access_key\"]\n \n try:\n gluu_secret_access_key = encryptionService.decrypt(gluu_secret_access_key)\n except:\n # Ignore exception. Password is not encrypted\n print \"Super-Gluu. Initialize Gluu notification services. Assuming that 'gluu_secret_access_key' in not encrypted\"\n \n self.pushAppleService = gluuClient \n self.pushAppleServiceAuth = notifyClientFactory.getAuthorization(gluu_access_key, gluu_secret_access_key);\n print \"Super-Gluu. Initialize Gluu notification services. Created iOS notification service\"\n\n enabled = self.pushAndroidService != None or self.pushAppleService != None\n\n return enabled\n\n def loadPushNotificationCreds(self, configurationAttributes):\n print \"Super-Gluu. Initialize notification services\"\n if not configurationAttributes.containsKey(\"credentials_file\"):\n return None\n\n super_gluu_creds_file = configurationAttributes.get(\"credentials_file\").getValue2()\n\n # Load credentials from file\n f = open(super_gluu_creds_file, 'r')\n try:\n creds = json.loads(f.read())\n except:\n print \"Super-Gluu. Initialize notification services. Failed to load credentials from file:\", super_gluu_creds_file\n return None\n finally:\n f.close()\n\n return creds\n\n def sendPushNotification(self, client_redirect_uri, user, super_gluu_request):\n try:\n self.sendPushNotificationImpl(client_redirect_uri, user, super_gluu_request)\n except:\n print \"Super-Gluu. Send push notification. Failed to send push notification: \", sys.exc_info()[1]\n\n def sendPushNotificationImpl(self, client_redirect_uri, user, super_gluu_request):\n if not self.enabledPushNotifications:\n return\n\n user_name = user.getUserId()\n print \"Super-Gluu. Send push notification. Loading user '%s' devices\" % user_name\n\n send_notification = False\n send_notification_result = True\n\n userService = CdiUtil.bean(UserService)\n deviceRegistrationService = CdiUtil.bean(DeviceRegistrationService)\n\n user_inum = userService.getUserInum(user_name)\n\n send_android = 0\n send_ios = 0\n u2f_devices_list = deviceRegistrationService.findUserDeviceRegistrations(user_inum, client_redirect_uri, \"oxId\", \"oxDeviceData\", \"oxDeviceNotificationConf\")\n if u2f_devices_list.size() > 0:\n for u2f_device in u2f_devices_list:\n device_data = u2f_device.getDeviceData()\n\n # Device data which Super-Gluu gets during enrollment\n if device_data == None:\n continue\n\n platform = device_data.getPlatform()\n push_token = device_data.getPushToken()\n debug = False\n\n if StringHelper.equalsIgnoreCase(platform, \"ios\") and StringHelper.isNotEmpty(push_token):\n # Sending notification to iOS user's device\n if self.pushAppleService == None:\n print \"Super-Gluu. Send push notification. Apple native push notification service is not enabled\"\n else:\n send_notification = True\n \n title = \"Super Gluu\"\n message = \"Confirm your sign in request to: %s\" % client_redirect_uri\n\n if self.pushSnsMode or self.pushGluuMode:\n pushSnsService = CdiUtil.bean(PushSnsService)\n targetEndpointArn = self.getTargetEndpointArn(deviceRegistrationService, pushSnsService, PushPlatform.APNS, user, u2f_device)\n if targetEndpointArn == None:\n \treturn\n\n send_notification = True\n \n sns_push_request_dictionary = { \"aps\": \n { \"badge\": 0,\n \"alert\" : {\"body\": message, \"title\" : title},\n \"category\": \"ACTIONABLE\",\n \"content-available\": \"1\",\n \"sound\": 'default'\n },\n \"request\" : super_gluu_request\n }\n push_message = json.dumps(sns_push_request_dictionary, separators=(',',':'))\n \n if self.pushSnsMode:\n apple_push_platform = PushPlatform.APNS\n if not self.pushAppleServiceProduction:\n apple_push_platform = PushPlatform.APNS_SANDBOX\n \n send_notification_result = pushSnsService.sendPushMessage(self.pushAppleService, apple_push_platform, targetEndpointArn, push_message, None)\n if debug:\n print \"Super-Gluu. Send iOS SNS push notification. token: '%s', message: '%s', send_notification_result: '%s', apple_push_platform: '%s'\" % (push_token, push_message, send_notification_result, apple_push_platform)\n elif self.pushGluuMode:\n send_notification_result = self.pushAppleService.sendNotification(self.pushAppleServiceAuth, targetEndpointArn, push_message)\n if debug:\n print \"Super-Gluu. Send iOS Gluu push notification. token: '%s', message: '%s', send_notification_result: '%s'\" % (push_token, push_message, send_notification_result)\n else:\n additional_fields = { \"request\" : super_gluu_request }\n \n msgBuilder = APNS.newPayload().alertBody(message).alertTitle(title).sound(\"default\")\n msgBuilder.category('ACTIONABLE').badge(0)\n msgBuilder.forNewsstand()\n msgBuilder.customFields(additional_fields)\n push_message = msgBuilder.build()\n \n send_notification_result = self.pushAppleService.push(push_token, push_message)\n if debug:\n print \"Super-Gluu. Send iOS Native push notification. token: '%s', message: '%s', send_notification_result: '%s'\" % (push_token, push_message, send_notification_result)\n send_ios = send_ios + 1\n\n if StringHelper.equalsIgnoreCase(platform, \"android\") and StringHelper.isNotEmpty(push_token):\n # Sending notification to Android user's device\n if self.pushAndroidService == None:\n print \"Super-Gluu. Send native push notification. Android native push notification service is not enabled\"\n else:\n send_notification = True\n\n title = \"Super-Gluu\"\n if self.pushSnsMode or self.pushGluuMode:\n pushSnsService = CdiUtil.bean(PushSnsService)\n targetEndpointArn = self.getTargetEndpointArn(deviceRegistrationService, pushSnsService, PushPlatform.GCM, user, u2f_device)\n if targetEndpointArn == None:\n \treturn\n\n send_notification = True\n \n sns_push_request_dictionary = { \"collapse_key\": \"single\",\n \"content_available\": True,\n \"time_to_live\": 60,\n \"data\": \n { \"message\" : super_gluu_request,\n \"title\" : title }\n }\n push_message = json.dumps(sns_push_request_dictionary, separators=(',',':'))\n \n if self.pushSnsMode:\n send_notification_result = pushSnsService.sendPushMessage(self.pushAndroidService, PushPlatform.GCM, targetEndpointArn, push_message, None)\n if debug:\n print \"Super-Gluu. Send Android SNS push notification. token: '%s', message: '%s', send_notification_result: '%s'\" % (push_token, push_message, send_notification_result)\n elif self.pushGluuMode:\n send_notification_result = self.pushAndroidService.sendNotification(self.pushAndroidServiceAuth, targetEndpointArn, push_message)\n if debug:\n print \"Super-Gluu. Send Android Gluu push notification. token: '%s', message: '%s', send_notification_result: '%s'\" % (push_token, push_message, send_notification_result)\n else:\n msgBuilder = Message.Builder().addData(\"message\", super_gluu_request).addData(\"title\", title).collapseKey(\"single\").contentAvailable(True)\n push_message = msgBuilder.build()\n \n send_notification_result = self.pushAndroidService.send(push_message, push_token, 3)\n if debug:\n print \"Super-Gluu. Send Android Native push notification. token: '%s', message: '%s', send_notification_result: '%s'\" % (push_token, push_message, send_notification_result)\n send_android = send_android + 1\n\n print \"Super-Gluu. Send push notification. send_android: '%s', send_ios: '%s'\" % (send_android, send_ios)\n\n def getTargetEndpointArn(self, deviceRegistrationService, pushSnsService, platform, user, u2fDevice):\n targetEndpointArn = None\n \n # Return endpoint ARN if it created already\n notificationConf = u2fDevice.getDeviceNotificationConf()\n if StringHelper.isNotEmpty(notificationConf):\n notificationConfJson = json.loads(notificationConf)\n targetEndpointArn = notificationConfJson['sns_endpoint_arn']\n if StringHelper.isNotEmpty(targetEndpointArn):\n print \"Super-Gluu. Get target endpoint ARN. There is already created target endpoint ARN\"\n return targetEndpointArn\n\n # Create endpoint ARN \n pushClient = None\n pushClientAuth = None\n platformApplicationArn = None\n if platform == PushPlatform.GCM:\n pushClient = self.pushAndroidService\n if self.pushSnsMode:\n platformApplicationArn = self.pushAndroidPlatformArn\n if self.pushGluuMode:\n pushClientAuth = self.pushAndroidServiceAuth\n elif platform == PushPlatform.APNS:\n pushClient = self.pushAppleService\n if self.pushSnsMode:\n platformApplicationArn = self.pushApplePlatformArn\n if self.pushGluuMode:\n pushClientAuth = self.pushAppleServiceAuth\n else:\n return None\n\n deviceData = u2fDevice.getDeviceData()\n pushToken = deviceData.getPushToken()\n \n print \"Super-Gluu. Get target endpoint ARN. Attempting to create target endpoint ARN for user: '%s'\" % user.getUserId()\n if self.pushSnsMode:\n targetEndpointArn = pushSnsService.createPlatformArn(pushClient, platformApplicationArn, pushToken, user)\n else:\n customUserData = pushSnsService.getCustomUserData(user)\n registerDeviceResponse = pushClient.registerDevice(pushClientAuth, pushToken, customUserData);\n if registerDeviceResponse != None and registerDeviceResponse.getStatusCode() == 200:\n targetEndpointArn = registerDeviceResponse.getEndpointArn()\n \n if StringHelper.isEmpty(targetEndpointArn):\n\t print \"Super-Gluu. Failed to get endpoint ARN for user: '%s'\" % user.getUserId()\n \treturn None\n\n print \"Super-Gluu. Get target endpoint ARN. Create target endpoint ARN '%s' for user: '%s'\" % (targetEndpointArn, user.getUserId())\n \n # Store created endpoint ARN in device entry\n userInum = user.getAttribute(\"inum\")\n u2fDeviceUpdate = deviceRegistrationService.findUserDeviceRegistration(userInum, u2fDevice.getId())\n u2fDeviceUpdate.setDeviceNotificationConf('{\"sns_endpoint_arn\" : \"%s\"}' % targetEndpointArn)\n deviceRegistrationService.updateDeviceRegistration(userInum, u2fDeviceUpdate)\n\n return targetEndpointArn\n\n def getApplicationUri(self, session_attributes):\n if self.applicationId != None:\n return self.applicationId\n \n if not session_attributes.containsKey(\"redirect_uri\"):\n return None\n\n return session_attributes.get(\"redirect_uri\")\n\n def setRequestScopedParameters(self, identity, step):\n downloadMap = HashMap()\n if self.registrationUri != None:\n identity.setWorkingParameter(\"external_registration_uri\", self.registrationUri)\n\n if self.androidUrl!= None and step == 1:\n downloadMap.put(\"android\", self.androidUrl)\n\n if self.IOSUrl != None and step == 1:\n downloadMap.put(\"ios\", self.IOSUrl)\n \n if self.customLabel != None:\n identity.setWorkingParameter(\"super_gluu_label\", self.customLabel)\n \n identity.setWorkingParameter(\"download_url\", downloadMap)\n identity.setWorkingParameter(\"super_gluu_qr_options\", self.customQrOptions)\n\n def addGeolocationData(self, session_attributes, super_gluu_request_dictionary):\n if session_attributes.containsKey(\"remote_ip\"):\n remote_ip = session_attributes.get(\"remote_ip\")\n if StringHelper.isNotEmpty(remote_ip):\n print \"Super-Gluu. Prepare for step 2. Adding req_ip and req_loc to super_gluu_request\"\n super_gluu_request_dictionary['req_ip'] = remote_ip\n\n remote_loc_dic = self.determineGeolocationData(remote_ip)\n if remote_loc_dic == None:\n print \"Super-Gluu. Prepare for step 2. Failed to determine remote location by remote IP '%s'\" % remote_ip\n return\n\n remote_loc = \"%s, %s, %s\" % ( remote_loc_dic['country'], remote_loc_dic['regionName'], remote_loc_dic['city'] )\n remote_loc_encoded = urllib.quote(remote_loc.encode('utf-8'))\n super_gluu_request_dictionary['req_loc'] = remote_loc_encoded\n\n def determineGeolocationData(self, remote_ip):\n print \"Super-Gluu. Determine remote location. remote_ip: '%s'\" % remote_ip\n httpService = CdiUtil.bean(HttpService)\n\n http_client = httpService.getHttpsClient()\n http_client_params = http_client.getParams()\n http_client_params.setIntParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 15 * 1000)\n \n geolocation_service_url = \"http://ip-api.com/json/%s?fields=49177\" % remote_ip\n geolocation_service_headers = { \"Accept\" : \"application/json\" }\n\n try:\n http_service_response = httpService.executeGet(http_client, geolocation_service_url, geolocation_service_headers)\n http_response = http_service_response.getHttpResponse()\n except:\n print \"Super-Gluu. Determine remote location. Exception: \", sys.exc_info()[1]\n return None\n\n try:\n if not httpService.isResponseStastusCodeOk(http_response):\n print \"Super-Gluu. Determine remote location. Get invalid response from validation server: \", str(http_response.getStatusLine().getStatusCode())\n httpService.consume(http_response)\n return None\n \n response_bytes = httpService.getResponseContent(http_response)\n response_string = httpService.convertEntityToString(response_bytes)\n httpService.consume(http_response)\n finally:\n http_service_response.closeConnection()\n\n if response_string == None:\n print \"Super-Gluu. Determine remote location. Get empty response from location server\"\n return None\n \n response = json.loads(response_string)\n \n if not StringHelper.equalsIgnoreCase(response['status'], \"success\"):\n print \"Super-Gluu. Determine remote location. Get response with status: '%s'\" % response['status']\n return None\n\n return response\n\n def isUserMemberOfGroup(self, user, attribute, group):\n is_member = False\n member_of_list = user.getAttributeValues(attribute)\n if (member_of_list != None):\n for member_of in member_of_list:\n if StringHelper.equalsIgnoreCase(group, member_of) or member_of.endswith(group):\n is_member = True\n break\n\n return is_member\n\n def processAuditGroup(self, user, attribute, group):\n is_member = self.isUserMemberOfGroup(user, attribute, group)\n if (is_member):\n print \"Super-Gluu. Authenticate for processAuditGroup. User '%s' member of audit group\" % user.getUserId()\n print \"Super-Gluu. Authenticate for processAuditGroup. Sending e-mail about user '%s' login to %s\" % (user.getUserId(), self.audit_email)\n \n # Send e-mail to administrator\n user_id = user.getUserId()\n mailService = CdiUtil.bean(MailService)\n subject = \"User log in: %s\" % user_id\n body = \"User log in: %s\" % user_id\n mailService.sendMail(self.audit_email, subject, body)\n", @@ -819,7 +819,7 @@ "level": 70, "programmingLanguage": "PYTHON", "description": "Fido2 authentication module", - "locationType": "LDAP", + "locationType": "db", "dn": "inum=8BAF-80D7,ou=scripts,o=gluu", "inum": "8BAF-80D7", "script": "# jans-auth is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text.\n# Copyright (c) 2018, Gluu\n#\n# Author: Yuriy Movchan\n#\n\nfrom javax.ws.rs.core import Response\nfrom org.jboss.resteasy.client import ClientResponseFailure\nfrom org.jboss.resteasy.client.exception import ResteasyClientException\nfrom javax.ws.rs.core import Response\nfrom org.gluu.model.custom.script.type.auth import PersonAuthenticationType\nfrom org.gluu.fido2.client import Fido2ClientFactory\nfrom org.gluu.oxauth.security import Identity\nfrom org.gluu.oxauth.service import AuthenticationService, SessionIdService\nfrom org.gluu.oxauth.service.common import UserService\nfrom org.gluu.oxauth.util import ServerUtil\nfrom org.gluu.service.cdi.util import CdiUtil\nfrom org.gluu.util import StringHelper\n\nfrom java.util.concurrent.locks import ReentrantLock\n\nimport java\nimport sys\ntry:\n import json\nexcept ImportError:\n import simplejson as json\n\nclass PersonAuthentication(PersonAuthenticationType):\n def __init__(self, currentTimeMillis):\n self.currentTimeMillis = currentTimeMillis\n\n def init(self, customScript, configurationAttributes):\n print \"Fido2. Initialization\"\n\n if not configurationAttributes.containsKey(\"fido2_server_uri\"):\n print \"fido2_server_uri. Initialization. Property fido2_server_uri is not specified\"\n return False\n\n self.fido2_server_uri = configurationAttributes.get(\"fido2_server_uri\").getValue2()\n\n self.fido2_domain = None\n if configurationAttributes.containsKey(\"fido2_domain\"):\n self.fido2_domain = configurationAttributes.get(\"fido2_domain\").getValue2()\n\n self.metaDataLoaderLock = ReentrantLock()\n self.metaDataConfiguration = None\n \n print \"Fido2. Initialized successfully\"\n return True \n\n def destroy(self, configurationAttributes):\n print \"Fido2. Destroy\"\n print \"Fido2. Destroyed successfully\"\n return True\n\n def getApiVersion(self):\n return 11\n \n def getAuthenticationMethodClaims(self, requestParameters):\n return None\n \n def isValidAuthenticationMethod(self, usageType, configurationAttributes):\n return True\n\n def getAlternativeAuthenticationMethod(self, usageType, configurationAttributes):\n return None\n\n def authenticate(self, configurationAttributes, requestParameters, step):\n authenticationService = CdiUtil.bean(AuthenticationService)\n\n identity = CdiUtil.bean(Identity)\n credentials = identity.getCredentials()\n\n user_name = credentials.getUsername()\n\n if step == 1:\n print \"Fido2. Authenticate for step 1\"\n\n user_password = credentials.getPassword()\n logged_in = False\n if StringHelper.isNotEmptyString(user_name) and StringHelper.isNotEmptyString(user_password):\n userService = CdiUtil.bean(UserService)\n logged_in = authenticationService.authenticate(user_name, user_password)\n\n if not logged_in:\n return False\n\n return True\n elif step == 2:\n print \"Fido2. Authenticate for step 2\"\n\n token_response = ServerUtil.getFirstValue(requestParameters, \"tokenResponse\")\n if token_response == None:\n print \"Fido2. Authenticate for step 2. tokenResponse is empty\"\n return False\n\n auth_method = ServerUtil.getFirstValue(requestParameters, \"authMethod\")\n if auth_method == None:\n print \"Fido2. Authenticate for step 2. authMethod is empty\"\n return False\n\n authenticationService = CdiUtil.bean(AuthenticationService)\n user = authenticationService.getAuthenticatedUser()\n if user == None:\n print \"Fido2. Prepare for step 2. Failed to determine user name\"\n return False\n\n if auth_method == 'authenticate':\n print \"Fido2. Prepare for step 2. Call Fido2 in order to finish authentication flow\"\n assertionService = Fido2ClientFactory.instance().createAssertionService(self.metaDataConfiguration)\n assertionStatus = assertionService.verify(token_response)\n authenticationStatusEntity = assertionStatus.readEntity(java.lang.String)\n\n if assertionStatus.getStatus() != Response.Status.OK.getStatusCode():\n print \"Fido2. Authenticate for step 2. Get invalid authentication status from Fido2 server\"\n return False\n\n return True\n elif auth_method == 'enroll':\n print \"Fido2. Prepare for step 2. Call Fido2 in order to finish registration flow\"\n attestationService = Fido2ClientFactory.instance().createAttestationService(self.metaDataConfiguration)\n attestationStatus = attestationService.verify(token_response)\n\n if attestationStatus.getStatus() != Response.Status.OK.getStatusCode():\n print \"Fido2. Authenticate for step 2. Get invalid registration status from Fido2 server\"\n return False\n\n return True\n else:\n print \"Fido2. Prepare for step 2. Authentication method is invalid\"\n return False\n\n return False\n else:\n return False\n\n def prepareForStep(self, configurationAttributes, requestParameters, step):\n identity = CdiUtil.bean(Identity)\n\n if step == 1:\n return True\n elif step == 2:\n print \"Fido2. Prepare for step 2\"\n\n session = CdiUtil.bean(SessionIdService).getSessionId()\n if session == None:\n print \"Fido2. Prepare for step 2. Failed to determine session_id\"\n return False\n\n authenticationService = CdiUtil.bean(AuthenticationService)\n user = authenticationService.getAuthenticatedUser()\n if user == None:\n print \"Fido2. Prepare for step 2. Failed to determine user name\"\n return False\n\n userName = user.getUserId()\n\n metaDataConfiguration = self.getMetaDataConfiguration()\n \n assertionResponse = None\n attestationResponse = None\n\n # Check if user have registered devices\n userService = CdiUtil.bean(UserService)\n countFido2Devices = userService.countFidoAndFido2Devices(userName, self.fido2_domain)\n if countFido2Devices > 0:\n print \"Fido2. Prepare for step 2. Call Fido2 endpoint in order to start assertion flow\"\n\n try:\n assertionService = Fido2ClientFactory.instance().createAssertionService(metaDataConfiguration)\n assertionRequest = json.dumps({'username': userName}, separators=(',', ':'))\n assertionResponse = assertionService.authenticate(assertionRequest).readEntity(java.lang.String)\n except ClientResponseFailure, ex:\n print \"Fido2. Prepare for step 2. Failed to start assertion flow. Exception:\", sys.exc_info()[1]\n return False\n else:\n print \"Fido2. Prepare for step 2. Call Fido2 endpoint in order to start attestation flow\"\n\n try:\n attestationService = Fido2ClientFactory.instance().createAttestationService(metaDataConfiguration)\n attestationRequest = json.dumps({'username': userName, 'displayName': userName, 'attestation' : 'direct'}, separators=(',', ':'))\n attestationResponse = attestationService.register(attestationRequest).readEntity(java.lang.String)\n except ClientResponseFailure, ex:\n print \"Fido2. Prepare for step 2. Failed to start attestation flow. Exception:\", sys.exc_info()[1]\n return False\n\n identity.setWorkingParameter(\"fido2_assertion_request\", ServerUtil.asJson(assertionResponse))\n identity.setWorkingParameter(\"fido2_attestation_request\", ServerUtil.asJson(attestationResponse))\n print \"Fido2. Prepare for step 2. Successfully start flow with next requests.\\nfido2_assertion_request: '%s'\\nfido2_attestation_request: '%s'\" % ( assertionResponse, attestationResponse )\n\n return True\n elif step == 3:\n print \"Fido2. Prepare for step 3\"\n\n return True\n else:\n return False\n\n def getExtraParametersForStep(self, configurationAttributes, step):\n return None\n\n def getCountAuthenticationSteps(self, configurationAttributes):\n return 2\n\n def getNextStep(self, configurationAttributes, requestParameters, step):\n return -1\n\n def getPageForStep(self, configurationAttributes, step):\n if step == 2:\n return \"/auth/fido2/login.xhtml\"\n\n return \"\"\n\n def logout(self, configurationAttributes, requestParameters):\n return True\n\n def getAuthenticationMethodClaims(self, requestParameters):\n return None\n \n def getLogoutExternalUrl(self, configurationAttributes, requestParameters):\n print \"Get external logout URL call\"\n return None \n \n \n def getMetaDataConfiguration(self):\n if self.metaDataConfiguration != None:\n return self.metaDataConfiguration\n \n self.metaDataLoaderLock.lock()\n # Make sure that another thread not loaded configuration already \n if self.metaDataConfiguration != None:\n return self.metaDataConfiguration\n\n try:\n print \"Fido2. Initialization. Downloading Fido2 metadata\"\n self.fido2_server_metadata_uri = self.fido2_server_uri + \"/.well-known/fido2-configuration\"\n #self.fido2_server_metadata_uri = self.fido2_server_uri + \"/fido2/restv1/fido2/configuration\"\n\n metaDataConfigurationService = Fido2ClientFactory.instance().createMetaDataConfigurationService(self.fido2_server_metadata_uri)\n \n max_attempts = 10\n for attempt in range(1, max_attempts + 1):\n try:\n self.metaDataConfiguration = metaDataConfigurationService.getMetadataConfiguration().readEntity(java.lang.String)\n return self.metaDataConfiguration\n except ClientResponseFailure, ex:\n # Detect if last try or we still get Service Unavailable HTTP error\n if (attempt == max_attempts) or (ex.getResponse().getResponseStatus() != Response.Status.SERVICE_UNAVAILABLE):\n raise ex\n \n java.lang.Thread.sleep(3000)\n print \"Attempting to load metadata: %d\" % attempt\n except ResteasyClientException, ex:\n # Detect if last try or we still get Service Unavailable HTTP error\n if attempt == max_attempts:\n raise ex\n \n java.lang.Thread.sleep(3000)\n print \"Attempting to load metadata: %d\" % attempt\n finally:\n self.metaDataLoaderLock.unlock()\n \n", @@ -852,7 +852,7 @@ "level": 70, "programmingLanguage": "PYTHON", "description": "UAF authentication module", - "locationType": "LDAP", + "locationType": "db", "dn": "inum=5018-AF9C,ou=scripts,o=gluu", "inum": "5018-AF9C", "script": "# jans-auth is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text.\n# Copyright (c) 2016, Gluu\n#\n# Author: Yuriy Movchan\n#\n\n# Requires the following custom properties and values:\n# uaf_server_uri: \n#\n# These are non mandatory custom properties and values:\n# uaf_policy_name: default\n# send_push_notifaction: false\n# registration_uri: https:///identity/register\n# qr_options: { width: 400, height: 400 }\n\nfrom org.gluu.model.custom.script.type.auth import PersonAuthenticationType\nfrom org.gluu.service.cdi.util import CdiUtil\nfrom org.gluu.oxauth.security import Identity\nfrom org.gluu.oxauth.service import AuthenticationService, SessionIdService\nfrom org.gluu.oxauth.service.common import UserService\nfrom org.gluu.util import StringHelper, ArrayHelper\nfrom org.gluu.oxauth.util import ServerUtil\nfrom org.gluu.oxauth.model.config import Constants\nfrom javax.ws.rs.core import Response\nfrom java.util import Arrays\nfrom org.gluu.oxauth.service.net import HttpService\nfrom org.apache.http.params import CoreConnectionPNames\n\nimport sys\nimport java\nimport json\n\nclass PersonAuthentication(PersonAuthenticationType):\n def __init__(self, currentTimeMillis):\n self.currentTimeMillis = currentTimeMillis\n\n def init(self, customScript, configurationAttributes):\n print \"UAF. Initialization\"\n\n if not configurationAttributes.containsKey(\"uaf_server_uri\"):\n print \"UAF. Initialization. Property uaf_server_uri is mandatory\"\n return False\n\n self.uaf_server_uri = configurationAttributes.get(\"uaf_server_uri\").getValue2()\n\n self.uaf_policy_name = \"default\"\n if configurationAttributes.containsKey(\"uaf_policy_name\"):\n self.uaf_policy_name = configurationAttributes.get(\"uaf_policy_name\").getValue2()\n\n self.send_push_notifaction = False\n if configurationAttributes.containsKey(\"send_push_notifaction\"):\n self.send_push_notifaction = StringHelper.toBoolean(configurationAttributes.get(\"send_push_notifaction\").getValue2(), False)\n\n self.registration_uri = None\n if configurationAttributes.containsKey(\"registration_uri\"):\n self.registration_uri = configurationAttributes.get(\"registration_uri\").getValue2()\n\n self.customQrOptions = {}\n if configurationAttributes.containsKey(\"qr_options\"):\n self.customQrOptions = configurationAttributes.get(\"qr_options\").getValue2()\n\n print \"UAF. Initializing HTTP client\"\n httpService = CdiUtil.bean(HttpService)\n self.http_client = httpService.getHttpsClient()\n http_client_params = self.http_client.getParams()\n http_client_params.setIntParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 15 * 1000)\n\n print \"UAF. Initialized successfully. uaf_server_uri: '%s', uaf_policy_name: '%s', send_push_notifaction: '%s', registration_uri: '%s', qr_options: '%s'\" % (self.uaf_server_uri, self.uaf_policy_name, self.send_push_notifaction, self.registration_uri, self.customQrOptions)\n \n print \"UAF. Initialized successfully\"\n return True\n\n def destroy(self, configurationAttributes):\n print \"UAF. Destroy\"\n print \"UAF. Destroyed successfully\"\n return True\n\n def getApiVersion(self):\n return 11\n \n def getAuthenticationMethodClaims(self, requestParameters):\n return None\n \n def isValidAuthenticationMethod(self, usageType, configurationAttributes):\n return True\n\n def getAlternativeAuthenticationMethod(self, usageType, configurationAttributes):\n return None\n\n def authenticate(self, configurationAttributes, requestParameters, step):\n identity = CdiUtil.bean(Identity)\n credentials = identity.getCredentials()\n\n session_attributes = identity.getSessionId().getSessionAttributes()\n\n self.setRequestScopedParameters(identity)\n\n if (step == 1):\n print \"UAF. Authenticate for step 1\"\n\n user_name = credentials.getUsername()\n\n authenticated_user = self.processBasicAuthentication(credentials)\n if authenticated_user == None:\n return False\n\n uaf_auth_method = \"authenticate\"\n # Uncomment this block if you need to allow user second device registration\n #enrollment_mode = ServerUtil.getFirstValue(requestParameters, \"loginForm:registerButton\")\n #if StringHelper.isNotEmpty(enrollment_mode):\n # uaf_auth_method = \"enroll\"\n \n if uaf_auth_method == \"authenticate\":\n user_enrollments = self.findEnrollments(credentials)\n if len(user_enrollments) == 0:\n uaf_auth_method = \"enroll\"\n print \"UAF. Authenticate for step 1. There is no UAF enrollment for user '%s'. Changing uaf_auth_method to '%s'\" % (user_name, uaf_auth_method)\n\n print \"UAF. Authenticate for step 1. uaf_auth_method: '%s'\" % uaf_auth_method\n \n identity.setWorkingParameter(\"uaf_auth_method\", uaf_auth_method)\n\n return True\n elif (step == 2):\n print \"UAF. Authenticate for step 2\"\n\n session = CdiUtil.bean(SessionIdService).getSessionId()\n if session == None:\n print \"UAF. Prepare for step 2. Failed to determine session_id\"\n return False\n\n user = authenticationService.getAuthenticatedUser()\n if (user == None):\n print \"UAF. Authenticate for step 2. Failed to determine user name\"\n return False\n user_name = user.getUserId()\n\n uaf_auth_result = ServerUtil.getFirstValue(requestParameters, \"auth_result\")\n if uaf_auth_result != \"success\":\n print \"UAF. Authenticate for step 2. auth_result is '%s'\" % uaf_auth_result\n return False\n\n # Restore state from session\n uaf_auth_method = session_attributes.get(\"uaf_auth_method\")\n\n if not uaf_auth_method in ['enroll', 'authenticate']:\n print \"UAF. Authenticate for step 2. Failed to authenticate user. uaf_auth_method: '%s'\" % uaf_auth_method\n return False\n\n # Request STATUS_OBB\n if True:\n #TODO: Remove this condition\n # It's workaround becuase it's not possible to call STATUS_OBB 2 times. First time on browser and second ime on server\n uaf_user_device_handle = ServerUtil.getFirstValue(requestParameters, \"auth_handle\")\n else:\n uaf_obb_auth_method = session_attributes.get(\"uaf_obb_auth_method\")\n uaf_obb_server_uri = session_attributes.get(\"uaf_obb_server_uri\")\n uaf_obb_start_response = session_attributes.get(\"uaf_obb_start_response\")\n\n # Prepare STATUS_OBB\n uaf_obb_start_response_json = json.loads(uaf_obb_start_response)\n uaf_obb_status_request_dictionary = { \"operation\": \"STATUS_%s\" % uaf_obb_auth_method,\n \"userName\": user_name,\n \"needDetails\": 1,\n \"oobStatusHandle\": uaf_obb_start_response_json[\"oobStatusHandle\"],\n }\n \n uaf_obb_status_request = json.dumps(uaf_obb_status_request_dictionary, separators=(',',':'))\n print \"UAF. Authenticate for step 2. Prepared STATUS request: '%s' to send to '%s'\" % (uaf_obb_status_request, uaf_obb_server_uri)\n\n uaf_status_obb_response = self.executePost(uaf_obb_server_uri, uaf_obb_status_request)\n if uaf_status_obb_response == None:\n return False\n\n print \"UAF. Authenticate for step 2. Get STATUS response: '%s'\" % uaf_status_obb_response\n uaf_status_obb_response_json = json.loads(uaf_status_obb_response)\n \n if uaf_status_obb_response_json[\"statusCode\"] != 4000:\n print \"UAF. Authenticate for step 2. UAF operation status is invalid. statusCode: '%s'\" % uaf_status_obb_response_json[\"statusCode\"]\n return False\n\n uaf_user_device_handle = uaf_status_obb_response_json[\"additionalInfo\"][\"authenticatorsResult\"][\"handle\"]\n\n if StringHelper.isEmpty(uaf_user_device_handle):\n print \"UAF. Prepare for step 2. Failed to get UAF handle\"\n return False\n\n uaf_user_external_uid = \"uaf:%s\" % uaf_user_device_handle\n print \"UAF. Authenticate for step 2. UAF handle: '%s'\" % uaf_user_external_uid\n\n if uaf_auth_method == \"authenticate\":\n # Validate if user used device with same keYHandle\n user_enrollments = self.findEnrollments(credentials)\n if len(user_enrollments) == 0:\n uaf_auth_method = \"enroll\"\n print \"UAF. Authenticate for step 2. There is no UAF enrollment for user '%s'.\" % user_name\n return False\n \n for user_enrollment in user_enrollments:\n if StringHelper.equalsIgnoreCase(user_enrollment, uaf_user_device_handle):\n print \"UAF. Authenticate for step 2. There is UAF enrollment for user '%s'. User authenticated successfully\" % user_name\n return True\n else:\n userService = CdiUtil.bean(UserService)\n\n # Double check just to make sure. We did checking in previous step\n # Check if there is user which has uaf_user_external_uid\n # Avoid mapping user cert to more than one IDP account\n find_user_by_external_uid = userService.getUserByAttribute(\"oxExternalUid\", uaf_user_external_uid)\n if find_user_by_external_uid == None:\n # Add uaf_user_external_uid to user's external GUID list\n find_user_by_external_uid = userService.addUserAttribute(user_name, \"oxExternalUid\", uaf_user_external_uid)\n if find_user_by_external_uid == None:\n print \"UAF. Authenticate for step 2. Failed to update current user\"\n return False\n \n return True\n\n return False\n else:\n return False\n\n def prepareForStep(self, configurationAttributes, requestParameters, step):\n authenticationService = CdiUtil.bean(AuthenticationService)\n\n identity = CdiUtil.bean(Identity)\n credentials = identity.getCredentials()\n\n session_attributes = identity.getSessionId().getSessionAttributes()\n\n self.setRequestScopedParameters(identity)\n\n if (step == 1):\n return True\n elif (step == 2):\n print \"UAF. Prepare for step 2\"\n\n session = CdiUtil.bean(SessionIdService).getSessionId()\n if session == None:\n print \"UAF. Prepare for step 2. Failed to determine session_id\"\n return False\n\n user = authenticationService.getAuthenticatedUser()\n if (user == None):\n print \"UAF. Prepare for step 2. Failed to determine user name\"\n return False\n\n uaf_auth_method = session_attributes.get(\"uaf_auth_method\")\n if StringHelper.isEmpty(uaf_auth_method):\n print \"UAF. Prepare for step 2. Failed to determine auth_method\"\n return False\n\n print \"UAF. Prepare for step 2. uaf_auth_method: '%s'\" % uaf_auth_method\n\n uaf_obb_auth_method = \"OOB_REG\"\n uaf_obb_server_uri = self.uaf_server_uri + \"/nnl/v2/reg\" \n if StringHelper.equalsIgnoreCase(uaf_auth_method, \"authenticate\"):\n uaf_obb_auth_method = \"OOB_AUTH\"\n uaf_obb_server_uri = self.uaf_server_uri + \"/nnl/v2/auth\" \n\n # Prepare START_OBB\n uaf_obb_start_request_dictionary = { \"operation\": \"START_%s\" % uaf_obb_auth_method,\n \"userName\": user.getUserId(),\n \"policyName\": \"default\",\n \"oobMode\":\n { \"qr\": \"true\", \"rawData\": \"false\", \"push\": \"false\" } \n }\n\n uaf_obb_start_request = json.dumps(uaf_obb_start_request_dictionary, separators=(',',':'))\n print \"UAF. Prepare for step 2. Prepared START request: '%s' to send to '%s'\" % (uaf_obb_start_request, uaf_obb_server_uri)\n\n # Request START_OBB\n uaf_obb_start_response = self.executePost(uaf_obb_server_uri, uaf_obb_start_request)\n if uaf_obb_start_response == None:\n return False\n\n print \"UAF. Prepare for step 2. Get START response: '%s'\" % uaf_obb_start_response\n uaf_obb_start_response_json = json.loads(uaf_obb_start_response)\n\n # Prepare STATUS_OBB\n #TODO: Remove needDetails parameter\n uaf_obb_status_request_dictionary = { \"operation\": \"STATUS_%s\" % uaf_obb_auth_method,\n \"userName\": user.getUserId(),\n \"needDetails\": 1,\n \"oobStatusHandle\": uaf_obb_start_response_json[\"oobStatusHandle\"],\n }\n\n uaf_obb_status_request = json.dumps(uaf_obb_status_request_dictionary, separators=(',',':'))\n print \"UAF. Prepare for step 2. Prepared STATUS request: '%s' to send to '%s'\" % (uaf_obb_status_request, uaf_obb_server_uri)\n\n identity.setWorkingParameter(\"uaf_obb_auth_method\", uaf_obb_auth_method)\n identity.setWorkingParameter(\"uaf_obb_server_uri\", uaf_obb_server_uri)\n identity.setWorkingParameter(\"uaf_obb_start_response\", uaf_obb_start_response)\n identity.setWorkingParameter(\"qr_image\", uaf_obb_start_response_json[\"modeResult\"][\"qrCode\"][\"qrImage\"])\n identity.setWorkingParameter(\"uaf_obb_status_request\", uaf_obb_status_request)\n\n return True\n else:\n return False\n\n def getExtraParametersForStep(self, configurationAttributes, step):\n return Arrays.asList(\"uaf_auth_method\", \"uaf_obb_auth_method\", \"uaf_obb_server_uri\", \"uaf_obb_start_response\")\n\n def getCountAuthenticationSteps(self, configurationAttributes):\n return 2\n\n def getPageForStep(self, configurationAttributes, step):\n if (step == 2):\n return \"/auth/uaf/login.xhtml\"\n\n return \"\"\n\n def getNextStep(self, configurationAttributes, requestParameters, step):\n return -1\n\n def getLogoutExternalUrl(self, configurationAttributes, requestParameters):\n print \"Get external logout URL call\"\n return None\n\n def logout(self, configurationAttributes, requestParameters):\n return True\n\n def setRequestScopedParameters(self, identity):\n if self.registration_uri != None:\n identity.setWorkingParameter(\"external_registration_uri\", self.registration_uri)\n identity.setWorkingParameter(\"qr_options\", self.customQrOptions)\n\n def processBasicAuthentication(self, credentials):\n userService = CdiUtil.bean(UserService)\n authenticationService = CdiUtil.bean(AuthenticationService)\n\n user_name = credentials.getUsername()\n user_password = credentials.getPassword()\n\n logged_in = False\n if StringHelper.isNotEmptyString(user_name) and StringHelper.isNotEmptyString(user_password):\n logged_in = authenticationService.authenticate(user_name, user_password)\n\n if not logged_in:\n return None\n\n find_user_by_uid = authenticationService.getAuthenticatedUser()\n if find_user_by_uid == None:\n print \"UAF. Process basic authentication. Failed to find user '%s'\" % user_name\n return None\n \n return find_user_by_uid\n\n def findEnrollments(self, credentials):\n result = []\n\n userService = CdiUtil.bean(UserService)\n user_name = credentials.getUsername()\n user = userService.getUser(user_name, \"oxExternalUid\")\n if user == None:\n print \"UAF. Find enrollments. Failed to find user\"\n return result\n \n user_custom_ext_attribute = userService.getCustomAttribute(user, \"oxExternalUid\")\n if user_custom_ext_attribute == None:\n return result\n \n uaf_prefix = \"uaf:\"\n uaf_prefix_length = len(uaf_prefix) \n for user_external_uid in user_custom_ext_attribute.getValues():\n index = user_external_uid.find(uaf_prefix)\n if index != -1:\n enrollment_uid = user_external_uid[uaf_prefix_length:]\n result.append(enrollment_uid)\n \n return result\n\n def executePost(self, request_uri, request_data):\n httpService = CdiUtil.bean(HttpService)\n\n request_headers = { \"Content-type\" : \"application/json; charset=UTF-8\", \"Accept\" : \"application/json\" }\n\n try:\n http_service_response = httpService.executePost(self.http_client, request_uri, None, request_headers, request_data)\n http_response = http_service_response.getHttpResponse()\n except:\n print \"UAF. Validate POST response. Exception: \", sys.exc_info()[1]\n return None\n\n try:\n if not httpService.isResponseStastusCodeOk(http_response):\n print \"UAF. Validate POST response. Get invalid response from server: %s\" % str(http_response.getStatusLine().getStatusCode())\n httpService.consume(http_response)\n return None\n \n response_bytes = httpService.getResponseContent(http_response)\n response_string = httpService.convertEntityToString(response_bytes)\n httpService.consume(http_response)\n \n return response_string\n finally:\n http_service_response.closeConnection()\n return None\n", diff --git a/jans-linux-setup/jans_setup/setup_app/installers/fido.py b/jans-linux-setup/jans_setup/setup_app/installers/fido.py index c814e886857..6ea4ee769b7 100644 --- a/jans-linux-setup/jans_setup/setup_app/installers/fido.py +++ b/jans-linux-setup/jans_setup/setup_app/installers/fido.py @@ -43,6 +43,7 @@ def __init__(self): self.fido_document_certs_dir = os.path.join(self.fido2ConfigFolder, 'mds/cert') self.fido_document_tocs_dir = os.path.join(self.fido2ConfigFolder, 'mds/toc') + self.fido_document_authenticator_cert_dir = os.path.join(self.fido2ConfigFolder, 'authenticator_cert') def install(self): diff --git a/jans-linux-setup/jans_setup/templates/jans-fido2/docuemts.ldif b/jans-linux-setup/jans_setup/templates/jans-fido2/docuemts.ldif index 08a9f84f9ec..501a00b736c 100644 --- a/jans-linux-setup/jans_setup/templates/jans-fido2/docuemts.ldif +++ b/jans-linux-setup/jans_setup/templates/jans-fido2/docuemts.ldif @@ -33,7 +33,7 @@ displayName: yubico-u2f-ca-cert.crt document: %(yubico_u2f_ca_cert_base64)s inum: %(yubico_u2f_ca_cert_inum)s jansEnabled: true -jansFilePath: %(fido_document_tocs_dir)s +jansFilePath: %(fido_document_certs_dir)s jansLevel: 0 jansService: Fido2 MDS @@ -46,7 +46,7 @@ displayName: HyperFIDO_CA_Cert_V1.pem document: %(HyperFIDO_CA_Cert_V1_base64)s inum: %(HyperFIDO_CA_Cert_V1_inum)s jansEnabled: true -jansFilePath: %(fido_document_tocs_dir)s +jansFilePath: %(fido_document_authenticator_cert_dir)s jansLevel: 0 jansService: Fido2 MDS @@ -59,7 +59,7 @@ displayName: HyperFIDO_CA_Cert_V2.pem document: %(HyperFIDO_CA_Cert_V2_base64)s inum: %(HyperFIDO_CA_Cert_V2_inum)s jansEnabled: true -jansFilePath: %(fido_document_tocs_dir)s +jansFilePath: %(fido_document_authenticator_cert_dir)s jansLevel: 0 jansService: Fido2 MDS @@ -72,7 +72,7 @@ displayName: Apple_WebAuthn_Root_CA.pem document: %(Apple_WebAuthn_Root_CA_base64)s inum: %(Apple_WebAuthn_Root_CA_inum)s jansEnabled: true -jansFilePath: %(fido_document_tocs_dir)s +jansFilePath: %(fido_document_certs_dir)s jansLevel: 0 jansService: Fido2 MDS