Using REST-assured to Test OAuth 2.0 flow Examples
OAuth 2.0 provides four different flows, but the main goal of each flow is to obtain an access_token and use it to access protected resources.
The four different flows are:
- Authorization Code Grant
- Implicit Grant Flow
- Client Credential
- Password Grant Flow
This tutorial provides code examples using REST-assured to test the OAuth 2.0 flows, Authorization Code Grant and Client Credential flows.
Authorization Code Grant Flow
This is the most common flow where a code is issued and used to obtain the access_token. This code is pushed to a front-end application (on the browser) after the user logs in. The access_token is issued on server side, authenticating the client with its password and the obtained code.
Three step process:
- 1 - Get Auth Code
- 2 - Get Access Token
- 3 - Use Access Token (to access protected resources)
Get Auth Code
The first step is to get the code
:
import io.restassured.RestAssured;
import io.restassured.http.ContentType;
import io.restassured.response.Response;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import static io.restassured.RestAssured.given;
import java.util.Base64;
public class RestAssuredOAuth2 {
public static String clientId = "some_client_id";
public static String redirectUri = "some_redirect_uri";
public static String scope = "some_scope";
public static String username = "some_email";
public static String password = "some_password";
public static String encode(String str1, String str2) {
return new String(Base64.getEncoder().encode((str1 + ":" + str2).getBytes()));
}
public static Response getCode() {
String authorization = encode(username, password);
return
given()
.header("authorization", "Basic " + authorization)
.contentType(ContentType.URLENC)
.formParam("response_type", "code")
.queryParam("client_id", clientId)
.queryParam("redirect_uri", redirectUri)
.queryParam("scope", scope)
.post("/oauth2/authorize")
.then()
.statusCode(200)
.extract()
.response();
}
public static String parseForOAuth2Code(Response response) {
return response.jsonPath().getString("code");
}
@BeforeAll
public static void setup() {
RestAssured.baseURI = "https://some-url.com";
}
@Test
public void iShouldGetCode() {
Response response = getCode();
String code = parseForOAuth2Code(response);
Assertions.assertNotNull(code);
}
}
Get Access Token
Once we obtain the authorization code, we can then request for access_token
:
public static Response getToken(String authCode) {
String authorization = encode(username, password);
return
given()
.header("authorization", "Basic " + authorization)
.contentType(ContentType.URLENC)
.queryParam("code", authCode)
.queryParam("redirect_uri", redirectUri)
.queryParam("grant_type", grantType)
.post("/oauth2/token")
.then()
.statusCode(200)
.extract()
.response();
}
public static String parseForAccessToken(Response loginResponse) {
return loginResponse.jsonPath().getString("access_token");
}
@Test
public void iShouldGetToken() {
Response tokenResponse = getToken(code);
String accessToken = parseForAccessToken(tokenResponse);
Assertions.assertNotNull(accessToken);
}
Using Access Token
Finally, when we have a valid access_token
, we can then make requests to protected resources:
public static void getUsers() {
given().auth()
.oauth2(accessToken)
.when()
.get("/users")
.then()
.statusCode(200);
}
We can also send the access token as an Authorization Header
with the Bearer
prefix:
For example:
public static void getUsers() {
given()
.header("Authorization", "Bearer " + accessToken)
.when()
.get("/users")
.then()
.statusCode(200);
}
Client Credential Flow
The client credential flow has no UI (browser) involved and is mainly used for Machine-to-Machine authorization.
In REST-assured, this will look like:
import io.restassured.RestAssured;
import io.restassured.http.ContentType;
import io.restassured.response.Response;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import static io.restassured.RestAssured.given;
import static io.restassured.RestAssured.requestSpecification;
public class RestAssuredOAuth2 {
public static Response response;
private String userAdminClientId = System.getenv("M2M_USER_ADMIN_CLIENT_ID");
private String userAdminClientSecret = System.getenv("M2M_USER_ADMIN_CLIENT_SECRET");
private String oauth2Payload = "{\n" +
" \"client_id\": \"" + userAdminClientId + "\",\n" +
" \"client_secret\": \"" + userAdminClientSecret + "\",\n" +
" \"audience\": \"https://some-url.com/user\",\n" +
" \"grant_type\": \"client_credentials\",\n" +
" \"scope\": \"user:admin\" \n}";
private static String createUserPayload = "{\n" +
" \"username\": \"api-user\",\n" +
" \"email\": \"api-user@putsbox.com\",\n" +
" \"password\": \"Passw0rd123!\",\n" +
" \"firstName\": \"my-first-name\",\n" +
" \"lastName\": \"my-last-name\",\n" +
" \"roles\": [\"read\"] \n}";
public void userAdminConfigSetup() {
requestSpecification = given().auth().oauth2(getAccessToken(oauth2Payload))
.header("Accept", ContentType.JSON.getAcceptHeader())
.contentType(ContentType.JSON);
}
public String getAccessToken(String payload) {
return given()
.contentType(ContentType.JSON)
.body(payload)
.post("/token")
.then().extract().response()
.jsonPath().getString("access_token");
}
@BeforeAll
public static void setup() {
RestAssured.baseURI = "https://some-url.com";
}
@Test
public void createUser() {
userAdminConfigSetup();
response = given(requestSpecification)
.body(createUserPayload)
.post("/user")
.then().extract().response();
Assertions.assertEquals(201, response.statusCode());
}
}
Conclusion
Here, we provided code examples with REST-assured on how to get access_token
using the OAuth 2.0 flows. Once we get the access_token
we can then make requests to protected resources.
Hope you found the above useful.