/*******************************************************************************
* 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 static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertNotNull;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import org.cloudfoundry.identity.uaa.authentication.AuthzAuthenticationRequest;
import org.cloudfoundry.identity.uaa.authentication.UaaAuthenticationTestFactory;
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.test.TestApplicationEventPublisher;
import org.cloudfoundry.identity.uaa.user.UaaUser;
import org.cloudfoundry.identity.uaa.user.UaaUserDatabase;
import org.cloudfoundry.identity.uaa.user.UaaUserTestFactory;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.mockito.Mockito;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.context.SecurityContextImpl;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.oauth2.provider.AuthorizationRequest;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
/**
* @author Dave Syer
*
*/
public class LoginAuthenticationManagerTests {
private LoginAuthenticationManager manager = new LoginAuthenticationManager();
private UaaUserDatabase userDatabase = Mockito.mock(UaaUserDatabase.class);
private OAuth2Authentication oauth2Authentication;
private TestApplicationEventPublisher<UserAuthenticationSuccessEvent> publisher;
@Rule
public ExpectedException expectedException = ExpectedException.none();
@Before
public void init() {
publisher = TestApplicationEventPublisher.forEventClass(UserAuthenticationSuccessEvent.class);
manager.setApplicationEventPublisher(publisher);
manager.setUserDatabase(userDatabase);
oauth2Authentication = new OAuth2Authentication(new AuthorizationRequest("client", Arrays.asList("read",
"write")).createOAuth2Request(), null);
SecurityContextImpl context = new SecurityContextImpl();
context.setAuthentication(oauth2Authentication);
SecurityContextHolder.setContext(context);
}
@After
public void clean() {
SecurityContextHolder.clearContext();
}
@Test
public void testNotProcessingWrongType() {
Authentication authentication = manager.authenticate(new UsernamePasswordAuthenticationToken("foo", "bar"));
assertNull(authentication);
}
@Test
public void testNotProcessingNotAuthenticated() {
SecurityContextHolder.clearContext();
Authentication authentication = manager.authenticate(UaaAuthenticationTestFactory
.getAuthenticationRequest("foo"));
assertNull(authentication);
}
@Test
public void testHappyDayNoAutoAdd() {
UaaUser user = UaaUserTestFactory.getUser("FOO", "foo", "fo@test.org", "Foo", "Bar");
Mockito.when(userDatabase.retrieveUserByName("foo", OriginKeys.LOGIN_SERVER)).thenReturn(user);
Authentication authentication = manager.authenticate(UaaAuthenticationTestFactory
.getAuthenticationRequest("foo"));
assertEquals(user.getUsername(), ((UaaPrincipal) authentication.getPrincipal()).getName());
assertEquals(user.getId(), ((UaaPrincipal) authentication.getPrincipal()).getId());
}
@Test
public void testHappyDayWithAuthorities() {
UaaUser user = UaaUserTestFactory.getAdminUser("FOO", "foo", "fo@test.org", "Foo", "Bar");
Mockito.when(userDatabase.retrieveUserByName("foo", OriginKeys.LOGIN_SERVER)).thenReturn(user);
Authentication authentication = manager.authenticate(UaaAuthenticationTestFactory
.getAuthenticationRequest("foo"));
assertEquals(user.getUsername(), ((UaaPrincipal) authentication.getPrincipal()).getName());
assertEquals(user.getAuthorities(), authentication.getAuthorities());
}
@Test(expected = BadCredentialsException.class)
public void testUserNotFoundNoAutoAdd() {
Mockito.when(userDatabase.retrieveUserByName("foo", OriginKeys.LOGIN_SERVER)).thenThrow(new UsernameNotFoundException("planned"));
manager.authenticate(UaaAuthenticationTestFactory.getAuthenticationRequest("foo"));
}
@Test
public void testHappyDayAutoAddButWithExistingUser() {
UaaUser user = UaaUserTestFactory.getUser("FOO", "foo", "fo@test.org", "Foo", "Bar");
Mockito.when(userDatabase.retrieveUserByName("foo", OriginKeys.LOGIN_SERVER)).thenReturn(user);
Authentication authentication = manager.authenticate(UaaAuthenticationTestFactory
.getAuthenticationRequest("foo", true));
assertEquals(user.getUsername(), ((UaaPrincipal) authentication.getPrincipal()).getName());
assertEquals(user.getId(), ((UaaPrincipal) authentication.getPrincipal()).getId());
}
@Test
public void testHappyDayAutoAddButWithNewUser() {
UaaUser user = UaaUserTestFactory.getUser("FOO", "foo", "fo@test.org", "Foo", "Bar");
Mockito.when(userDatabase.retrieveUserByName("foo", OriginKeys.LOGIN_SERVER)).thenThrow(new UsernameNotFoundException("planned"))
.thenReturn(user);
Authentication authentication = manager.authenticate(UaaAuthenticationTestFactory
.getAuthenticationRequest("foo", true));
assertEquals(user.getUsername(), ((UaaPrincipal) authentication.getPrincipal()).getName());
assertEquals(user.getId(), ((UaaPrincipal) authentication.getPrincipal()).getId());
}
@Test(expected = BadCredentialsException.class)
public void testFailedAutoAddButWithNewUser() {
UaaUser user = UaaUserTestFactory.getUser("FOO", "foo", "fo@test.org", "Foo", "Bar");
Mockito.when(userDatabase.retrieveUserByName("foo", OriginKeys.LOGIN_SERVER)).thenThrow(new UsernameNotFoundException("planned"));
Authentication authentication = manager.authenticate(UaaAuthenticationTestFactory
.getAuthenticationRequest("foo", true));
assertEquals(user.getUsername(), ((UaaPrincipal) authentication.getPrincipal()).getName());
assertEquals(user.getId(), ((UaaPrincipal) authentication.getPrincipal()).getId());
}
@Test
public void testAuthenticateWithStrangeNameAndMissingEmail() {
String username1 = "a@";
AuthzAuthenticationRequest req1 = UaaAuthenticationTestFactory.getAuthenticationRequest(username1, true);
UaaUser u1 = manager.getUser(req1, req1.getInfo());
assertEquals(username1, u1.getUsername());
String username2 = "@a";
AuthzAuthenticationRequest req2 = UaaAuthenticationTestFactory.getAuthenticationRequest(username2, true);
UaaUser u2 = manager.getUser(req2, req2.getInfo());
assertEquals(username2, u2.getUsername());
String username3 = "a@b@c";
AuthzAuthenticationRequest req3 = UaaAuthenticationTestFactory.getAuthenticationRequest(username3, true);
UaaUser u3 = manager.getUser(req3, req3.getInfo());
assertEquals(username3, u3.getUsername());
}
@Test
public void uaaOriginNotAllowedForExternalLogin() {
expectedException.expect(BadCredentialsException.class);
expectedException.expectMessage("uaa origin not allowed for external login server");
String username1 = "a@";
AuthzAuthenticationRequest req1 = UaaAuthenticationTestFactory.getAuthenticationRequest(username1, true);
Map<String, String> info = new HashMap<>(req1.getInfo());
info.put(OriginKeys.ORIGIN, OriginKeys.UAA);
manager.getUser(req1, info);
}
@Test
public void testSuccessfulAuthenticationPublishesEvent() throws Exception {
UaaUser user = UaaUserTestFactory.getUser("FOO", "foo", "fo@test.org", "Foo", "Bar");
Mockito.when(userDatabase.retrieveUserByName("foo", OriginKeys.LOGIN_SERVER)).thenReturn(user);
AuthzAuthenticationRequest authenticationRequest = UaaAuthenticationTestFactory.getAuthenticationRequest("foo");
manager.authenticate(authenticationRequest);
Assert.assertEquals(1, publisher.getEventCount());
Assert.assertEquals("foo", publisher.getLatestEvent().getUser().getUsername());
}
@Test
public void testNoOutOfBoundsInCaseOfWrongEmailFormat() {
// use an email without the '@' sign and provide no name and familyname to trigger the potential bug
String username = "newuser";
String email = "noAtSign";
AuthzAuthenticationRequest req1 = UaaAuthenticationTestFactory.getAuthenticationRequest(username, true);
Map<String,String> info = new HashMap<>(req1.getInfo());
info.put("email", email);
UaaUser u1 = manager.getUser(req1, info);
assertNotNull(u1);
assertEquals(username, u1.getUsername());
assertNotNull(u1.getFamilyName());
assertNotNull(u1.getGivenName());
}
}