package net.unicon.cas.addons.authentication.handler;
import com.stormpath.sdk.account.Account;
import com.stormpath.sdk.application.Application;
import com.stormpath.sdk.authc.UsernamePasswordRequest;
import com.stormpath.sdk.client.Client;
import com.stormpath.sdk.client.DefaultApiKey;
import com.stormpath.sdk.resource.ResourceException;
import net.unicon.cas.addons.support.Immutable;
import org.jasig.cas.authentication.handler.AuthenticationException;
import org.jasig.cas.authentication.handler.BadCredentialsAuthenticationException;
import org.jasig.cas.authentication.handler.support.AbstractUsernamePasswordAuthenticationHandler;
import org.jasig.cas.authentication.principal.UsernamePasswordCredentials;
import org.springframework.beans.factory.BeanCreationException;
/**
* An authentication handler for <a href="http://www.stormpath.com">Stormpath</a>.
* <p/>
* This implementation uses Stormpath's <a href="https://github.com/stormpath/stormpath-sdk-java/wiki">Java SDK</a>
*
* @author <a href="mailto:mmoayyed@unicon.net">Misagh Moayyed</a>
* @author Dmitriy Kopylenko
* @author Unicon, inc.
* @since 1.0
*/
@Immutable
public class StormpathAuthenticationHandler extends AbstractUsernamePasswordAuthenticationHandler {
private final Application application;
/**
* Receives the Stormpath admin credentials and applicationId and sets up and instance of a Stormpath's Application resource
* which will be used to authenticate users.
*
* @param stormpathAccessId accessId provided by Stormpath, for the admin user with the created API key.
* @param stormpathSecretKey secret key provided by Stormpath, for the admin user with the created API key.
* @param applicationId This is application id configured on Stormpath whose login source will be used to authenticate users.
* @throws BeanCreationException If credentials cannot be verified by Stormpath.
*/
public StormpathAuthenticationHandler(final String stormpathAccessId, final String stormpathSecretKey, final String applicationId) throws BeanCreationException {
final Client client = new Client(new DefaultApiKey(stormpathAccessId, stormpathSecretKey));
try {
this.application = client.getDataStore().getResource(String.format("/applications/%s", applicationId), Application.class);
}
catch (Throwable e) {
throw new BeanCreationException("An exception is caught trying to access Stormpath cloud. " +
"Please verify that your provided Stormpath <accessId>, " +
"<secretKey>, and <applicationId> are correct. Original Stormpath error: " + e.getMessage());
}
}
@Override
protected boolean authenticateUsernamePasswordInternal(final UsernamePasswordCredentials credentials) throws AuthenticationException {
try {
this.log.debug("Attempting to authenticate user [{}] against application [{}] in Stormpath cloud...", credentials.getUsername(), this.application.getName());
this.authenticateAccount(credentials);
this.log.debug("Successfully authenticated user [{}]", credentials.getUsername());
return true;
}
catch (ResourceException e) {
this.log.error(e.getMessage(), e);
throw new BadCredentialsAuthenticationException();
}
}
public Account authenticateAccount(final UsernamePasswordCredentials credentials) throws ResourceException {
return this.application.authenticateAccount(new UsernamePasswordRequest(credentials.getUsername(), credentials.getPassword())).getAccount();
}
}