We would like to use passwordless authentication when authenticating Jira with Crowd. Our project has followed the steps listed here to set up the two applications; the only difference being that we are using our customer authenticator in place of 'com.atlassian.jira.security.login.SSOSeraphAuthenticator".
While tailing the Crowd logs and accessing JIRA we can see that the custom authenticator is accessing Crowd. The user being passed to Crowd is set up as having accesing to JIRA inside of the Crowd. Crowd reports that it recognizes the user and that the user has access to JIRA. A problem occurs when Crowd tries to update its database and we see the below errors:
Could not synchronize database state with session: org.hibernate.StaleStateException: Batch update returned unexcepted row count from update [0]; actual row count: 0; expected: 1
java.sql.BatchUpdateException: Duplicate entry 'XXXXXX' for key 'identifier_hash'
I'm simply paraphrasing the stack trace here; the original stacktrace is on a seperate system than I can't transfer over and upload.
The username is set in the HTTPRequest by a Tomcat Filter before reaching the custom Authenticator.
The custom authenticator extends 'com.atlassian.crowd.integration.seraph.v25.CrowdAuthenticator'
Below is the authenticator code:
public class CustomCrowdAuthenticator extends CrowdAuthenticator{
public CustomCrowdAuthenticator(){
this(RestCrowdHttpAuthenticationFactory.getAuthenticator());
}
public CustomCrowdAuthentictor(CrowdHttpAuthenticator crwodHttpAuthenticator){
super(crowdHttpAuthenticator);
}
public Principal getUser(HttpServletRequest request, HttpServletResponse response){
Principal user = super.getUser(request,response);
if(user == null){
String username = //get user name out of request
try{
passwordlessLogin(request,response,username,true);
user = getUserFromSession(request);
catch(AuthenciationException e){
//log error
}
}
return user;
}
private boolean passwordlessLogin(HttpServletRequest request, HttpServletResponse response, String username, boolean cookie) throws AuthenticatorException{
boolean authenticated = false;
try{
logout(request,response);
request.setAttribute(LoginReason.REQUEST_ATTR_NAME,null);
crowdHttpAuthenticator.authenticateWithoutValidatingPassword(request,response,username);
authenticated = true;
}catch(Exception e){
//log exception
}
String fakePassword = authenticated ? CORRECT_PASSWORD : INCORRECT_PASSWORD;
authenticated = ((DefaultAuthenticator)this).login(request,response,username,fakePassword,cookie);
return authenticated;
}