001 package org.crsh.plugins.crowd; 002 003 import com.atlassian.crowd.exception.ApplicationPermissionException; 004 import com.atlassian.crowd.exception.InvalidAuthenticationException; 005 import com.atlassian.crowd.integration.rest.service.factory.RestCrowdClientFactory; 006 import com.atlassian.crowd.service.client.ClientProperties; 007 import com.atlassian.crowd.service.client.ClientPropertiesImpl; 008 import com.atlassian.crowd.service.client.ClientResourceLocator; 009 import com.atlassian.crowd.service.client.CrowdClient; 010 import org.crsh.auth.AuthenticationPlugin; 011 import org.crsh.plugin.CRaSHPlugin; 012 013 import java.util.logging.Level; 014 import java.util.logging.Logger; 015 016 /** 017 * Allows to use an Atlassian Crowd serer to authenticate on CRaSH 018 * To use it you need to : 019 * <ul> 020 * <li>Define the application on the crowd server side,</li> 021 * <li>Use <pre>crash.auth=crowd</pre> in your crash.properties configuration file,</li> 022 * <li>Create the <a href="https://confluence.atlassian.com/display/CROWD/The+crowd.properties+File"><pre>crowd.properties</pre> configuration file</a> 023 * and add it in your application classpath or by defining its path with the system property crowd.properties (<pre>-Dcrowd.properties={FILE-PATH}/crowd.properties</pre>).</li> 024 * </ul> 025 */ 026 public class CrowdAuthenticationPlugin extends 027 CRaSHPlugin<AuthenticationPlugin> implements 028 AuthenticationPlugin<String> { 029 030 /** 031 * Logger 032 */ 033 protected final Logger log = Logger.getLogger(getClass().getName()); 034 035 /** 036 * Crowd client instance 037 */ 038 private static volatile CrowdClient crowdClient; 039 040 /** 041 * Lock to create the crowd client 042 */ 043 private static final Object lock = new Object(); 044 045 /** 046 * Get a ready to use CrowdClient. 047 * 048 * @return a CrowdClient already initialized 049 */ 050 private static CrowdClient getCrowdClient() { 051 if (crowdClient == null) { 052 synchronized (lock) { 053 if (crowdClient == null) { 054 ClientResourceLocator 055 crl = new ClientResourceLocator("crowd.properties"); 056 if (crl.getProperties() == null) { 057 throw new NullPointerException("crowd.properties can not be found in classpath"); 058 } 059 ClientProperties clientProperties = ClientPropertiesImpl.newInstanceFromResourceLocator(crl); 060 RestCrowdClientFactory restCrowdClientFactory = new RestCrowdClientFactory(); 061 crowdClient = restCrowdClientFactory.newInstance(clientProperties); 062 } 063 } 064 } 065 return crowdClient; 066 } 067 068 public Class<String> getCredentialType() { 069 return String.class; 070 } 071 072 @Override 073 public String getName() { 074 return "crowd"; 075 } 076 077 @Override 078 public boolean authenticate(String username, String password) throws Exception { 079 // Username and passwords are required 080 if (username == null || username.isEmpty() || password == null || password.isEmpty()) { 081 log.log(Level.WARNING, "Unable to logon without username and password."); 082 return false; 083 } 084 try { 085 // Authenticate the user 086 if (log.isLoggable(Level.FINE)) { 087 log.log(Level.FINE, "Authenticating '" + username + "' on crowd directory"); 088 } 089 getCrowdClient().authenticateUser(username, password); 090 return true; 091 } catch (InvalidAuthenticationException e) { 092 log.log(Level.WARNING, "Authentication failed for user '" + username + "'"); 093 return false; 094 } catch (ApplicationPermissionException e) { 095 log.log(Level.SEVERE, "Application not authorized to authenticate user '" + username + "'", e); 096 return false; 097 } 098 } 099 100 @Override 101 public AuthenticationPlugin getImplementation() { 102 return this; 103 } 104 }