/******************************************************************************* * Cloud Foundry * Copyright (c) [2009-2016] Pivotal Software, Inc. All Rights Reserved. * * This product is licensed to you under the Apache License, Version 2.0 (the "License"). * You may not use this product except in compliance with the License. * * This product includes a number of subcomponents with * separate copyright notices and license terms. Your use of these * subcomponents is subject to the terms and conditions of the * subcomponent's license, as noted in the LICENSE file. *******************************************************************************/ package org.cloudfoundry.identity.uaa.authentication.manager; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.cloudfoundry.identity.uaa.authentication.AuthzAuthenticationRequest; import org.cloudfoundry.identity.uaa.authentication.UaaAuthentication; import org.cloudfoundry.identity.uaa.authentication.UaaAuthenticationDetails; import org.cloudfoundry.identity.uaa.authentication.UaaPrincipal; import org.cloudfoundry.identity.uaa.authentication.event.UserAuthenticationSuccessEvent; import org.cloudfoundry.identity.uaa.constants.OriginKeys; import org.cloudfoundry.identity.uaa.user.UaaAuthority; import org.cloudfoundry.identity.uaa.user.UaaUser; import org.cloudfoundry.identity.uaa.user.UaaUserDatabase; import org.cloudfoundry.identity.uaa.zone.IdentityZoneHolder; import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.ApplicationEventPublisherAware; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; import org.springframework.security.core.context.SecurityContext; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.security.oauth2.common.util.RandomValueStringGenerator; import org.springframework.security.oauth2.provider.OAuth2Authentication; import java.util.Date; import java.util.Map; public class LoginAuthenticationManager implements AuthenticationManager, ApplicationEventPublisherAware { public static final String NotANumber = OriginKeys.NotANumber; private final Log logger = LogFactory.getLog(getClass()); private ApplicationEventPublisher eventPublisher; private UaaUserDatabase userDatabase; private RandomValueStringGenerator generator = new RandomValueStringGenerator(); @Override public void setApplicationEventPublisher(ApplicationEventPublisher eventPublisher) { this.eventPublisher = eventPublisher; } /** * @param userDatabase the userDatabase to set */ public void setUserDatabase(UaaUserDatabase userDatabase) { this.userDatabase = userDatabase; } @Override public Authentication authenticate(Authentication request) throws AuthenticationException { if (!(request instanceof AuthzAuthenticationRequest)) { logger.debug("Cannot process request of type: " + request.getClass().getName()); return null; } AuthzAuthenticationRequest req = (AuthzAuthenticationRequest) request; Map<String, String> info = req.getInfo(); logger.debug("Processing authentication request for " + req.getName()); SecurityContext context = SecurityContextHolder.getContext(); if (context.getAuthentication() instanceof OAuth2Authentication) { OAuth2Authentication authentication = (OAuth2Authentication) context.getAuthentication(); if (authentication.isClientOnly()) { UaaUser user = getUser(req, info); UaaAuthenticationDetails authdetails = (UaaAuthenticationDetails) req.getDetails(); boolean addNewAccounts = authdetails != null && authdetails.isAddNew(); try { if (NotANumber.equals(user.getId())) { user = userDatabase.retrieveUserByName(user.getUsername(), user.getOrigin()); } else { //we should never add new accounts if we specify user_id addNewAccounts = false; user = userDatabase.retrieveUserById(user.getId()); } } catch (UsernameNotFoundException e) { // Not necessarily fatal if (addNewAccounts) { // Register new users automatically publish(new NewUserAuthenticatedEvent(user)); try { user = userDatabase.retrieveUserByName(user.getUsername(), user.getOrigin()); } catch (UsernameNotFoundException ex) { throw new BadCredentialsException("Bad credentials"); } } else { //if add_new=false then this is a bad user ID throw new BadCredentialsException("Bad Credentials"); } } Authentication success = new UaaAuthentication(new UaaPrincipal(user), user.getAuthorities(), authdetails); publish(new UserAuthenticationSuccessEvent(user, success)); return success; } } logger.debug("Did not locate login credentials"); return null; } protected void publish(ApplicationEvent event) { if (eventPublisher != null) { eventPublisher.publishEvent(event); } } protected UaaUser getUser(AuthzAuthenticationRequest req, Map<String, String> info) { String name = req.getName(); String email = info.get("email"); String userId = info.get("user_id")!=null?info.get("user_id"):NotANumber; if(info.get(OriginKeys.ORIGIN)!=null && info.get(OriginKeys.ORIGIN).equals(OriginKeys.UAA)){ throw new BadCredentialsException("uaa origin not allowed for external login server"); } String origin = info.get(OriginKeys.ORIGIN)!=null?info.get(OriginKeys.ORIGIN): OriginKeys.LOGIN_SERVER; if (name == null && email != null) { name = email; } if (name == null && NotANumber.equals(userId)) { throw new BadCredentialsException("Cannot determine username from credentials supplied"); } else if (name==null) { //we have user_id, name is irrelevant name="unknown"; } if (email == null) { if (name.contains("@")) { if (name.split("@").length == 2 && !name.startsWith("@") && !name.endsWith("@")) { email = name; } else { email = name.replaceAll("@", "") + "@unknown.org"; } } else { email = name + "@unknown.org"; } } String givenName = info.get("given_name"); if (givenName == null) { givenName = email.split("@")[0]; } String familyName = info.get("family_name"); if (familyName == null) { familyName = (email.split("@").length > 1 ? email.split("@")[1] : email); } return new UaaUser( userId, name, "" /*zero length password for login server */, email, UaaAuthority.USER_AUTHORITIES, givenName, familyName, new Date(), new Date(), origin, name, false, IdentityZoneHolder.get().getId(), null, null); } }