/** * Copyright (C) 2015 Caratarse Auth Team <lucio.benfante@gmail.com> * * This file is part of Caratarse Auth support for CAS. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.caratarse.auth.cas.support; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import org.caratarse.auth.client.ApiResponse; import org.caratarse.auth.client.CaratarseAuthClient; import org.jasig.cas.authentication.handler.AuthenticationException; import org.jasig.cas.authentication.handler.BadPasswordAuthenticationException; import org.jasig.cas.authentication.handler.BlockedCredentialsAuthenticationException; import org.jasig.cas.authentication.handler.UnknownUsernameAuthenticationException; import org.jasig.cas.authentication.handler.support.AbstractUsernamePasswordAuthenticationHandler; import org.jasig.cas.authentication.principal.UsernamePasswordCredentials; import org.springframework.beans.factory.InitializingBean; /** * An authentication handler that uses the Caratarse-auth services. * * @author Lucio Benfante <lucio@benfante.com> */ public class CaratarseAuthClientAuthenticationHandler extends AbstractUsernamePasswordAuthenticationHandler implements InitializingBean { private CaratarseAuthClient caratarseAuthClient; private boolean withSalt = true; protected final boolean authenticateUsernamePasswordInternal(final UsernamePasswordCredentials credentials) throws AuthenticationException { final String transformedUsername = getPrincipalNameTransformer().transform(credentials.getUsername()); final String encryptedPassword = getPasswordEncoder().encode( credentials.getPassword() + (isWithSalt()?"{" + transformedUsername + "}":"")); ApiResponse response; JsonNode userTree; try { response = caratarseAuthClient.getUserByUsername(transformedUsername); if ("404".equals(response.getCode())) { throw new UnknownUsernameAuthenticationException(); } ObjectMapper m = new ObjectMapper(); JsonNode rootTree = m.readTree(response.getContent()); userTree = rootTree.get("_embedded").get("users").get(0); if (userTree == null) { throw new UnknownUsernameAuthenticationException(); } } catch (Exception ex) { throw new AuthenticationException("Authentication failed for user "+transformedUsername, ex) {}; } if (!userIsEnabled(userTree)) { throw new BlockedCredentialsAuthenticationException(); } if (!passwordMatches(userTree, encryptedPassword)) { throw new BadPasswordAuthenticationException(); } // update last login return true; } @Override public void afterPropertiesSet() throws Exception { } public CaratarseAuthClient getCaratarseAuthClient() { return caratarseAuthClient; } public void setCaratarseAuthClient(CaratarseAuthClient caratarseAuthClient) { this.caratarseAuthClient = caratarseAuthClient; } public boolean isWithSalt() { return withSalt; } public void setWithSalt(boolean withSalt) { this.withSalt = withSalt; } private boolean userIsEnabled(JsonNode userTree) { return userTree.get("disabled") == null; } private boolean passwordMatches(JsonNode userTree, String encryptedPassword) { return encryptedPassword.equals(userTree.get("password").asText()); } }