org.apigw.authserver.AuthorizationCodeProviderIntegrationtest.java Source code

Java tutorial

Introduction

Here is the source code for org.apigw.authserver.AuthorizationCodeProviderIntegrationtest.java

Source

/**
 *   Copyright 2013 Stockholm County Council
 *
 *   This file is part of APIGW
 *
 *   APIGW is free software; you can redistribute it and/or modify
 *   it under the terms of version 2.1 of the GNU Lesser General Public
 *   License as published by the Free Software Foundation.
 *
 *   APIGW is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU Lesser General Public License for more details.
 *
 *   You should have received a copy of the GNU Lesser General Public
 *   License along with APIGW; if not, write to the
 *   Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 *   Boston, MA 02111-1307  USA
 *
 */

package org.apigw.authserver;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

import java.util.Arrays;
import java.util.EnumSet;

import org.apigw.authserver.svc.AdministrationServices;
import static org.apigw.authserver.types.domain.CertifiedClientRole.ROLE_CLIENT;
import static org.apigw.authserver.types.domain.CertifiedClientRole.ROLE_TRUSTED_CLIENT;
import org.apigw.util.OAuthTestHelper;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.Ignore;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;

/**
 * This class is based on code created by:
 * @author Dave Syer
 * @author Luke Taylor
 * The original code came from the Spring Security Oauth project: 
 *    https://github.com/SpringSource/spring-security-oauth
 * and is licensed under Apache License Version 2.0: 
 *    https://github.com/SpringSource/spring-security-oauth/blob/master/license.txt
 * 
 * The code has been modified and extended by:
 * @author Albert rwall
 * @author Christian Hilmersson 
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:intsvc-integration-test-context.xml")
public class AuthorizationCodeProviderIntegrationtest {

    private static final Logger log = LoggerFactory.getLogger(AuthorizationCodeProviderIntegrationtest.class);
    private final static String REDIRECT_URL = "http://localhost:8888/apigw-auth-server-web/resources/css/main.css";
    private final static String CLIENT_ID = "apitest";
    private final static String SCOPE = "CRM_SCHEDULING_READ";

    private final static String USERNAME = "196309283221";
    private final static String PASSWORD = "koala";

    @Rule
    public ServerRunning serverRunning = ServerRunning.isRunning();

    public OAuthTestHelper helper = new OAuthTestHelper(serverRunning, USERNAME, PASSWORD);

    @Autowired
    private AdministrationServices administrationServices;

    private static boolean initialized = false;

    @Before
    public void init() {
        if (AuthorizationCodeProviderIntegrationtest.initialized) {
            log.info("Already initialized, skipping data population");
            return;
        }

        log.info("Removing any previously registered data to avoid duplicates...");
        if (administrationServices.findCertifiedClientByClientId("another_client") != null) {
            administrationServices.deleteCertifiedClientByClientId("another_client");
        }
        if (administrationServices.findCertifiedClientByClientId("apitest") != null) {
            administrationServices.deleteCertifiedClientByClientId("apitest");
        }
        if (administrationServices.findPermission("CLINICALPROCESS_LOGISTICS_LOGISTICS_READ") != null) {
            administrationServices.deletePermission("CLINICALPROCESS_LOGISTICS_LOGISTICS_READ");
        }
        if (administrationServices.findPermission("CLINICALPROCESS_HEALTHCOND_DESCRIPTION_READ") != null) {
            administrationServices.deletePermission("CLINICALPROCESS_HEALTHCOND_DESCRIPTION_READ");
        }
        if (administrationServices.findPermission("CRM_CARELISTING_READ") != null) {
            administrationServices.deletePermission("CRM_CARELISTING_READ");
        }
        if (administrationServices.findPermission("CRM_REQUESTSTATUS_READ") != null) {
            administrationServices.deletePermission("CRM_REQUESTSTATUS_READ");
        }
        if (administrationServices.findPermission("CRM_SCHEDULING_WRITE") != null) {
            administrationServices.deletePermission("CRM_SCHEDULING_WRITE");
        }
        if (administrationServices.findPermission("CRM_SCHEDULING_READ") != null) {
            administrationServices.deletePermission("CRM_SCHEDULING_READ");
        }

        log.info("Populating test data...");

        administrationServices.registerPermission("CRM_SCHEDULING_READ", "Lsa tidbokningar");
        administrationServices.registerPermission("CRM_SCHEDULING_WRITE", "Skriva tidbokningar");
        administrationServices.registerPermission("CRM_REQUESTSTATUS_READ", "Lsa remiss-status");
        administrationServices.registerPermission("CRM_CARELISTING_READ", "Lsa listingar");
        administrationServices.registerPermission("CLINICALPROCESS_HEALTHCOND_DESCRIPTION_READ",
                "Lsa vrddokumentation");
        administrationServices.registerPermission("CLINICALPROCESS_LOGISTICS_LOGISTICS_READ",
                "Lsa vrdkontakter");

        administrationServices.registerApplication("apitest", "API Test", "Description of the API Test application",
                0L, 0L,
                "CN=Spring Security Test CA,OU=Spring Security,O=Spring Framework,L=Glasgow,ST=Scotland,C=GB",
                "CN=dianne,OU=Spring Security,O=Spring Framework,C=AU", "Callista Enterprise",
                Arrays.asList(
                        new String[] { "CRM_SCHEDULING_READ", "CRM_SCHEDULING_WRITE", "CRM_REQUESTSTATUS_READ",
                                "CRM_CARELISTING_READ", "CLINICALPROCESS_HEALTHCOND_DESCRIPTION_READ",
                                "CLINICALPROCESS_LOGISTICS_LOGISTICS_READ" }),
                "secret", EnumSet.of(ROLE_CLIENT, ROLE_TRUSTED_CLIENT));

        administrationServices.registerApplication("another_client", "Another client", "Application description",
                0L, 0L, "CA_2", null, "Callista Enterprise", Arrays.asList(new String[] { "CRM_SCHEDULING_READ" }),
                "secret", EnumSet.of(ROLE_CLIENT, ROLE_TRUSTED_CLIENT));
        AuthorizationCodeProviderIntegrationtest.initialized = true;
    }

    @Test
    public void testAuthorizationRequestRedirectsToLogin() throws Exception {
        log.debug("testAuthorizationRequestRedirectsToLogin");

        HttpHeaders headers = new HttpHeaders();
        headers.setAccept(Arrays.asList(MediaType.TEXT_HTML));

        String location = helper.getAuthorizeUrl(CLIENT_ID, REDIRECT_URL, SCOPE);
        ResponseEntity<Void> result = serverRunning.getForResponse(location, headers);
        assertEquals(HttpStatus.FOUND, result.getStatusCode());
        location = result.getHeaders().getLocation().toString();

        if (result.getHeaders().containsKey("Set-Cookie")) {
            String cookie = result.getHeaders().getFirst("Set-Cookie");
            headers.set("Cookie", cookie);
        }

        ResponseEntity<String> response = serverRunning.getForString(location, headers);
        // should be directed to the login screen...
        assertTrue(response.getBody().contains("/login.do"));
        assertTrue(response.getBody().contains("j_username"));
        assertTrue(response.getBody().contains("j_password"));
    }

    @Test
    public void testSuccessfulAuthorizationCodeFlow() throws Exception {
        log.debug("testSuccessfulAuthorizationCodeFlow");
        String code = helper.getAuthorizationCode(CLIENT_ID, REDIRECT_URL, SCOPE);
        // Get the token using the authorization code (no session required because it's a back channel)
        TokenResponseDTO accessToken = helper.getAccessToken(CLIENT_ID, REDIRECT_URL, code, SCOPE);

        assertNotNull(accessToken);
        assertNotNull(accessToken.getExpiresIn());
        assertFalse(accessToken.getExpiresIn().equals("0"));

        // first make sure the resource is actually protected.
        assertFalse(HttpStatus.OK
                .equals(serverRunning.getStatusCode("/crm-scheduling-api/crm/scheduling/v1/schedule")));

        // now make sure an authorized request is valid.
        HttpHeaders headers = new HttpHeaders();
        headers.set("Authorization",
                String.format("%s %s", OAuth2AccessToken.BEARER_TYPE, accessToken.getAccessToken()));

        assertEquals(HttpStatus.OK,
                serverRunning.getStatusCode("/crm-scheduling-api/crm/scheduling/v1/schedule", headers));
    }

    @Test
    public void testUserDeniesConfirmation() throws Exception {
        log.debug("testUserDeniesConfirmation");
        String cookie = helper.loginAndGetConfirmationPage(CLIENT_ID, REDIRECT_URL, SCOPE);

        HttpHeaders headers = new HttpHeaders();
        headers.setAccept(Arrays.asList(MediaType.TEXT_HTML));
        headers.set("Cookie", cookie);

        MultiValueMap<String, String> formData = new LinkedMultiValueMap<String, String>();
        formData.add("user_oauth_approval", "false");
        ResponseEntity<Void> result = serverRunning.postForStatus("/apigw-auth-server-web/oauth/authorize", headers,
                formData);
        assertEquals(HttpStatus.FOUND, result.getStatusCode());

        String location = result.getHeaders().getFirst("Location");
        assertTrue(location.startsWith(REDIRECT_URL));
        assertTrue(location.substring(location.indexOf('?')).contains("error=access_denied"));
        assertTrue(location.contains("state=gzzFqB!!!"));
    }

    public void testInvalidScopeInTokenRequest() throws Exception {
        ResponseEntity<Void> response = helper.attemptToGetConfirmationPage(CLIENT_ID, REDIRECT_URL, "bogus");
        assertEquals(HttpStatus.UNAUTHORIZED, response.getStatusCode());
    }

    @Test
    public void testNoClientIdProvided() throws Exception {
        log.debug("testNoClientIdProvided");
        ResponseEntity<Void> response = helper.attemptToGetConfirmationPage(null, REDIRECT_URL, SCOPE);
        assertEquals(HttpStatus.UNAUTHORIZED, response.getStatusCode());
    }

    @Test
    public void testNoRedirect() throws Exception {
        log.debug("testNoRedirect");
        ResponseEntity<Void> response = helper.attemptToGetConfirmationPage(CLIENT_ID, null, SCOPE);
        assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode());
    }

    @Test
    public void testInvalidScopeInResourceRequest() throws Exception {
        log.debug("testInvalidScopeInResourceRequest");
        String code = helper.getAuthorizationCode(CLIENT_ID, REDIRECT_URL, "CRM_SCHEDULING_WRITE");
        TokenResponseDTO accessToken = helper.getAccessToken(CLIENT_ID, REDIRECT_URL, code, "CRM_SCHEDULING_WRITE",
                HttpStatus.OK);
        assertNotNull(accessToken);

        // now make sure an unauthorized request fails the right way.
        HttpHeaders headers = new HttpHeaders();
        headers.set("Authorization",
                String.format("%s %s", OAuth2AccessToken.BEARER_TYPE, accessToken.getAccessToken()));
        ResponseEntity<String> response = serverRunning.getForString("/crm-scheduling-api/crm/scheduling/booking",
                headers);

        assertEquals(HttpStatus.FORBIDDEN, response.getStatusCode());

        String authenticate = response.getHeaders().getFirst("WWW-Authenticate");
        assertNotNull(authenticate);
        assertTrue(authenticate.startsWith("Bearer"));
        assertTrue(authenticate.contains("scope=\""));

    }

    @Test
    public void testInvalidAccessToken() throws Exception {
        log.debug("testInvalidAccessToken");
        // now make sure an unauthorized request fails the right way.
        HttpHeaders headers = new HttpHeaders();
        headers.set("Authorization", String.format("%s %s", OAuth2AccessToken.BEARER_TYPE, "FOO"));
        ResponseEntity<String> response = serverRunning.getForString("/crm-scheduling-api/crm/scheduling/booking",
                headers);
        assertEquals(HttpStatus.UNAUTHORIZED, response.getStatusCode());

        String authenticate = response.getHeaders().getFirst("WWW-Authenticate");
        assertNotNull(authenticate);
        assertTrue(authenticate.startsWith("Bearer"));
        // Resource Server doesn't know what scopes are required until teh token can be validated
        assertFalse(authenticate.contains("scope=\""));

    }
}