Java tutorial
/** * Copyright 2014 Michael Brush * * 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 com.bcknds.demo.oauth2.security; import java.util.ArrayList; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.oauth2.client.OAuth2RestTemplate; import org.springframework.security.oauth2.client.resource.OAuth2AccessDeniedException; import org.springframework.security.oauth2.common.OAuth2AccessToken; import org.springframework.security.oauth2.common.exceptions.InvalidGrantException; import org.springframework.security.oauth2.common.exceptions.UserDeniedAuthorizationException; import org.springframework.web.client.ResourceAccessException; import com.bcknds.demo.oauth2.BaseTest; import com.bcknds.demo.oauth2.model.Role; import com.bcknds.demo.oauth2.model.User; import com.bcknds.demo.oauth2.service.RoleService; import com.bcknds.demo.oauth2.service.UserService; import com.bcknds.demo.oauth2.util.AuthenticationUtil; import com.bcknds.demo.oauth2.util.SSLCertificateValidation; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.fail; /** * Authentication Tests for Password Authentication * * This class does not do scope or client id failures since ClientCredentialAuthenticationTests cover those * * In this class I did not use @Test( expected = SomeException.class ) for two reasons * 1.) This will show how exception can be handled * 2.) OAuth2RestTemplate returns a generic OAuth2AccessDeniedException, but the cause underneath * holds the real value for the failure. * * @author Michael Brush */ public class PasswordAuthenticationTests extends BaseTest { private static final BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(); @Autowired private UserService userService; @Autowired private RoleService roleService; private User validUser = new User("user", encoder.encode("password")); private Role validRole = new Role("ROLE_PASSWORD"); @Before public void setUp() { SSLCertificateValidation.disable(); validRole = roleService.save(validRole); validUser.addRole(validRole); validUser = userService.save(validUser); } @After public void tearDown() { userService.remove(validUser); roleService.remove(validRole); } /** * Verify that authentication is successful. */ @Test public void testSuccessfulAuthentication() { OAuth2RestTemplate restTemplate = AuthenticationUtil.getPasswordCredentials(USERNAME, PASSWORD); OAuth2AccessToken token = null; try { token = restTemplate.getAccessToken(); } catch (OAuth2AccessDeniedException ex) { if (ex.getCause() instanceof ResourceAccessException) { fail("It appears that the server may not be running. Please start it before running tests"); } else { fail(ex.getMessage()); } } catch (Exception ex) { fail(ex.getMessage()); } assertNotNull(token.getValue()); } /** * Test using a bad username */ @Test public void testBadUsername() { OAuth2RestTemplate restTemplate = AuthenticationUtil.getPasswordCredentials("badUsername", PASSWORD); try { restTemplate.getAccessToken(); fail("Expected OAuth2AccessDeniedException, but none was thrown"); } catch (OAuth2AccessDeniedException ex) { if (ex.getCause() instanceof InvalidGrantException) { InvalidGrantException clientException = (InvalidGrantException) ex.getCause(); assertEquals(HttpStatus.BAD_REQUEST.value(), clientException.getHttpErrorCode()); } else if (ex.getCause() instanceof ResourceAccessException) { fail("It appears that the server may not be running. Please start it before running tests"); } else { fail(String.format("Expected InvalidGrantException. Got %s", ex.getCause().getClass().getName())); } } catch (Exception ex) { fail(ex.getMessage()); } } /** * Test using a bad username */ @Test public void testBadPassword() { OAuth2RestTemplate restTemplate = AuthenticationUtil.getPasswordCredentials(USERNAME, "badPassword"); try { restTemplate.getAccessToken(); fail("Expected OAuth2AccessDeniedException, but none was thrown"); } catch (OAuth2AccessDeniedException ex) { if (ex.getCause() instanceof InvalidGrantException) { InvalidGrantException clientException = (InvalidGrantException) ex.getCause(); assertEquals(HttpStatus.BAD_REQUEST.value(), clientException.getHttpErrorCode()); } else if (ex.getCause() instanceof ResourceAccessException) { fail("It appears that the server may not be running. Please start it before running tests"); } else { fail(String.format("Expected InvalidGrantException. Got %s", ex.getCause().getClass().getName())); } } catch (Exception ex) { fail(ex.getMessage()); } } /** * Test successful authentication to method secure endpoint that requires only authentication * using password authentication */ @Test public void testPasswordAuthenticationMethodEndpoint() { OAuth2RestTemplate restTemplate = AuthenticationUtil.getPasswordCredentials(USERNAME, PASSWORD); ResponseEntity<String> response = null; try { response = restTemplate.getForEntity(METHOD_SECURE_ENDPOINT, String.class); assertEquals("This is secured by annotation", response.getBody()); assertEquals(HttpStatus.OK, response.getStatusCode()); } catch (OAuth2AccessDeniedException ex) { if (ex.getCause() instanceof ResourceAccessException) { fail("It appears that the server may not be running. Please start it before running tests"); } else { fail(ex.getMessage()); } } catch (Exception ex) { fail(ex.getMessage()); } } /** * Test successful authentication to method secure endpoint that requires the ROLE_PASSWORD * role. */ @Test public void testPasswordAuthenticationRoleEndpoint() { OAuth2RestTemplate restTemplate = AuthenticationUtil.getPasswordCredentials(USERNAME, PASSWORD); ResponseEntity<String> response = null; try { response = restTemplate.getForEntity(ROLE_SECURE_ENDPOINT, String.class); assertEquals("This is secured by annotation and role.", response.getBody()); assertEquals(HttpStatus.OK, response.getStatusCode()); } catch (OAuth2AccessDeniedException ex) { if (ex.getCause() instanceof ResourceAccessException) { fail("It appears that the server may not be running. Please start it before running tests"); } else { fail(ex.getMessage()); } } catch (Exception ex) { fail(ex.getMessage()); } } /** * Test authentication failure to role secure endpoint that requires the ROLE_PASSWORD role * which this user will not have */ @Test public void testPasswordAuthenticationBadRole() { userService.remove(validUser); Role badRole = new Role("ROLE_INVALID"); validUser.setRoles(new ArrayList<Role>()); validUser.addRole(badRole); userService.save(validUser); OAuth2RestTemplate restTemplate = AuthenticationUtil.getPasswordCredentials(USERNAME, PASSWORD); try { restTemplate.getForEntity(ROLE_SECURE_ENDPOINT, String.class); fail("Expected exception. None was thrown"); } catch (UserDeniedAuthorizationException ex) { assertEquals(HttpStatus.BAD_REQUEST.value(), ex.getHttpErrorCode()); } catch (Exception ex) { fail(ex.getMessage()); } } /** * Test successful authentication to method secure endpoint that requires the ROLE_PASSWORD * role. */ @Test public void testPasswordAuthenticationMultipleRole() { Role adminRole = new Role("ROLE_ADMIN"); userService.remove(validUser); validUser.addRole(adminRole); userService.save(validUser); OAuth2RestTemplate restTemplate = AuthenticationUtil.getPasswordCredentials(USERNAME, PASSWORD); ResponseEntity<String> response = null; try { response = restTemplate.getForEntity(ROLE_SECURE_ENDPOINT, String.class); assertEquals("This is secured by annotation and role.", response.getBody()); assertEquals(HttpStatus.OK, response.getStatusCode()); } catch (OAuth2AccessDeniedException ex) { if (ex.getCause() instanceof ResourceAccessException) { fail("It appears that the server may not be running. Please start it before running tests"); } else { fail(ex.getMessage()); } } catch (Exception ex) { fail(ex.getMessage()); } } }