All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.atlassian.asap.it.BaseIntegrationTest Maven / Gradle / Ivy

There is a newer version: 2.26.0
Show newest version
package com.atlassian.asap.it;

import java.io.IOException;
import java.net.URI;
import java.security.PublicKey;
import java.util.Optional;

import javax.annotation.Nullable;

import com.atlassian.asap.api.Jwt;
import com.atlassian.asap.api.JwtBuilder;
import com.atlassian.asap.api.SigningAlgorithm;
import com.atlassian.asap.api.client.http.AuthorizationHeaderGenerator;
import com.atlassian.asap.core.client.http.AuthorizationHeaderGeneratorImpl;
import com.atlassian.asap.core.keys.KeyProvider;
import com.atlassian.asap.core.keys.PemReader;
import com.atlassian.asap.core.keys.publickey.ClasspathPublicKeyProvider;

import org.apache.http.HttpHeaders;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.utils.HttpClientUtils;
import org.apache.http.impl.client.HttpClients;
import org.junit.After;
import org.junit.Test;

import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;

/**
 * Performs integration testing by making HTTP requests.
 * Subclasses of this implement the server start/stop and inherit the tests.
 */
public abstract class BaseIntegrationTest
{
    protected static final String AUDIENCE = "test-resource-server";

    protected static final String ISSUER1 = "issuer1";
    protected static final String ISSUER2 = "issuer2";
    protected static final String ISSUER1_RSA_KEY_ID = "issuer1/rsa-key-for-tests";
    protected static final String ISSUER1_EC_KEY_ID = "issuer1/es256-key-for-tests";
    protected static final String ISSUER2_RSA_KEY_ID = "issuer2/rsa-key-for-tests";
    protected static final KeyProvider PUBLIC_KEY_PROVIDER =
            new ClasspathPublicKeyProvider("/publickeyrepo/", new PemReader());

    protected static final String RESOURCE = "resource";

    protected static final String UNAUTHORIZED_SUBJECT = "unauthorized-subject";

    private HttpClient httpClient = HttpClients.createDefault();

    protected abstract URI getUrlForResourceName(String resourceName);

    @After
    public void shutdownHttpClient()
    {
        HttpClientUtils.closeQuietly(httpClient);
    }

    private String generateAuthorizationHeader(Jwt jwt) throws Exception
    {
        AuthorizationHeaderGenerator authorizationHeaderGenerator
            = AuthorizationHeaderGeneratorImpl.createDefault(URI.create("classpath:///privatekeys/"));

        return authorizationHeaderGenerator.generateAuthorizationHeader(jwt);
    }

    private HttpResponse executeRequestWithJwt(String resourceName, Jwt jwt) throws Exception
    {
        String authorizationHeader = generateAuthorizationHeader(jwt);
        return executeRequestWithAuthorization(resourceName, authorizationHeader);
    }

    private HttpResponse executeRequestWithAuthorization(String resourceName,
                                                         @Nullable String authorizationHeader) throws IOException
    {
        HttpGet getRequest = new HttpGet(getUrlForResourceName(resourceName));
        getRequest.setHeader(HttpHeaders.AUTHORIZATION, authorizationHeader);
        return httpClient.execute(getRequest);
    }

    /**
     * Verifies that the server rejects requests that lack the authentication header.
     * @throws Exception if the test fails to execute
     */
    @Test
    public void shouldRejectRequestWithoutAuthenticationHeader() throws Exception
    {
        HttpResponse response = executeRequestWithAuthorization(RESOURCE, null);

        assertUnauthorized(response);
    }

    /**
     * Verifies that the server rejects requests that do not have a bearer token.
     * @throws Exception if the test fails to execute
     */
    @Test
    public void shouldRejectRequestWithBasicAuth() throws Exception
    {
        HttpResponse response = executeRequestWithAuthorization(RESOURCE, "Basic foobar");

        assertUnauthorized(response);
    }

    /**
     * Verifies that the server rejects requests which have an uparseable token.
     * @throws Exception if the test fails to execute
     */
    @Test
    public void shouldRejectRequestWithMalformedToken() throws Exception
    {
        HttpResponse response = executeRequestWithAuthorization(RESOURCE, "Bearer this-is-not-jwt");

        assertUnauthorized(response);
    }

    /**
     * Verifies that the server accepts requests with a valid token using RS256.
     * @throws Exception if the test fails to execute
     */
    @Test
    public void shouldAcceptRequestWithValidRS256Token() throws Exception
    {
        Jwt jwt = JwtBuilder.newJwt()
                .keyId(ISSUER1_RSA_KEY_ID)
                .issuer(ISSUER1)
                .audience(AUDIENCE)
                .build();

        HttpResponse response = executeRequestWithJwt(RESOURCE, jwt);

        assertOk(response);
    }

    /**
     * Verifies that the server accepts requests with a valid token using PS256.
     * @throws Exception if the test fails to execute
     */
    @Test
    public void shouldAcceptRequestWithValidPS256Token() throws Exception
    {
        Jwt jwt = JwtBuilder.newJwt()
                .algorithm(SigningAlgorithm.PS256)
                .keyId(ISSUER1_RSA_KEY_ID)
                .issuer(ISSUER1)
                .audience(AUDIENCE)
                .build();

        HttpResponse response = executeRequestWithJwt(RESOURCE, jwt);

        assertOk(response);
    }

    /**
     * Verifies that the server accepts requests with a valid token using ES256.
     * @throws Exception if the test fails to execute
     */
    @Test
    public void shouldAcceptRequestWithValidES256Token() throws Exception
    {
        Jwt jwt = JwtBuilder.newJwt()
                .algorithm(SigningAlgorithm.ES256)
                .keyId(ISSUER1_EC_KEY_ID)
                .issuer(ISSUER1)
                .audience(AUDIENCE)
                .build();

        HttpResponse response = executeRequestWithJwt(RESOURCE, jwt);

        assertOk(response);
    }

    /**
     * Verifies that the server rejects requests if the subject is not authorized.
     * @throws Exception if the test fails to execute
     */
    @Test
    public void shouldRejectRequestWithUnauthorizedSubject() throws Exception
    {
        Jwt jwt = JwtBuilder.newJwt()
                .keyId(ISSUER1_RSA_KEY_ID)
                .issuer(ISSUER1)  // issuer is authorized, but subject is not
                .audience(AUDIENCE)
                .subject(Optional.of(UNAUTHORIZED_SUBJECT))
                .build();

        HttpResponse response = executeRequestWithJwt(RESOURCE, jwt);

        assertForbidden(response);
    }

    /**
     * Verifies that the server rejects requests if the issuer is not authorized.
     * @throws Exception if the test fails to execute
     */
    @Test
    public void shouldRejectRequestWithUnauthorizedIssuer() throws Exception
    {
        Jwt jwt = JwtBuilder.newJwt()
                .keyId(ISSUER2_RSA_KEY_ID)
                .issuer(ISSUER2)
                .audience(AUDIENCE)
                .subject(Optional.of(ISSUER1)) // subject is authorized, but issuer is not
                .build();

        HttpResponse response = executeRequestWithJwt(RESOURCE, jwt);

        assertForbidden(response);
    }

    private static void assertOk(HttpResponse response)
    {
        assertThat(response.getStatusLine().getStatusCode(), is(HttpStatus.SC_OK));
    }

    private static void assertUnauthorized(HttpResponse response)
    {
        assertThat(response.getStatusLine().getStatusCode(), is(HttpStatus.SC_UNAUTHORIZED));
    }

    private static void assertForbidden(HttpResponse response)
    {
        assertThat(response.getStatusLine().getStatusCode(), is(HttpStatus.SC_FORBIDDEN));
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy