By: Doug Appleyard user 18 Sep 2017 at 10:29 a.m. CDT

12 Responses
Doug Appleyard gravatar
In Gluu 3.0.2, I was able to log in with a user not defined locally. It would get to my custom Person Authentication script and in the Python, I would add the user (with just the userid), then proceed with my external validation API call. Now (3.1.0), it does not get to the Python script. Instead it quickly returns "incorrect name or password" with these logs: 2017-09-18 11:22:08,380 ERROR [qtp1020391880-15] [org.xdi.oxauth.service.SessionIdService] (SessionIdService.java:243) - Faces context returns null for http request object. 2017-09-18 11:22:08,380 INFO [qtp1020391880-15] [org.xdi.oxauth.auth.Authenticator] (Authenticator.java:153) - Authentication failed for 'naa168997' Do all users need to be added/imported now before they can be used for login? If I add a user manually from the Gluu GUI (in either version), I am forced to enter a password. Then when I log in, it validates the user locally and does not get to my Person Auth script. Thanks

By Aliaksandr Samuseu staff 18 Sep 2017 at 10:39 a.m. CDT

Aliaksandr Samuseu gravatar
Hi, Doug. Could you elaborate a bit what "undefined" means in this case? In previous versions of Gluu, unless you had a corresponding user entry in Gluu's internal LDAP server, it would have denied you access as well, at some point. >In Gluu 3.0.2, I was able to log in with a user not defined locally. It would get to my custom Person Authentication script and in the Python, I would add the user (with just the userid), then proceed with my external validation API call. Seeing the script would make it easier to understand, I believe. Is it possible? >If I add a user manually from the Gluu GUI (in either version), I am forced to enter a password. Then when I log in, it validates the user locally and does not get to my Person Auth script. That's strange. Do you mean that if user with the same uid and some password assigned to it exists in Gluu's LDAP, it won't call your custom script at all? If it's the case, could you provide screnshots of your "Manage authentication" web UI pages, in addition to script's sources I've asked before? We may need to investigate it.

By Michael Schwartz Account Admin 18 Sep 2017 at 11 a.m. CDT

Michael Schwartz gravatar
Which authentication script are you using? Can you paste it into the ticket?

By Doug Appleyard user 18 Sep 2017 at 11:20 a.m. CDT

Doug Appleyard gravatar
In Gluu 3.0.2, I can attempt login with a brand-new userid which is not in Gluu's LDAP. It enters my Person Authentication script (pasted below, and which still needs a lot of work). The script adds the user locally, then does the remote API call, and if the remote API returns 200, the user is valid, and login proceeds. In Gluu 3.1.0, the user needs to be created in the local LDAP with a password (I used the Gluu GUI to do this), and I have never seen it get to my custom script (it is either rejected immediately for a user not in the local LDAP, or it is authenticated immediately and the user gets logged in). Maybe the 3.0.2 behavior is not what you intended and it has been fixed in 3.1.0. If that's the case then I would like to ask how to get it to proceed to the Person Authentication script if it's already authenticated. Also I'll have to rethink my strategy for validating against a remote API. But I understand if that is a support forum level I don't have. [root@naatlgluu scripts]# cat allianceAuthenticate ``` # oxAuth is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. # Copyright (c) 2016, Gluu # # Author: Yuriy Movchan # import urllib import logging import traceback from org.jboss.seam.security import Identity from org.xdi.model.custom.script.type.auth import PersonAuthenticationType from org.xdi.oxauth.service import UserService from org.xdi.util import StringHelper from org.xdi.oxauth.service.net import HttpService from org.xdi.oxauth.model.common import User # from org.gluu.oxtrust.model import GluuCustomPerson # from org.gluu.oxtrust.ldap.service import IPersonService import java class PersonAuthentication(PersonAuthenticationType): def __init__(self, currentTimeMillis): self.currentTimeMillis = currentTimeMillis def logit(self, text): print("Alliance Auth: " + text) def init(self, configurationAttributes): return True def destroy(self, configurationAttributes): return True def getApiVersion(self): return 1 def isValidAuthenticationMethod(self, usageType, configurationAttributes): return True def getAlternativeAuthenticationMethod(self, usageType, configurationAttributes): return None def authenticateLocal(self, user_name, user_password): try: userService = UserService.instance() if userService.authenticate(user_name, user_password): self.logit("Local: Verification for " + user_name + " succeeded.") return True else: self.logit("Local: Verification for " + user_name + " failed.") except Exception as e: self.logit("Exception in local auth") logging.error(traceback.format_exc()) return False def authenticateRemote(self, user_name, user_password, configurationAttributes): # 1. Check if user is in local Gluu LDAP. If not, add a barebones entry # (which Gluu requires for remote API authentication). # 2. Make the remote API call and return true or false based on the response. # 3. TODO: Delete the user if they were just added and the remote API response # was invalid. That way we won't fill up the local Gluu LDAP with typos. # Not yet sure how to delete a user from the local Gluu LDAP. # userService = UserService.instance() foundUser = userService.getUserByAttribute("uid", user_name) if (foundUser == None): newUser = User() newUser.setAttribute("uid", user_name) foundUser = userService.addUser(newUser, True) foundUserName = foundUser.getUserId() self.logit("Remote: Added local Gluu user with uid " + foundUserName) try: if userService.authenticate(user_name): self.logit("Remote: Local verification for " + user_name + " succeeded.") else: self.logit("Remote: Local verification for " + user_name + " failed.") return False except Exception as e: self.logit("Exception in remote auth, local verification") logging.error(traceback.format_exc()) return False # Get URI from Gluu GUI configuration (Person Authentication custom script) api_uri = configurationAttributes.get("employee_api_uri").getValue2() req_uri = api_uri + "/employee/" + user_name + "/" + urllib.quote(user_password, safe='') httpService = HttpService.instance() http_client = httpService.getHttpsClient() req_headers = {"Authorization" : "Basic xxxxxxxxxxxxxxxx"} try: http_service_response = httpService.executeGet(http_client, req_uri, req_headers) http_response = http_service_response.getHttpResponse() except Exception as e: self.logit("Exception in remote auth") logging.error(traceback.format_exc()) return False try: # Yes it is spelled that way... if not httpService.isResponseStastusCodeOk(http_response): self.logit("Remote: Invalid response from Authentication Server: " + str(http_response.getStatusLine().getStatusCode())) httpService.consume(http_response) return False self.logit("Remote: Status code from Authentication Server: " + str(http_response.getStatusLine().getStatusCode())) response_bytes = httpService.getResponseContent(http_response) response_string = httpService.convertEntityToString(response_bytes) self.logit("Remote: Response from Authentication Server: " + response_string) httpService.consume(http_response) # TBD: adding attribute so they can be queried by web site # localUser = IPersonService.getPersonByUid(foundUser.getUserId()); # mail = foundUser.getUserId() + "@example.org" # self.logit("Remote: Set email address of " + mail) # localUser.setMail(mail) return True except Exception as e: self.logit("Exception on remote response processing") logging.error(traceback.format_exc()) finally: # Will be executed no matter what happens http_service_response.closeConnection() return False def authenticate(self, configurationAttributes, requestParameters, step): if (step == 1): credentials = Identity.instance().getCredentials() user_name = credentials.getUsername() user_password = credentials.getPassword() if (StringHelper.isNotEmptyString(user_name) and StringHelper.isNotEmptyString(user_password)): if (user_name == "admin"): return self.authenticateLocal(user_name, user_password) else: return self.authenticateRemote(user_name, user_password, configurationAttributes) else: self.logit("Either username and/or password is empty") return False 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): return "" def logout(self, configurationAttributes, requestParameters): return True ```

By Michael Schwartz Account Admin 18 Sep 2017 at 11:33 a.m. CDT

Michael Schwartz gravatar
Sahil, can you take a look at this?

By Doug Appleyard user 19 Sep 2017 at 3:31 p.m. CDT

Doug Appleyard gravatar
Hi, I am still seeing this after a fresh install of Gluu 3.1.0. Are there some trace logs I can collect which might help you? I corrected some import lines to match your example scripts (CdiUtil, Identity), and I think my python script loads correctly (at least there are no logs). But it still does not execute in any of these cases: 1) userid is not in local Gluu LDAP 2) userid is in local Gluu LDAP and password matches 3) userid is in local Gluu LDAP and password does not match Thanks

By Aliaksandr Samuseu staff 19 Sep 2017 at 4:16 p.m. CDT

Aliaksandr Samuseu gravatar
Hi, Doug. If I may suggest, just usual few things for script debugging: 1. Check `oxauth_script.log`, when you update your script in any way (like, adding a comment), it should shortly be re-initialized, and you should see result of this in the log ("success" or a error stack trace) 2. If previous test is passed, try to insert a lot of lines like `print "Debugging point #1"` all the way along main path of execution. Thus you can track down where exactly it stops executing 3. Enclose any suspicious code sections in catch-all exception handlers like below; if you are not sure, try enclose all code of your main function in it; if any exception is caught in it, narrow down the scope until you'll find segment that generates it ``` ... import sys ... try: ... some block of code ... except Exception, ex: print "Catching point #1" print "Unexpected error:", ex raise except: print "Catching point #2" print "Unexpected error:", sys.exc_info()[0] raise ``` Please share your findings here and leave the rest to Sahil.

By Doug Appleyard user 19 Sep 2017 at 4:35 p.m. CDT

Doug Appleyard gravatar
I do not see any kind of "success" message when I save the file and it loads. (Might be a trace log.) But I do see a print statement that I put in __init__() and I do see a print statement that I put in init(). I also put a print statement as the first line of authenticate() and I don't see it when I log in a user. Which seems to indicate that the custom script is successfully registered but not being invoked. (It is enabled.) If you could point to the user login authentication code which calls the custom scripts, I could look through it and discover if I might have a misconfiguration. Thanks

By Sahil Arora user 19 Sep 2017 at 7:31 p.m. CDT

Sahil Arora gravatar
Hi Doug, There has been change in custom script objects in 3.1.x, jboss.seam is no longer used in latest version. You would need to migrate your custom scripts from 3.0.x to 3.1.x Please refer this [document](https://github.com/GluuFederation/oxAuth/blob/master/Server/integrations/Migration_stepts_to_3.1.x.txt)

By Doug Appleyard user 20 Sep 2017 at 3:32 p.m. CDT

Doug Appleyard gravatar
I’ve tried updating to these new import/methods. But my authenticate() function is still not being called (as it is in 3.0.2). I tried disabling my script and enabling one that came pre-packaged (basic). Its authenticate() doesn’t get called either (nor does getApiVersion(), nor does getPageForStep()). When I turn on trace logs, I don’t see any sign of external authentication being entered. I noticed there is some different session data between 3.0.2 (when my custom script gets called) and 3.1.0 (when it does not, nor does “basic”). In 3.0.2, the acr value is set to my custom script name: 2017-09-20 15:31:05,563 TRACE [qtp1395089624-12] [org.xdi.oxauth.service.AuthenticationService] (AuthenticationService.java:413) - configureSessionUser: credentials: '1,012,356,073', sessionState: 'SessionState, dn='oxAuthSessionId=4a5b2196-4082-42ee-9063-78c051c779bc,ou=session,o=@!CE11.07C5.E6C2.D744!0001!5E41.D513,o=gluu', id='4a5b2196-4082-42ee-9063-78c051c779bc', isJwt=false, lastUsedAt=Wed Sep 20 15:31:00 EDT 2017, userDn='null', authenticationTime=Wed Sep 20 15:30:26 EDT 2017, state=unauthenticated, permissionGranted=null, permissionGrantedMap=org.xdi.oxauth.model.common.SessionIdAccessMap@7051684a, sessionAttributes={auth_step=1, acr=myCustomAuthenticate, remote_ip=xx.xx.xx.xx, scope=openid uid email profile, response_type=code, redirect_uri=https://client.example.com/index.php, state=1kbm69iu4uj927dednvao0p1fj, nonce=4v5oesgadqr1grp8cn6porn3nn, client_id=@!CE11.07C5.E6C2.D744!0001!5E41.D513!0008!FD08.4D95.2D90.1F60, auth_user=myuser}, persisted=false}', credentials.userName: 'myuser', authenticatedUser.userId: 'myuser' In 3.1.0 my script name is not in the session: 2017-09-20 16:11:28,013 TRACE [qtp1020391880-13] [org.xdi.oxauth.service.AuthenticationService] (AuthenticationService.java:407) - configureSessionUser: credentials: '1747957740', sessionId: 'SessionState {dn='oxAuthSessionId=16bb9d44-071e-4b53-98f6-bd3a1e014823,ou=session,o=@!0F64.1F9A.2111.F703!0001!E4B6.2F5D,o=gluu', id='16bb9d44-071e-4b53-98f6-bd3a1e014823', lastUsedAt=Wed Sep 20 16:11:04 EDT 2017, userDn='', authenticationTime=Wed Sep 20 16:11:04 EDT 2017, state=unauthenticated, sessionState='87138736-b221-4d1c-87c2-eaaa562cba9c', permissionGranted=null, isJwt=false, jwt=null, permissionGrantedMap=org.xdi.oxauth.model.common.SessionIdAccessMap@4d888018, involvedClients=null, sessionAttributes={auth_step=1, acr=auth_ldap_server, remote_ip=xx.xx.xx.xx, scope=openid uid email profile, response_type=code, redirect_uri=https://client.example.com/index.php, state=et4rp3822ua7mfndeo4hukoa7f, nonce=7n5a5sf10ocvf2sd6lkujumjgt, client_id=@!0F64.1F9A.2111.F703!0001!E4B6.2F5D!0008!0367.9E10.1DAC.C871}, persisted=true}', credentials.userName: 'myuser', authenticatedUser.userId: 'myuser' This is despite having the default ACR set to myCustomAuthenticate for both Gluu servers (although I’m not entirely sure what this does). If this is getting too much into custom authentication support, I understand. Thanks for your time. Doug Appleyard

By Sahil Arora user 21 Sep 2017 at 7:29 p.m. CDT

Sahil Arora gravatar
Have you also set `oxTrust acr` to your custom script? If not, Please do so and let me know. I have not been able to reproduce on my local system. Please provide your updated custom script code to check it further.

By Doug Appleyard user 22 Sep 2017 at 8:57 a.m. CDT

Doug Appleyard gravatar
I figured it out. I needed to set the acr_values in my oxd client config file (oxd-rp-settings.json) to the name of my custom script. E.g. "acr_values":["myCustomAuthenticate"] (Or I need to update the Default requested Authentication Context Class Reference values to include myCustomAuthenticate.) After doing this, it does not matter what I have set in "Default acr" and "oxTrust acr" under Default Authentication Method. Right now I have default set to auth_ldap_server and oxTrust acr set to Default. My custom validator runs fine. In my previous client for oxd 3.0.2, I had acr_values set to an empty string (and it was not in the client config on the oxTrust GUI), but I had the oxTrust default acr set to myCustomAuthenticate under Default Authentication Method, and it worked. I can use 3.1.0 by setting acr_values in the oxd_client or by updating the client settings on oxTrust. But the real question is, if no ACR is chosen in oxd client settings, why is the oxTrust default ACR from Default Authentication Method not being used? I see the same behavior with mod_auth_openidc. You can close this ticket because I can just update the client settings to specify my custom script, but you might want to look at why the default method is not being used if it is set to a script, and the client has not specified a script. Thanks

By Jajati Badu Account Admin 25 Sep 2017 at 1:32 a.m. CDT

Jajati Badu gravatar
Hi Doug, > question is, if no ACR is chosen in oxd client settings, why is the oxTrust default ACR from Default Authentication Method not being used? We tried the same by setting a custom Auth script as default oxTrust acr and the default acr is getting triggered without passing any acr values from client application. Kind Regards, Jajati