org.cloudfoundry.identity.uaa.login.feature.AutologinIT.java Source code

Java tutorial

Introduction

Here is the source code for org.cloudfoundry.identity.uaa.login.feature.AutologinIT.java

Source

/*******************************************************************************
 *     Cloud Foundry 
 *     Copyright (c) [2009-2014] 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.login.feature;

import org.cloudfoundry.identity.uaa.login.test.DefaultIntegrationTestConfig;
import org.cloudfoundry.identity.uaa.login.test.IntegrationTestRule;
import org.cloudfoundry.identity.uaa.login.test.TestClient;
import org.cloudfoundry.identity.uaa.test.UaaTestAccounts;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.RestOperations;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static org.junit.Assert.assertEquals;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = DefaultIntegrationTestConfig.class)
public class AutologinIT {

    @Autowired
    @Rule
    public IntegrationTestRule integrationTestRule;

    @Autowired
    WebDriver webDriver;

    @Value("${integration.test.base_url}")
    String baseUrl;

    @Value("${integration.test.app_url}")
    String appUrl;

    @Autowired
    RestOperations restOperations;

    @Autowired
    TestClient testClient;

    private UaaTestAccounts testAccounts = UaaTestAccounts.standard(null);

    @Test
    public void testAutologinFlow() throws Exception {
        webDriver.get(baseUrl + "/logout.do");

        HttpHeaders headers = getAppBasicAuthHttpHeaders();

        Map<String, String> requestBody = new HashMap<>();
        requestBody.put("username", testAccounts.getUserName());
        requestBody.put("password", testAccounts.getPassword());

        ResponseEntity<Map> autologinResponseEntity = restOperations.exchange(baseUrl + "/autologin",
                HttpMethod.POST, new HttpEntity<>(requestBody, headers), Map.class);
        String autologinCode = (String) autologinResponseEntity.getBody().get("code");

        String authorizeUrl = UriComponentsBuilder.fromHttpUrl(baseUrl).path("/oauth/authorize")
                .queryParam("redirect_uri", appUrl).queryParam("response_type", "code")
                .queryParam("scope", "openid").queryParam("client_id", "app").queryParam("code", autologinCode)
                .build().toUriString();

        webDriver.get(authorizeUrl);

        webDriver.get(baseUrl);

        assertEquals(testAccounts.getUserName(), webDriver.findElement(By.cssSelector(".header .nav")).getText());
    }

    @Test
    public void testSimpleAutologinFlow() throws Exception {
        HttpHeaders headers = getAppBasicAuthHttpHeaders();

        LinkedMultiValueMap<String, String> requestBody = new LinkedMultiValueMap<>();
        requestBody.add("username", testAccounts.getUserName());
        requestBody.add("password", testAccounts.getPassword());

        //generate an autologin code with our credentials
        ResponseEntity<Map> autologinResponseEntity = restOperations.exchange(baseUrl + "/autologin",
                HttpMethod.POST, new HttpEntity<>(requestBody, headers), Map.class);
        String autologinCode = (String) autologinResponseEntity.getBody().get("code");

        //start the authorization flow - this will issue a login event
        //by using the autologin code
        String authorizeUrl = UriComponentsBuilder.fromHttpUrl(baseUrl).path("/oauth/authorize")
                .queryParam("redirect_uri", appUrl).queryParam("response_type", "code")
                .queryParam("client_id", "app").queryParam("code", autologinCode).build().toUriString();

        //rest template that does NOT follow redirects
        RestTemplate template = new RestTemplate(new DefaultIntegrationTestConfig.HttpClientFactory());
        headers.remove("Authorization");
        ResponseEntity<Map> authorizeResponse = template.exchange(authorizeUrl, HttpMethod.GET,
                new HttpEntity<>(new HashMap<String, String>(), headers), Map.class);

        //we are now logged in. retrieve the JSESSIONID
        List<String> cookies = authorizeResponse.getHeaders().get("Set-Cookie");
        assertEquals(1, cookies.size());
        headers = getAppBasicAuthHttpHeaders();
        headers.add("Cookie", cookies.get(0));

        //if we receive a 200, then we must approve our scopes
        if (HttpStatus.OK == authorizeResponse.getStatusCode()) {
            authorizeUrl = UriComponentsBuilder.fromHttpUrl(baseUrl).path("/oauth/authorize")
                    .queryParam("user_oauth_approval", "true").build().toUriString();
            authorizeResponse = template.exchange(authorizeUrl, HttpMethod.POST,
                    new HttpEntity<>(new HashMap<String, String>(), headers), Map.class);
        }

        //approval is complete, we receive a token code back
        assertEquals(HttpStatus.FOUND, authorizeResponse.getStatusCode());
        List<String> location = authorizeResponse.getHeaders().get("Location");
        assertEquals(1, location.size());
        String newCode = location.get(0).substring(location.get(0).indexOf("code=") + 5);

        //request a token using our code
        String tokenUrl = UriComponentsBuilder.fromHttpUrl(baseUrl).path("/oauth/token")
                .queryParam("response_type", "token").queryParam("grant_type", "authorization_code")
                .queryParam("code", newCode).queryParam("redirect_uri", appUrl).build().toUriString();

        ResponseEntity<Map> tokenResponse = template.exchange(tokenUrl, HttpMethod.POST,
                new HttpEntity<>(new HashMap<String, String>(), headers), Map.class);
        assertEquals(HttpStatus.OK, tokenResponse.getStatusCode());

        //here we must reset our state. we do that by following the logout flow.
        headers.clear();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        ResponseEntity<Void> loginResponse = restOperations.exchange(baseUrl + "/login.do", HttpMethod.POST,
                new HttpEntity<>(requestBody, headers), Void.class);
        cookies = loginResponse.getHeaders().get("Set-Cookie");
        assertEquals(1, cookies.size());
        headers.clear();
        headers.add("Cookie", cookies.get(0));
        restOperations.exchange(baseUrl + "/profile", HttpMethod.GET, new HttpEntity<>(null, headers), Void.class);

        String revokeApprovalsUrl = UriComponentsBuilder.fromHttpUrl(baseUrl).path("/profile").build()
                .toUriString();
        requestBody.clear();
        requestBody.add("clientId", "app");
        requestBody.add("delete", "");
        ResponseEntity<Void> revokeResponse = template.exchange(revokeApprovalsUrl, HttpMethod.POST,
                new HttpEntity<>(requestBody, headers), Void.class);
        assertEquals(HttpStatus.FOUND, revokeResponse.getStatusCode());
    }

    @Test
    public void testFormEncodedAutologinRequest() throws Exception {
        HttpHeaders headers = getAppBasicAuthHttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);

        MultiValueMap<String, String> requestBody = new LinkedMultiValueMap<>();
        requestBody.add("username", testAccounts.getUserName());
        requestBody.add("password", testAccounts.getPassword());

        ResponseEntity<Map> autologinResponseEntity = restOperations.exchange(baseUrl + "/autologin",
                HttpMethod.POST, new HttpEntity<>(requestBody, headers), Map.class);

        String autologinCode = (String) autologinResponseEntity.getBody().get("code");
        assertEquals(6, autologinCode.length());
    }

    @Test
    public void testPasswordRequired() throws Exception {
        HttpHeaders headers = getAppBasicAuthHttpHeaders();

        Map<String, String> requestBody = new HashMap<>();
        requestBody.put("username", testAccounts.getUserName());

        try {
            restOperations.exchange(baseUrl + "/autologin", HttpMethod.POST, new HttpEntity<>(requestBody, headers),
                    Map.class);
        } catch (HttpClientErrorException e) {
            assertEquals(HttpStatus.UNAUTHORIZED, e.getStatusCode());
        }
    }

    @Test
    public void testClientAuthorization() throws Exception {
        Map<String, String> requestBody = new HashMap<>();
        requestBody.put("username", testAccounts.getUserName());
        requestBody.put("password", testAccounts.getPassword());

        try {
            restOperations.exchange(baseUrl + "/autologin", HttpMethod.POST, new HttpEntity<>(requestBody),
                    Map.class);
        } catch (HttpClientErrorException e) {
            assertEquals(HttpStatus.UNAUTHORIZED, e.getStatusCode());
        }
    }

    @Test
    public void testClientIdMustBeConsistent() throws Exception {
        webDriver.get(baseUrl + "/logout.do");

        HttpHeaders headers = getAppBasicAuthHttpHeaders();

        Map<String, String> requestBody = new HashMap<>();
        requestBody.put("username", testAccounts.getUserName());
        requestBody.put("password", testAccounts.getPassword());

        ResponseEntity<Map> autologinResponseEntity = restOperations.exchange(baseUrl + "/autologin",
                HttpMethod.POST, new HttpEntity<>(requestBody, headers), Map.class);
        String autologinCode = (String) autologinResponseEntity.getBody().get("code");

        String authorizeUrl = UriComponentsBuilder.fromHttpUrl(baseUrl).path("/oauth/authorize")
                .queryParam("redirect_uri", appUrl).queryParam("response_type", "code")
                .queryParam("scope", "openid").queryParam("client_id", "stealer_of_codes")
                .queryParam("code", autologinCode).build().toUriString();

        try {
            restOperations.exchange(authorizeUrl, HttpMethod.GET, null, Void.class);
        } catch (HttpClientErrorException e) {
            assertEquals(HttpStatus.UNAUTHORIZED, e.getStatusCode());
        }
    }

    private HttpHeaders getAppBasicAuthHttpHeaders() {
        HttpHeaders headers = new HttpHeaders();
        headers.add("Authorization", testClient.getBasicAuthHeaderValue("app", "appclientsecret"));
        return headers;
    }
}