package org.apereo.cas.adaptors.authy;
import com.authy.api.Token;
import com.authy.api.User;
import org.apereo.cas.authentication.Credential;
import org.apereo.cas.authentication.HandlerResult;
import org.apereo.cas.authentication.PreventedException;
import org.apereo.cas.authentication.handler.support.AbstractPreAndPostProcessingAuthenticationHandler;
import org.apereo.cas.authentication.principal.Principal;
import org.apereo.cas.authentication.principal.PrincipalFactory;
import org.apereo.cas.services.ServicesManager;
import org.apereo.cas.web.support.WebUtils;
import org.springframework.webflow.execution.RequestContext;
import org.springframework.webflow.execution.RequestContextHolder;
import javax.security.auth.login.FailedLoginException;
import java.security.GeneralSecurityException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
/**
* Authy authentication handler for CAS.
*
* @author Misagh Moayyed
* @since 5.0
*/
public class AuthyAuthenticationHandler extends AbstractPreAndPostProcessingAuthenticationHandler {
private Boolean forceVerification = Boolean.FALSE;
private final AuthyClientInstance instance;
public AuthyAuthenticationHandler(final String name, final ServicesManager servicesManager, final PrincipalFactory principalFactory,
final AuthyClientInstance instance, final boolean forceVerification) {
super(name, servicesManager, principalFactory, null);
this.instance = instance;
this.forceVerification = forceVerification;
}
@Override
protected HandlerResult doAuthentication(final Credential credential) throws GeneralSecurityException, PreventedException {
final AuthyTokenCredential tokenCredential = (AuthyTokenCredential) credential;
final RequestContext context = RequestContextHolder.getRequestContext();
final Principal principal = WebUtils.getAuthentication(context).getPrincipal();
final User user = instance.getOrCreateUser(principal);
if (!user.isOk()) {
throw new FailedLoginException(AuthyClientInstance.getErrorMessage(user.getError()));
}
final Map<String, String> options = new HashMap<>(1);
options.put("force", this.forceVerification.toString());
final Token verification = this.instance.getAuthyTokens().verify(user.getId(), tokenCredential.getToken(), options);
if (!verification.isOk()) {
throw new FailedLoginException(AuthyClientInstance.getErrorMessage(verification.getError()));
}
return createHandlerResult(tokenCredential, principal, new ArrayList<>());
}
@Override
public boolean supports(final Credential credential) {
return AuthyTokenCredential.class.isAssignableFrom(credential.getClass());
}
}