By: Benjamin Sebbah user 01 Jun 2016 at 9:36 a.m. CDT

13 Responses
Benjamin Sebbah gravatar
Hello, I'm creating a custom script authentication to authenticate against a SOAP webservice. I have a jar package containing java methods to authenticate against the web service so that I don't have to handle the web flows. I've added the jar in the /opt/tomcat/endorsed (it didn't exist I had to create it). I've used the basic template and modified the authenticate method to use my java methods. I've been able to convert the java code into jython and when I access a SAML SP federated in Gluu, I'm redirected and asked to enter my credentials. I enter login and password (which are not valid in Gluu local repo but are valid in my WS) in the form it is validated against the webservice which gives me back an authorization code. Now I'm stuck. If the method sends a non empty value (i.e. a string), I need to let the user access the requested page and add the value in an attribute in the saml response (and if the method sends an empty value, the user needs to try to auth again). Any help would be very appreciated. If it would help here is where I stopped: ``` #define the object as needed try: _login__return = object.auth_method(user_name, user_password) except MyMethod_Exception, e: print "MyCustomer. Expected exception: MyMethod_Exception has occurred. :" + e.toString() logged_in = False if ( _login__return != None ): print "MyCustomer. login success: result=" + _login__return logged_in = True else: print "MyCustomer. login failure" # this is never printed no matter what I do... #Don't know what to do next! ``` FYI, I'm well able to see the log line below but as I said, not sure what to do next: MyCustomer. login success: result=xxxxx Thanks! Ben

By Michael Schwartz Account Admin 01 Jun 2016 at 9:47 a.m. CDT

Michael Schwartz gravatar
Yuriy, can you give some ideas to Ben here?

By Yuriy Zabrovarnyy staff 01 Jun 2016 at 10:57 a.m. CDT

Yuriy Zabrovarnyy gravatar
Ben, If after your internal authentication you need to redirect to some page then please return it in getPageForStep() method (if you leave it blank than it will redirect you to internal login page which in your case is wrong). I guess this [sample](https://github.com/GluuFederation/oxAuth/blob/master/Server/integrations/basic.change_password/BasicPassowrdUpdateExternalAuthenticator.py) is quite close on what you are looking for. Also other samples [here](https://github.com/GluuFederation/oxAuth/tree/master/Server/integrations). Let me know whether it helps. Thanks, Yuriy

By Benjamin Sebbah user 01 Jun 2016 at 12:07 p.m. CDT

Benjamin Sebbah gravatar
Hi Yuriy, Thanks for your answer. To sum up my post I am in a SAML SP=>IdP situation (where Gluu is the IdP) and I have 2 questions regarding custom authentication: 1) In the jython script, if my custom authentication is a success, how to redirect user to the page (s)he requested in the first place before being redirected in Gluu's IdP? (if I understand correctly, your answer is a static redirect which wouldn't match my need) 2) My custom authentication method (the one from my jar) returns me a String (a kind of token), how to add this value (that I was able to get during the authenticate method) in the saml response? And finally I have another question: 3) how to have the web admin interface using the "basic" authentication script and a SP using a custom script? About 1, I can see in the saml sample that you are auto enrolling users, is that mandatory (I'm not doing that, maybe this is why it's not working)? Thanks, Ben

By Yuriy Zabrovarnyy staff 02 Jun 2016 at 3:48 a.m. CDT

Yuriy Zabrovarnyy gravatar
Ben, 1) If you have just one step authentication then if you have: a) step count = 1 b) for step 1 return True in authenticate() then successful authentication event is thrown inside server (check this code snippet https://github.com/GluuFederation/oxAuth/blob/master/Server/src/main/java/org/xdi/oxauth/auth/Authenticator.java#L201-326) which leads to redirection to Authorization Page where user can "Allow" or "Deny" access c) you can omit even this authorization page and set your client to "Trusted" (https://gluu.org/docs/integrate/openid-connect/#client-registration). In this case after successful authentication user will be redirected to "redirect_uri" that was provided in original authorization request. 2) Not sure I got what you meant here. Saml response is provided/returned or you would like to construct it somewhere inside your jar and send outside? 3) each authorization request has acr_values parameter. (https://gluu.org/docs/api/oic-authorization/) acr_values=basic triggers basic authentication script. acr_values=<your script> triggers your custom script. Thanks, Yuriy

By Yuriy Movchan staff 02 Jun 2016 at 8:19 a.m. CDT

Yuriy Movchan gravatar
Hi Ben, I can add few words to Yuriy Z answer. 2) In default authentication model oxAuth don't know Saml. The high level workflow is the next: request->idp->oxAuth->idp->response In idp we added few servlets to handle authentication request and redirect authentication to oxAuth. Hence we don't change default IDP behavior. There is script which allows inboundSaml: https://github.com/GluuFederation/oxAuth/blob/master/Server/integrations/saml/SamlExternalAuthenticator.py 3) In oxTust GUI in authentication tab there are 2 dropdown lists. One is default acr for oxAuth. And second one is default acr for oxTrust.

By Benjamin Sebbah user 02 Jun 2016 at 11:55 a.m. CDT

Benjamin Sebbah gravatar
Thanks. This helps a lot. I was able to go a little bit further (you can't see it, but there is joy all around me). As this is just a POC, I cheated and created the user manually in Gluu's repo so that I don't have to create it as you do in the saml auto enroll. But if the webservice auth is a success, I update the password: ``` if ( _login__return != None ): "MyCustomer. login success: result=" + _login__return logged_in = True #return True else: print "MyCustomer. login failure" print "MyCustomer. Log test" if (StringHelper.isNotEmptyString(user_name) and StringHelper.isNotEmptyString(user_password)): userService = UserService.instance() find_user_by_uid = userService.getUser(user_name) if (find_user_by_uid == None): print "MyCustomer user not created in the first place" return False print "MyCustomer. user found, we'll update the password" find_user_by_uid.setAttribute("userPassword", user_password) userService.updateUser(find_user_by_uid) print "MyCustomer password updated" logged_in = userService.authenticate(user_name, user_password) ``` So now I can authenticate against my webservice and access the SP! Now I need to transmit the value of the string _login__return to the application, what would be the best way to do that? Thanks again.

By Benjamin Sebbah user 06 Jun 2016 at 3:21 a.m. CDT

Benjamin Sebbah gravatar
Hello, Any help would be appreciated on my last question: > Now I need to transmit the value of the string _login__return to the application, what would be the best way to do that? Thanks in advance. Regards, Ben

By Yuriy Movchan staff 07 Jun 2016 at 12:25 p.m. CDT

Yuriy Movchan gravatar
Hi Benjamin, If I understand correctly you need to return this value to application (client) which calls oxAuth for authorization. In this case we can return it as OpenId claim. We can use dynamic scope script. Here is example how to get value from LDAP session from dynamic scope script: def update(self, dynamicScopeContext, configurationAttributes): print "MT. Dynamic scope. Update" requestedDynamicScopes = dynamicScopeContext.getDynamicScopes() authorizationGrant = dynamicScopeContext.getAuthorizationGrant() sessionDn = authorizationGrant.getSessionDn() user = dynamicScopeContext.getUser() userId = user.getUserId() userService = UserService.instance() userInum = userService.getUserInum(user) jsonWebResponse = dynamicScopeContext.getJsonWebResponse() claims = jsonWebResponse.getClaims() if StringHelper.isEmpty(sessionDn): print "MT. Dynamic scope. Update. Failed to determine sessionDn" return False sessionStateService = SessionStateService.instance() sessionState = sessionStateService.getSessionByDN(sessionDn) sessionAttributes = sessionStateService.getSessionAttributes(sessionState) print "MT. Dynamic scope. Update. sessionDn: %s, sessionAttributes: %s" % (sessionDn, sessionAttributes) # Find used device_id in session attribute if not sessionAttributes.containsKey("oxpush2_u2f_device_id"): print "MT. Dynamic scope. Update. There is no oxpush2_u2f_device_id associated with this request" return None usedDeviceId = sessionAttributes.get("oxpush2_u2f_device_id") After that you can add 'usedDeviceId' to list of result claims. But you need to use lastest oxAuth build to use this functionality: http://ox.gluu.org/maven/org/xdi/oxauth-server/2.4.3-SNAPSHOT/oxauth-server-2.4.3-SNAPSHOT.war

By Yuriy Movchan staff 07 Jun 2016 at 12:30 p.m. CDT

Yuriy Movchan gravatar
In this dynamic script we uses valirable "oxpush2_u2f_device_id" which we stoted earlier in authentication script. Here is exaple how to store it: def authenticate(self, configurationAttributes, requestParameters, step): context = Contexts.getEventContext() context.set("oxpush2_u2f_device_id", "dummy_device_id") ... def getExtraParametersForStep(self, configurationAttributes, step): if step == 1: return Arrays.asList("oxpush2_u2f_device_id") return None

By Yuriy Movchan staff 07 Jun 2016 at 12:31 p.m. CDT

Yuriy Movchan gravatar
Also I have not about inital post. This folder /opt/tomcat/endorsed exists in 2.4.3. Please re-download rpm/deb again... Regarding library. Yes, you can put custom library into endorsed but starting from 2.4.3 you can put it into /var/gluu/webapps/oxauth/libs.

By Benjamin Sebbah user 07 Jun 2016 at 12:35 p.m. CDT

Benjamin Sebbah gravatar
Thanks, but I'm doing SAML not openid connect. Can we push the value as a http header that will reach the application?

By Benjamin Sebbah user 09 Jun 2016 at 3:03 a.m. CDT

Benjamin Sebbah gravatar
I'm suggesting http header but any solution (that doesn't involve oidc because, as explained, it's out of scope) would be appreciated.

By Yuriy Movchan staff 13 Jun 2016 at 6:03 a.m. CDT

Yuriy Movchan gravatar
Hi Benjamin, As far a I understand oxAuth should returns your header in authorization response. Example: https://ce-dev.gluu.org/identity/authentication/authcode#session_state=e42acc65-4340-4651-8954-6fc2e0f835e1&scope=user_name+email+openid+profile&state&code=1b7da8bd-3425-417e-a869-a6b523b18016&id_token=eyJ0eXAiOiJ... Header1: value_1_from script Header2: value_2_from script Am I understand your idea correctly? I'm opened issue about this. https://github.com/GluuFederation/oxAuth/issues/234 Regards, Yura