OAuth2 protected resources in RestAssured Testcases

Upasana | December 12, 2019 | 4 min read | 8,453 views | Rest Assured


There are different Grant Types in OAuth 2.0, most common of which are:

  1. Password (Resource Owner Password)

  2. Client Credentials

More on OAuth 2.0

You can find more details on OAuth2 Scope and Grant Types here: OAuth2 Grant Type

Here in this article we will cover how to access OAuth2 protected resources in Rest Assured testcases using access token obtained with any of the above two grant types.

An OAuth2 Authorization Server is responsible for issuing JWT accessToken/refreshToken when a resource owner presents its credentials. credentials typically consists of ClientId/ClientSecret, username/password, grant_type and scope of the request.

Using Password grant type

In this section we will use RestAssured library to hit the token endpoint on authorization server and generate the accessToken using password grant type.

Resource Owner Password Credentials grant type
import io.restassured.response.Response;
import org.json.JSONException;
import org.json.JSONObject;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import static io.restassured.RestAssured.given;

public class OAuth2Test {

    private final Logger logger = LoggerFactory.getLogger(OAuth2Test.class);

    private String resourceOwnerLogin(String tokenUri, String clientId, String clientSecret, String username, String password, String scope) throws JSONException {
        logger.info("Getting OAuth Token from server - {}", tokenUri);
        Response response =
                given().auth().preemptive().basic(clientId, clientSecret)   (1)
                        .formParam("grant_type", "password")
                        .formParam("username", username)
                        .formParam("password", password)
                        .formParam("scope", scope)
                        .when()
                        .post(tokenUri);

        JSONObject jsonObject = new JSONObject(response.getBody().asString());
        String accessToken = jsonObject.get("access_token").toString();
        String tokenType = jsonObject.get("token_type").toString();
        logger.info("Oauth Token for {} with type {} is {}", username, tokenType, accessToken);
        return accessToken;
    }
}
1 cliendId and clientSecret are basic credentials provided by OAuth2 Provider
Using curl, we can issue the below request to obtain access token from command line.
curl https://<clientId>:<clientSecret>@example.com/oauth/token -d grant_type=password -d username=<username> -d password=<password> -d scope=<scope>

Now this accessToken can be used to make calls to the protected resource server using the below syntax:

Making Call to actual service using recently acquired AccessToken
public class OAuth2Test {
    public void callSecuredEndpoint(String accessToken) {
        //language=JSON
        String jsonString = "{\"id\": \"100\"}";
        Response response = given().auth().preemptive().oauth2(accessToken) (1)
                .contentType("application/json")
                .body(jsonString)
                .when()
                .post("/api/feed");
        String responseBody = response.getBody().asString();
        if (response.getStatusCode() >= 200 && response.getStatusCode() <= 299) {
            logger.info("Create Daily Feed Response = " + responseBody);
        } else {
            logger.error("Error creating daily feed = {}", responseBody);
        }
    }
}
1 Passing the OAuth2 AccessToken in request.

Acquiring AccessToken using RefreshToken

Normally AccessToken is valid for a short duration. RefreshToken can be used to create a new AccessToken without actually supplying the Resource Owner Credentials, as shown in the following code:

Get AccessToken using RefreshToken
public class OAuth2Test {

    private final Logger logger = LoggerFactory.getLogger(OAuth2Test.class);

    private TokenInfo accessTokenUsingRefreshToken(String tokenUri, String clientId, String clientSecret, String refreshToken) throws JSONException {
        logger.info("Getting OAuth Token using RefreshToken - {}", tokenUri);
        Response response =
                given().auth().preemptive().basic(clientId, clientSecret)
                        .formParam("grant_type", "refresh_token")
                        .formParam("refresh_token", refreshToken)
                        .when()
                        .post(tokenUri);

        JSONObject jsonObject = new JSONObject(response.getBody().asString());
        String accessToken = jsonObject.get("access_token").toString();
        String newRefreshToken = jsonObject.get("refresh_token").toString();
        String tokenType = jsonObject.get("token_type").toString();
        logger.info("Oauth Token with type {} is {}", tokenType, accessToken);
        return new TokenInfo(accessToken, newRefreshToken, tokenType);
    }

}

Using Client Credentials grant type

client credentials grant type is used mostly for backend to backend communication without requiring the user’s credentials.

Client Credentials grant type
public class OAuth2Test {
    private String clientCredentialsLogin(String tokenUri, String clientId, String clientSecret, String scope) throws JSONException {
        logger.info("Getting OAuth Token from server - {}", tokenUri);
        Response response =
                given().auth().preemptive().basic(clientId, clientSecret)
                        .formParam("grant_type", "client_credentials")
                        .formParam("scope", scope)
                        .when()
                        .post(tokenUri);

        JSONObject jsonObject = new JSONObject(response.getBody().asString());
        String accessToken = jsonObject.get("access_token").toString();
        String tokenType = jsonObject.get("token_type").toString();
        logger.info("Oauth Token with type {} is {}", tokenType, accessToken);
        return accessToken;
    }
}
The equivalent curl command for the same is:
curl https://<client-id>:<client-secret>@example.com/oauth/token -d grant_type=client_credentials -d scope=openid
Sample response
{
  "access_token" : "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsiZ29sby1z0aG9zYjgtZWI3Yy00ZTljLWItZSJ9.NYemrNTp3uF_5qvmIDwlJvaCUHcP7VpWlS0vwMo8Z3WerA",
  "token_type" : "bearer",
  "expires_in" : 3599,
  "scope" : "openid",
  "jti" : "f3abd3b8-eb7c-4e9c-b915-4ae3e39e661d"
}

Now we can use the AccessToke to access protected resource on Resource Server:

Access protected resource using access token
public class OAuth2Test {
    public void getDataFromResourceServer(String accessToken) {
        Response response = given().auth().preemptive().oauth2(accessToken)
                .contentType("application/json")
                .when()
                .get("/api/feed");
        String responseBody = response.getBody().asString();
        if (response.getStatusCode() >= 200 && response.getStatusCode() <= 299) {
            logger.info("Create Daily Feed Response = " + responseBody);
        } else {
            logger.error("Error creating daily feed = {}", responseBody);
        }
    }
}

Sample RestAssured testcase

Make sure you import the required rest-assured libraries into your project:

If you are using Gradle based build, then your build.gradle have the following entries:

build.gradle
plugins {
	id 'org.springframework.boot' version '2.2.2.RELEASE'
	id 'java'
	id 'org.jetbrains.kotlin.jvm' version "1.3.61"
	id 'io.spring.dependency-management' version "1.0.8.RELEASE"
}

sourceCompatibility = 11

dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-web'
	implementation 'io.rest-assured:json-path:4.1.2'
	implementation 'io.rest-assured:xml-path:4.1.2'
	// https://mvnrepository.com/artifact/io.rest-assured/rest-assured
	testImplementation group: 'io.rest-assured', name: 'rest-assured', version: '4.1.2'
	testImplementation ('org.springframework.boot:spring-boot-starter-test') {
		exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
	}
}

test {
	useJUnitPlatform()
}

A sample testcase for rest-assured will look like below:

public class OAuth2Test {
    @Test
    public void testAuthWithResourceOwnerCredentials() throws JSONException {
        final String accessToken = resourceOwnerLogin("https://example.com/oauth/token", "<client-id>", "<client-secret>", "<username>", "<password>", "<scope>");
        logger.info("AccessToken = {}", accessToken);
        //TODO: Whatever you want to do with access token now
        getDataFromResourceServer(accessToken);
    }

    @Test
    public void testAuthWithClientCredentials() throws JSONException {
        final String accessToken = clientCredentialsLogin("https://example.com/oauth/token", "<client-id>", "<client-secret>", "<scope>");
        logger.info("AccessToken = {}", accessToken);
        //TODO: Whatever you want to do with access token now
        getDataFromResourceServer(accessToken);
    }
}

That’s all!

If you are looking to use RestTemplate instead, then follow this article- OAuth2 protected resources using RestTemplate


Rest Assured:
  1. Rest Assured API Testing Interview Questions
  2. RestAssured multipart file upload
  3. REST Assured Basic Authentication
See all articles in Rest Assured
Top articles in this category:
  1. OAuth2 protected resources using RestTemplate
  2. REST Assured Basic Authentication
  3. Rest Assured API Testing Interview Questions
  4. Junit interview questions for SDET automation engineer
  5. 50 Java Interview Questions for SDET Automation Engineer
  6. RestAssured multipart file upload
  7. Java Coding Problems for SDET Automation Engineer

Recommended books for interview preparation:

Find more on this topic:
Buy interview books

Java & Microservices interview refresher for experienced developers.