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()); } }