package org.apereo.cas.support.oauth.web; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import org.apereo.cas.authentication.Authentication; import org.apereo.cas.authentication.BasicCredentialMetaData; import org.apereo.cas.authentication.BasicIdentifiableCredential; import org.apereo.cas.authentication.CoreAuthenticationTestUtils; import org.apereo.cas.authentication.CredentialMetaData; import org.apereo.cas.authentication.DefaultAuthenticationBuilder; import org.apereo.cas.authentication.DefaultHandlerResult; import org.apereo.cas.authentication.HandlerResult; import org.apereo.cas.authentication.principal.Principal; import org.apereo.cas.mock.MockTicketGrantingTicket; import org.apereo.cas.support.oauth.OAuth20Constants; import org.apereo.cas.support.oauth.web.endpoints.OAuth20UserProfileControllerController; import org.apereo.cas.ticket.accesstoken.AccessToken; import org.apereo.cas.ticket.accesstoken.AccessTokenFactory; import org.apereo.cas.ticket.accesstoken.DefaultAccessTokenFactory; import org.apereo.cas.ticket.support.AlwaysExpiresExpirationPolicy; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; import java.time.ZonedDateTime; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import static org.junit.Assert.*; /** * This class tests the {@link OAuth20UserProfileControllerController} class. * * @author Jerome Leleu * @since 3.5.2 */ public class OAuth20ProfileControllerTests extends AbstractOAuth20Tests { private static final ObjectMapper MAPPER = new ObjectMapper(); private static final String CONTEXT = "/oauth2.0/"; private static final String ID = "1234"; private static final String NAME = "attributeName"; private static final String NAME2 = "attributeName2"; private static final String VALUE = "attributeValue"; private static final String CONTENT_TYPE = "application/json"; private static final String GET = "GET"; private static final String ATTRIBUTES_PARAM = "attributes"; @Autowired private AccessTokenFactory accessTokenFactory; @Autowired private OAuth20UserProfileControllerController oAuth20ProfileController; @Test public void verifyNoGivenAccessToken() throws Exception { final MockHttpServletRequest mockRequest = new MockHttpServletRequest(GET, CONTEXT + OAuth20Constants.PROFILE_URL); final MockHttpServletResponse mockResponse = new MockHttpServletResponse(); final ResponseEntity<String> entity = oAuth20ProfileController.handleRequest(mockRequest, mockResponse); assertEquals(HttpStatus.UNAUTHORIZED, entity.getStatusCode()); assertEquals(CONTENT_TYPE, mockResponse.getContentType()); assertTrue(entity.getBody().contains(OAuth20Constants.MISSING_ACCESS_TOKEN)); } @Test public void verifyNoExistingAccessToken() throws Exception { final MockHttpServletRequest mockRequest = new MockHttpServletRequest(GET, CONTEXT + OAuth20Constants.PROFILE_URL); mockRequest.setParameter(OAuth20Constants.ACCESS_TOKEN, "DOES NOT EXIST"); final MockHttpServletResponse mockResponse = new MockHttpServletResponse(); final ResponseEntity<String> entity = oAuth20ProfileController.handleRequest(mockRequest, mockResponse); assertEquals(HttpStatus.UNAUTHORIZED, entity.getStatusCode()); assertEquals(CONTENT_TYPE, mockResponse.getContentType()); assertTrue(entity.getBody().contains(OAuth20Constants.EXPIRED_ACCESS_TOKEN)); } @Test public void verifyExpiredAccessToken() throws Exception { final Principal principal = CoreAuthenticationTestUtils.getPrincipal(ID, new HashMap<>()); final Authentication authentication = getAuthentication(principal); final DefaultAccessTokenFactory expiringAccessTokenFactory = new DefaultAccessTokenFactory(new AlwaysExpiresExpirationPolicy()); final AccessToken accessToken = expiringAccessTokenFactory.create(CoreAuthenticationTestUtils.getService(), authentication, new MockTicketGrantingTicket("casuser")); this.ticketRegistry.addTicket(accessToken); final MockHttpServletRequest mockRequest = new MockHttpServletRequest(GET, CONTEXT + OAuth20Constants.PROFILE_URL); mockRequest.setParameter(OAuth20Constants.ACCESS_TOKEN, accessToken.getId()); final MockHttpServletResponse mockResponse = new MockHttpServletResponse(); final ResponseEntity<String> entity = oAuth20ProfileController.handleRequest(mockRequest, mockResponse); assertEquals(HttpStatus.UNAUTHORIZED, entity.getStatusCode()); assertEquals(CONTENT_TYPE, mockResponse.getContentType()); assertTrue(entity.getBody().contains(OAuth20Constants.EXPIRED_ACCESS_TOKEN)); } @Test public void verifyOK() throws Exception { final Map<String, Object> map = new HashMap<>(); map.put(NAME, VALUE); final List<String> list = Arrays.asList(VALUE, VALUE); map.put(NAME2, list); final Principal principal = CoreAuthenticationTestUtils.getPrincipal(ID, map); final Authentication authentication = getAuthentication(principal); final AccessToken accessToken = accessTokenFactory.create(CoreAuthenticationTestUtils.getService(), authentication, new MockTicketGrantingTicket("casuser")); this.ticketRegistry.addTicket(accessToken); final MockHttpServletRequest mockRequest = new MockHttpServletRequest(GET, CONTEXT + OAuth20Constants.PROFILE_URL); mockRequest.setParameter(OAuth20Constants.ACCESS_TOKEN, accessToken.getId()); final MockHttpServletResponse mockResponse = new MockHttpServletResponse(); final ResponseEntity<String> entity = oAuth20ProfileController.handleRequest(mockRequest, mockResponse); assertEquals(HttpStatus.OK, entity.getStatusCode()); assertEquals(CONTENT_TYPE, mockResponse.getContentType()); final String expected = "{\"id\":\"" + ID + "\",\"attributes\":[{\"" + NAME + "\":\"" + VALUE + "\"},{\"" + NAME2 + "\":[\"" + VALUE + "\",\"" + VALUE + "\"]}]}"; final JsonNode expectedObj = MAPPER.readTree(expected); final JsonNode receivedObj = MAPPER.readTree(entity.getBody()); assertEquals(expectedObj.get("id").asText(), receivedObj.get("id").asText()); final JsonNode expectedAttributes = expectedObj.get(ATTRIBUTES_PARAM); final JsonNode receivedAttributes = receivedObj.get(ATTRIBUTES_PARAM); assertEquals(expectedAttributes.findValue(NAME).asText(), receivedAttributes.findValue(NAME).asText()); assertEquals(expectedAttributes.findValues(NAME2), receivedAttributes.findValues(NAME2)); } @Test public void verifyOKWithAuthorizationHeader() throws Exception { final Map<String, Object> map = new HashMap<>(); map.put(NAME, VALUE); final List<String> list = Arrays.asList(VALUE, VALUE); map.put(NAME2, list); final Principal principal = CoreAuthenticationTestUtils.getPrincipal(ID, map); final Authentication authentication = getAuthentication(principal); final AccessToken accessToken = accessTokenFactory.create(CoreAuthenticationTestUtils.getService(), authentication, new MockTicketGrantingTicket("casuser")); this.ticketRegistry.addTicket(accessToken); final MockHttpServletRequest mockRequest = new MockHttpServletRequest(GET, CONTEXT + OAuth20Constants.PROFILE_URL); mockRequest.addHeader("Authorization", OAuth20Constants.BEARER_TOKEN + ' ' + accessToken.getId()); final MockHttpServletResponse mockResponse = new MockHttpServletResponse(); final ResponseEntity<String> entity = oAuth20ProfileController.handleRequest(mockRequest, mockResponse); assertEquals(HttpStatus.OK, entity.getStatusCode()); assertEquals(CONTENT_TYPE, mockResponse.getContentType()); final String expected = "{\"id\":\"" + ID + "\",\"attributes\":[{\"" + NAME + "\":\"" + VALUE + "\"},{\"" + NAME2 + "\":[\"" + VALUE + "\",\"" + VALUE + "\"]}]}"; final JsonNode expectedObj = MAPPER.readTree(expected); final JsonNode receivedObj = MAPPER.readTree(entity.getBody()); assertEquals(expectedObj.get("id").asText(), receivedObj.get("id").asText()); final JsonNode expectedAttributes = expectedObj.get(ATTRIBUTES_PARAM); final JsonNode receivedAttributes = receivedObj.get(ATTRIBUTES_PARAM); assertEquals(expectedAttributes.findValue(NAME).asText(), receivedAttributes.findValue(NAME).asText()); assertEquals(expectedAttributes.findValues(NAME2), receivedAttributes.findValues(NAME2)); } private static Authentication getAuthentication(final Principal principal) { final CredentialMetaData metadata = new BasicCredentialMetaData(new BasicIdentifiableCredential(principal.getId())); final HandlerResult handlerResult = new DefaultHandlerResult(principal.getClass().getCanonicalName(), metadata, principal, new ArrayList<>()); return DefaultAuthenticationBuilder.newInstance() .setPrincipal(principal) .addCredential(metadata) .setAuthenticationDate(ZonedDateTime.now()) .addSuccess(principal.getClass().getCanonicalName(), handlerResult) .build(); } }