diff --git a/external-authn/README.md b/external-authn/README.md new file mode 100644 index 0000000000..1f426db5f4 --- /dev/null +++ b/external-authn/README.md @@ -0,0 +1,160 @@ +# External Authn + +## Design +``` +Title External Authn + +actor Person +participant Browser +participant Website1 +participant Website2 +participant IDP +database cache + +Person->Browser: 1. Navigate to website1 +Browser->Website1: +Website1->Browser: 2. redirect +group Person Authn Script : Step One +Browser->IDP: 3. [GET] /oxauth/authorize?client_id=__&redirect_uri=__&state=__\n&nonce=__&prompt=none&scope=__\n&response_mode=__&response_type=__ +IDP->IDP: 4. generate jans_key +IDP<->cache: cache in session context\njans_key: {request params} +IDP->Browser: 5. redirect /internal.idp?________\nSet Pre-Authn Session Cookie +Browser->Website2: +end +Website2->Browser: 6. Display login page +Person->Browser: 7. Enter Username / PW +Browser->Website2: 8. (creds) +group ROPW script +Website2->IDP: 9. /oxauth/token?uid=__&pw="__&browser_ip=__&jans_key=__ +IDP->IDP: 10. update cache:\n "jans_key": "auth_success" +IDP->IDP: 11. retreive user claims +IDP->Website2:12. {\n "callback_url":"https://op-host/oxauth**/authorize?session_id={session_id}&redirect_uri={original_redirect}&...**",\n "userinfo": {"uid": "__",...}\n } +end +group Person Authn Script Step 2 +Website2->Browser: 13. write website 2 cookie;\n302 Location IDP callback_url +Browser->IDP: 14. callback_url_from_step_12 +IDP->IDP: 15. get session context +IDP->cache:16. delete jans_key\n lookup original redirect_uri +IDP->Browser: 17. write IDP session cookie\nand 302: Location original redirect_uri +end +Browser->Website1: +Website1->Website1: optional: 18 Validate id_token\n (claims optional) +``` +![](external-authn-diagram.png) + +Follow the instructions below to set up: + +## oxAuth Configuration +Above the **ox-auth** record of the **oxAuthConfiguration** table, enable a new attribute on the **oxAuthConfDynamic** field + +Example: +``` +"authorizationRequestCustomAllowedParameters": [ + { + "paramName": "jansKey", + "returnInResponse": false + } +] +``` + +## Enable Custom Script + +- ### Person Authentication - External Authn + +Create a new record in table **oxCustomScript**. +``` +INSERT INTO oxCustomScript ( doc_id, objectClass, dn, displayName, oxEnabled, oxRevision, oxScript, oxAlias, oxScriptType, oxModuleProperty, programmingLanguage, oxScriptError, oxConfigurationProperty, inum, description, oxLevel ) +VALUES ( 'PA01-EA01', 'oxCustomScript', 'inum=PA01-EA01,ou=scripts,o=gluu', 'pa-external-authn', 0, 1, '', '{"v": []}', 'person_authentication', '{"v": ["{\\"value1\\":\\"usage_type\\",\\"value2\\":\\"interactive\\",\\"description\\":\\"\\"}", "{\\"value1\\":\\"location_type\\",\\"value2\\":\\"ldap\\",\\"description\\":\\"\\"}"]}', 'python', NULL, '{"v": ["{\\"value1\\":\\"urlstep1\\",\\"value2\\":\\"http://demoexample.net:81\\",\\"hide\\":false,\\"description\\":\\"Url to return in step 1\\"}"]}', 'PA01-EA01', 'PA External Authn', 10 ); +``` + +Modify the **oxConfigurationProperty** field by replacing **URL_REDIRECT_URI** with the url that you want to return to the first step +``` +'{"v": ["{\\"value1\\":\\"urlstep1\\",\\"value2\\":\\"{URL_REDIRECT_URI}\\",\\"hide\\":false,\\"description\\":\\"Url to return in step 1\\"}"]}' +``` + +Modify the **oxScript** field by adding the content of the following link: [PersonAuthentication Script](pa-external-authn.py) + +- ### ROPC (Resource Owner Password Credentials) Script - External Authn + +Create a new record in table **oxCustomScript**. +``` +INSERT INTO oxCustomScript ( doc_id, objectClass, dn, displayName, oxEnabled, oxRevision, oxScript, oxAlias, oxScriptType, oxModuleProperty, programmingLanguage, oxScriptError, oxConfigurationProperty, inum, description, oxLevel ) +VALUES ( 'ROPC-EA01', 'oxCustomScript', 'inum=ROPC-EA01,ou=scripts,o=gluu', 'ropc-external-authn', 0, 1, '', '{"v": []}', 'resource_owner_password_credentials', '{"v": ["{\\"value1\\":\\"location_type\\",\\"value2\\":\\"ldap\\",\\"description\\":\\"\\"}"]}', 'python', NULL, '{"v": []}', 'ROPC-EA01', 'ROPC External Authn', 1 ); +``` + +Modify the **oxScript** field by adding the content of the following link: [ROPC (Resource Owner Password Credentials) Script](ropc-external-authn.py) + +- ### Update Token Script - External Authn + +Create a new record in table **oxCustomScript**. +``` +INSERT INTO oxCustomScript ( doc_id, objectClass, dn, displayName, oxEnabled, oxRevision, oxScript, oxAlias, oxScriptType, oxModuleProperty, programmingLanguage, oxScriptError, oxConfigurationProperty, inum, description, oxLevel ) +VALUES ( 'UPDT-EA01', 'oxCustomScript', 'inum=UPDT-EA01,ou=scripts,o=gluu', 'update-token-external-authn', 0, 1, '', '{"v": []}', 'update_token', '{"v": ["{\\"value1\\":\\"location_type\\",\\"value2\\":\\"ldap\\",\\"description\\":\\"\\"}"]}', 'python', NULL, '{"v": []}', 'UPDT-EA01', 'Update token External Authn', 1 ); +``` + +Modify the **oxScript** field by adding the content of the following link: [Update Token Script](ut-external-authn.py) + +In this script you can choose whether to use the header or payload of the **id_token** for the **callback_url**: +``` +jsonWebResponse.getHeader().setClaim("callback_url", jsonValCallbackUrl) +jsonWebResponse.getClaims().setClaim("callback_url", jsonValCallbackUrl) +``` + +## Enable custom script on the Client +In the table **oxAuthClient** modify the field **oxAttributes** associating the custom scripts configured previously +``` +"updateTokenScriptDns": ["inum=UPDT-EA01,ou=scripts,o=gluu"], +"ropcScripts": ["inum=ROPC-EA01,ou=scripts,o=gluu"], +``` + +And in the field **oxAuthDefaultAcrValues** add this value: +``` +{"v": ["pa-external-authn"]} +``` + +## Call Flow +- ### Step 1: /authorize +Request: +``` +curl --location --request GET 'https://{your-gluu-url}/oxauth/restv1/authorize?response_type=code&client_id=14e36e18-1d51-41ac-a4cf-a7dc677f53a5&scope=openid+profile+address+email&redirect_uri=https://jans.localhost/jans-auth-rp/home.htm&state=a84dd61f-533c-46a4-9315-a66fda3e9a4e&nonce=80e6bd2b-eb78-48b9-be9c-6bb33ef80991&ui_locales=&claims_locales=&request_session_id=false&acr_values=' +``` +Response: (return the **redirect_uri** with jansKey) +``` +http://demoexample.net:81?jansKey=46340f40-a554-46b1-9246-37c2e869919f +``` + +- ### Step 2: /token +Request: (**Authorization** = Basic base64(client_id:client_secret)) +``` +curl --location --request POST 'https://{your-gluu-url}/oxauth/restv1/token' \ +--header 'Authorization: Basic MTRlMzZlMTgtMWQ1MS00MWFjLWE0Y2YtYTdkYzY3N2Y1M2E1Ojk5NzE4NWU1LTc2NGUtNGE4Yi1hNjYwLTdjZmQ4NzJhNjc0Ng==' \ +--header 'Content-Type: application/x-www-form-urlencoded' \ +--data-urlencode 'grant_type=password' \ +--data-urlencode 'username=test_user' \ +--data-urlencode 'password=test_user_password' \ +--data-urlencode 'scope=openid' \ +--data-urlencode 'jansKey=46340f40-a554-46b1-9246-37c2e869919f' +``` +Response: (id_token contains in header or payload callback_url) +``` +{ + "access_token": "a0878887-b998-4da4-aa0b-4e74bd9a4441", + "refresh_token": "d8b618ac-9d9c-4b90-9cac-aafb1e38e82e", + "scope": "openid", + "id_token": "eyJjYWxsYmFja191cmwiOiJodHRwczovL2phbnMubG9jYWxob3N0L2phbnMtYXV0aC9yZXN0djEvYXV0aG9yaXplP3Jlc3BvbnNlX3R5cGU9Y29kZSZzZXNzaW9uX2lkPWI1MDFmNzg0LTY0MTAtNDIyYy1iYWQ0LWU0MTNiYTViMjI1NSZyZWRpcmVjdF91cmk9aHR0cHMlM0ElMkYlMkZqYW5zLmxvY2FsaG9zdCUyRmphbnMtYXV0aC1ycCUyRmhvbWUuaHRtJmNsaWVudF9pZD0xNGUzNmUxOC0xZDUxLTQxYWMtYTRjZi1hN2RjNjc3ZjUzYTUiLCJraWQiOiIxNmEyMmIwMy03YjUzLTQxY2QtYWE3OS01YjI1ZjNlY2QzOGNfc2lnX3JzMjU2IiwidHlwIjoiand0IiwiYWxnIjoiUlMyNTYifQ.eyJjYWxsYmFja191cmwiOiJodHRwczovL2phbnMubG9jYWxob3N0L2phbnMtYXV0aC9yZXN0djEvYXV0aG9yaXplP3Jlc3BvbnNlX3R5cGU9Y29kZSZzZXNzaW9uX2lkPWI1MDFmNzg0LTY0MTAtNDIyYy1iYWQ0LWU0MTNiYTViMjI1NSZyZWRpcmVjdF91cmk9aHR0cHMlM0ElMkYlMkZqYW5zLmxvY2FsaG9zdCUyRmphbnMtYXV0aC1ycCUyRmhvbWUuaHRtJmNsaWVudF9pZD0xNGUzNmUxOC0xZDUxLTQxYWMtYTRjZi1hN2RjNjc3ZjUzYTUiLCJhdWQiOiIxNGUzNmUxOC0xZDUxLTQxYWMtYTRjZi1hN2RjNjc3ZjUzYTUiLCJhY3IiOiJzaW1wbGVfcGFzc3dvcmRfYXV0aCIsInN1YiI6InpMM3FrWFVwZE9OOXoxRDNNVUkyRG1CTHd3MzA1RUt4eWY3al8zb0oyaDQiLCJjb2RlIjoiNzg4OTA4ZTAtMmM3MC00YjE1LWFkZmUtYWZlMDBiMTgyMTkxIiwiYW1yIjpbXSwiaXNzIjoiaHR0cHM6Ly9qYW5zLmxvY2FsaG9zdCIsImV4cCI6MTY1OTc1ODA4MywiZ3JhbnQiOiJwYXNzd29yZCIsImlhdCI6MTY1OTc1NDQ4Mywic2lkIjoiODA0OGZjYmYtM2RjNC00YjFhLTgwYjktNmU1NTkzZTJhOWMwIiwib3hPcGVuSURDb25uZWN0VmVyc2lvbiI6Im9wZW5pZGNvbm5lY3QtMS4wIn0.u0sK9Yccf-P0OLQe0cKz75dF3cKQzQt9QpoHbqBsuIgXb4YwzDTWSuVM055USo5iO9P3KUiIGnMs6WPrZa-xcH84oKWsjF4TnAHdtwE_1xSofxDUU1nSdg8V3mRjHmZKWAvSmGtWTJFqTNGJKQsz1xrTpZ4ZAsI8Ey5OUNIhLsS6BIrFixLm3Sjufe4I2hiTtUPXb1PSYkPgHPZI00h8h4NDspPM9syufMbSLi-HN1aTQaJCONw2X-4KnvLGq1utX7qryclW1pq17W2j6Z49CjCW5ZtstK2p2FRoPwnInXNNr6vqSrpWR6pY9Uus7LHZZbg2DWKBASyfdjN6ecQaIw", + "token_type": "Bearer", + "expires_in": 299 +} +``` + +- ### Step 3: callback_uri (/authorize) + +Request: +``` +curl --location --request GET 'https://{your-gluu-url}/oxauth/restv1/authorize?response_type=code&session_id=b501f784-6410-422c-bad4-e413ba5b2255&redirect_uri=https%3A%2F%2Fjans.localhost%2Fjans-auth-rp%2Fhome.htm&client_id=14e36e18-1d51-41ac-a4cf-a7dc677f53a5' +``` + +Response: (return to the **redirect_uri**) +``` +https://jans.localhost/jans-auth-rp/home.htm?code=441688df-8f36-4e2c-8174-18d23cc88049&acr_values=pa-external-authn&session_id=7ee59d72-d59a-49ce-a0cb-19c4fcfc404c&session_state=c3f595a892208e3d237722ad06d830f199295ccc355827c436fff71509401eae.a505421b-a332-4604-8772-6ca345c4a4b9 +``` \ No newline at end of file diff --git a/external-authn/external-authn-diagram.png b/external-authn/external-authn-diagram.png new file mode 100644 index 0000000000..44ec4931f1 Binary files /dev/null and b/external-authn/external-authn-diagram.png differ diff --git a/external-authn/pa-external-authn.py b/external-authn/pa-external-authn.py new file mode 100644 index 0000000000..00d123beb3 --- /dev/null +++ b/external-authn/pa-external-authn.py @@ -0,0 +1,128 @@ +# PersonAuthentication External Authn + +from org.gluu.model.custom.script.type.auth import PersonAuthenticationType +from org.gluu.service.cdi.util import CdiUtil +from org.gluu.oxauth.security import Identity +from org.gluu.oxauth.service import AuthenticationService +from org.gluu.util import StringHelper +from org.gluu.oxauth.util import ServerUtil +from org.gluu.oxauth.service import SessionIdService +from org.gluu.oxauth.service import CookieService +from org.gluu.service.cache import CacheProvider +from javax.faces.context import ExternalContext +from java.util import HashMap +from org.gluu.oxauth.service import UserService, RequestParameterService +from org.gluu.oxauth.service.net import HttpService +from javax.faces.context import FacesContext +from org.gluu.jsf2.service import FacesService + +import java +import uuid + +class PersonAuthentication(PersonAuthenticationType): + def __init__(self, currentTimeMillis): + self.currentTimeMillis = currentTimeMillis + + def init(self, customScript, configurationAttributes): + print "PA External Authn. Initialization" + print "PA External Authn. Initialized successfully configurationAttributes = %s" % configurationAttributes + + self.url_step1 = None + + # Get Custom Properties + try: + self.url_step1 = configurationAttributes.get("urlstep1").getValue2() + print "PA External Authn. Initialization. url_step1: '%s'" % self.url_step1 + except: + print 'Missing required configuration attribute "urlstep1"' + + return True + + def destroy(self, configurationAttributes): + print "PA External Authn. Destroy" + print "PA External Authn. Destroyed successfully" + return True + + def getAuthenticationMethodClaims(self, requestParameters): + return None + + def getApiVersion(self): + return 11 + + def isValidAuthenticationMethod(self, usageType, configurationAttributes): + return True + + def getAlternativeAuthenticationMethod(self, usageType, configurationAttributes): + return None + + def authenticate(self, configurationAttributes, requestParameters, step): + print "PA External Authn. Authenticate for step: %s" % step + return True + + def prepareForStep(self, configurationAttributes, requestParameters, step): + if (step == 1): + return True + else: + return False + + def getExtraParametersForStep(self, configurationAttributes, step): + return None + + def getCountAuthenticationSteps(self, configurationAttributes): + return 1 + + def getPageForStep(self, configurationAttributes, step): + print "PA External Authn. GetPageForStep for step: %s" % step + + externalContext = CdiUtil.bean(ExternalContext) + sessionId = ServerUtil.getFirstValue(externalContext.getRequestParameterValuesMap(), "session_id") + if (sessionId == None): + # Retrieve sessionId from request parameters and validate it + redirectUri = ServerUtil.getFirstValue(externalContext.getRequestParameterValuesMap(), "redirect_uri") + if (redirectUri == None or StringHelper.isEmpty(redirectUri)): + print "PA External Authn. GetPageForStep redirect_uri is null or empty" + return "" + print "PA External Authn. GetPageForStep redirect_uri '%s' found in request parameters" % redirectUri + + clientId = ServerUtil.getFirstValue(externalContext.getRequestParameterValuesMap(), "client_id") + if (clientId == None or StringHelper.isEmpty(clientId)): + print "PA External Authn. GetPageForStep client_id is null or empty" + return "" + print "PA External Authn. GetPageForStep client_id '%s' found in request parameters" % clientId + + # Generate jansKey + jansKey = str(uuid.uuid4()); + print "PA External Authn. GetPageForStep jansKey '%s' generated" % jansKey + + # Create JSON Values + jsonValues = {} + jsonValues["redirectUri"] = str(redirectUri) + jsonValues["clientId"] = str(clientId) + + cacheProvider = CdiUtil.bean(CacheProvider) + cacheProvider.put(300, jansKey, jsonValues) + print "PA External Authn. GetPageForStep jansKey '%s' added to cache: %s" % (jansKey, jsonValues) + + requestParameterService = CdiUtil.bean(RequestParameterService) + parametersMap = HashMap() + parametersMap.put("jansKey", jansKey) + callBackUrl = requestParameterService.parametersAsString(parametersMap) + callBackUrl = "%s?%s" % (self.url_step1, callBackUrl) + + print "PA External Authn. GetPageForStep redirect to %s" % callBackUrl + + facesService = CdiUtil.bean(FacesService) + facesService.redirectToExternalURL(callBackUrl) + + return "" + + return "postlogin.xhtml" + + def getNextStep(self, configurationAttributes, requestParameters, step): + return -1 + + def getLogoutExternalUrl(self, configurationAttributes, requestParameters): + return None + + def logout(self, configurationAttributes, requestParameters): + return True diff --git a/external-authn/ropc-external-authn.py b/external-authn/ropc-external-authn.py new file mode 100644 index 0000000000..559860a308 --- /dev/null +++ b/external-authn/ropc-external-authn.py @@ -0,0 +1,145 @@ +# ResourceOwnerPasswordCredentials External Authn + +from org.gluu.model.custom.script.type.owner import ResourceOwnerPasswordCredentialsType +from org.gluu.oxauth.service import AuthenticationService, SessionIdService +from org.gluu.oxauth.model.common import SessionIdState +from org.gluu.oxauth.security import Identity +from org.gluu.service.cdi.util import CdiUtil +from org.gluu.oxauth.model.authorize import AuthorizeRequestParam +from org.gluu.oxauth.model.config import Constants +from org.gluu.util import StringHelper +from java.lang import String +from java.util import Date, HashMap +from org.gluu.service.cache import CacheProvider + +from org.gluu.oxauth.service import RequestParameterService +from org.gluu.oxauth.service.net import HttpService +from javax.faces.context import FacesContext +from org.gluu.jsf2.service import FacesService + +class ResourceOwnerPasswordCredentials(ResourceOwnerPasswordCredentialsType): + def __init__(self, currentTimeMillis): + self.currentTimeMillis = currentTimeMillis + + def init(self, customScript, configurationAttributes): + print "ROPC External Authn. Initializing ..." + print "ROPC External Authn. Initialized successfully" + return True + + def destroy(self, configurationAttributes): + print "ROPC External Authn. Destroying ..." + print "ROPC External Authn. Destroyed successfully" + return True + + def getApiVersion(self): + return 11 + + def authenticate(self, context): + print "ROPC External Authn. Authenticate" + + # Retrieve jansKey from request parameters + jansKey = context.getHttpRequest().getParameter("jansKey") + if (jansKey == None or StringHelper.isEmpty(jansKey)): + print "ROPC External Authn. Authenticate. jansKey not found or empty" + return False + print "ROPC External Authn. Authenticate. jansKey '%s' found in request" % jansKey + + cacheProvider = CdiUtil.bean(CacheProvider) + jsonValues = cacheProvider.get(jansKey) + if (jsonValues == None): + print "ROPC External Authn. Authenticate. Could not find jsonValues in cache" + return False + print "ROPC External Authn. Authenticate. jsonValues found in cache" + + # Do generic authentication + authenticationService = CdiUtil.bean(AuthenticationService) + + username = context.getHttpRequest().getParameter("username") + password = context.getHttpRequest().getParameter("password") + result = authenticationService.authenticate(username, password) + if not result: + print "ROPC External Authn. Authenticate. Could not authenticate user '%s' " % username + return False + + context.setUser(authenticationService.getAuthenticatedUser()) + print "ROPC External Authn. Authenticate. User '%s' authenticated successfully" % username + + # Get cusom parameters from request + customParam1Value = context.getHttpRequest().getParameter("custom1") + customParam2Value = context.getHttpRequest().getParameter("custom2") + + customParameters = {} + customParameters["custom1"] = customParam1Value + customParameters["custom2"] = customParam2Value + print "ROPC External Authn. Authenticate. User '%s'. Creating authenticated session with custom attributes: '%s'" % (username, customParameters) + + session = self.createNewAuthenticatedSession(context, customParameters) + + # This is needed to allow store in token entry sessionId + authenticationService.configureEventUser(session) + print "ROPC External Authn. Authenticate. User '%s'. Created authenticated session: '%s'" % (username, customParameters) + + callbackUrl = self.createCallbackUrl(context, session, jsonValues) + if (callbackUrl != None and StringHelper.isNotEmpty(callbackUrl)): + jsonValues["callbackUrl"] = str(callbackUrl) + cacheProvider.put(300, jansKey, jsonValues) + print "ROPC External Authn. Authenticate. CallbackUrl stored in cache: '%s'" % callbackUrl + + return True + + def createNewAuthenticatedSession(self, context, customParameters={}): + sessionIdService = CdiUtil.bean(SessionIdService) + + user = context.getUser() + client = CdiUtil.bean(Identity).getSessionClient().getClient() + + # Add mandatory session parameters + sessionAttributes = HashMap() + sessionAttributes.put(Constants.AUTHENTICATED_USER, user.getUserId()) + sessionAttributes.put(AuthorizeRequestParam.CLIENT_ID, client.getClientId()) + sessionAttributes.put(AuthorizeRequestParam.PROMPT, "") + + # Add custom session parameters + for key, value in customParameters.iteritems(): + if StringHelper.isNotEmpty(value): + sessionAttributes.put(key, value) + + # Generate authenticated session + sessionId = sessionIdService.generateAuthenticatedSessionId(context.getHttpRequest(), user.getDn(), sessionAttributes) + + print "ROPC External Authn. Generated sessionId. DN: '%s'" % sessionId.getDn() + + return sessionId + + def createCallbackUrl(self, context, sessionId={}, jsonValues={}): + print "ROPC External Authn. CreateCallbackUrl context: '%s'" % context + + # Retrieve redirectUri from cache using jansKey + jsonValRedirectUri = jsonValues.get("redirectUri") + if (jsonValRedirectUri == None): + print "ROPC External Authn. CreateCallbackUrl. redirectUri not found in cache" + return "" + print "ROPC External Authn. CreateCallbackUrl. redirectUri found '%s' in cache" % jsonValRedirectUri + + # Retrieve clientId from cache using jansKey + jsonValClientId = jsonValues.get("clientId") + if (jsonValClientId == None): + print "ROPC External Authn. CreateCallbackUrl. clientId not found in cache" + return "" + print "ROPC External Authn. CreateCallbackUrl. clientId found '%s' in cache" % jsonValClientId + + parameterMap = HashMap() + parameterMap.put("response_type", "code") + parameterMap.put("client_id", jsonValClientId) + parameterMap.put("redirect_uri", jsonValRedirectUri) + parameterMap.put("session_id", sessionId.getId()) + + requestParameterService = CdiUtil.bean(RequestParameterService) + parameterString = requestParameterService.parametersAsString(parameterMap) + + authorizeEndpoint = context.getAppConfiguration().getAuthorizationEndpoint() + jansUrl = '%s?%s' % (authorizeEndpoint, parameterString) + + print "ROPC External Authn. CreateCallbackUrl. jansUrl '%s'" % jansUrl + + return jansUrl \ No newline at end of file diff --git a/external-authn/ut-external-authn.py b/external-authn/ut-external-authn.py new file mode 100644 index 0000000000..d5c1c8ba40 --- /dev/null +++ b/external-authn/ut-external-authn.py @@ -0,0 +1,73 @@ +# UpdateToken External Authn + +from org.gluu.model.custom.script.type.token import UpdateTokenType +from org.gluu.service.cache import CacheProvider +from org.gluu.service.cdi.util import CdiUtil +from org.gluu.util import StringHelper + +class UpdateToken(UpdateTokenType): + def __init__(self, currentTimeMillis): + self.currentTimeMillis = currentTimeMillis + + def init(self, customScript, configurationAttributes): + print "UT External Authn. Initializing ..." + print "UT External Authn. Initialized successfully" + + return True + + def destroy(self, configurationAttributes): + print "UT External Authn. Destroying ..." + print "UT External Authn. Destroyed successfully" + return True + + def getApiVersion(self): + return 11 + + def modifyIdToken(self, jsonWebResponse, context): + + # Retrieve jansKey from cache + jansKey = context.getHttpRequest().getParameter("jansKey") + if (jansKey == None or StringHelper.isEmpty(jansKey)): + print "UT External Authn. ModifyIdToken Could not find jansKey in request" + return False + print "UT External Authn. ModifyIdToken jansKey '%s' found in request" % jansKey + + # Retrieve jsonValues from cache using jansKey + cacheProvider = CdiUtil.bean(CacheProvider) + jsonValues = cacheProvider.get(jansKey) + if (jsonValues == None): + print "UT External Authn. ModifyIdToken Could not find jansKey in cache" + return False + print "UT External Authn. ModifyIdToken jansKey found in cache" + + # Retrieve redirectUri from cache using jansKey + jsonValCallbackUrl = jsonValues.get("callbackUrl") + if (jsonValCallbackUrl == None): + print "UT External Authn. ModifyIdToken Could not find callbackUrl in cache" + return False + print "UT External Authn. ModifyIdToken callbackUrl '%s' found in cache" % jsonValCallbackUrl + + # Decide where to set the callback_uri in header or payload + jsonWebResponse.getHeader().setClaim("callback_url", jsonValCallbackUrl) + jsonWebResponse.getClaims().setClaim("callback_url", jsonValCallbackUrl) + + # Remove jansKey from cache + cacheProvider.remove(jansKey) + print "UT External Authn. ModifyIdToken jansKey removed from cache" + + return True + + def modifyRefreshToken(self, refreshToken, context): + return True + + def modifyAccessToken(self, accessToken, context): + return True + + def getRefreshTokenLifetimeInSeconds(self, context): + return 0 + + def getIdTokenLifetimeInSeconds(self, context): + return 0 + + def getAccessTokenLifetimeInSeconds(self, context): + return 0