You can find more details on OAuth2 Scope and Grant Types here: OAuth2 Grant Type
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:
-
Password (Resource Owner Password)
-
Client Credentials
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.
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 |
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:
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:
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.
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;
}
}
curl https://<client-id>:<client-secret>@example.com/oauth/token -d grant_type=client_credentials -d scope=openid
{
"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:
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:
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:
- Rest Assured API Testing Interview Questions
- RestAssured multipart file upload
- REST Assured Basic Authentication
Top articles in this category:
- OAuth2 protected resources using RestTemplate
- REST Assured Basic Authentication
- Rest Assured API Testing Interview Questions
- Junit interview questions for SDET automation engineer
- 50 Java Interview Questions for SDET Automation Engineer
- RestAssured multipart file upload
- Java Coding Problems for SDET Automation Engineer