Handling Auth Token

Sample REST APIs

Let us use Reqres as our APIs under test.

It is common that APIs accept authorization token. Let us see how do we pass auth token to API. We have a login API that generates auth token and let us assume Create User API accepts auth token as part of header. Let’s automate the same.

Login API

To start with let us understand the Login API.

curl -X POST \
  https://reqres.in/api/login \
  -H 'content-type: application/json' \
  -d '{
    "email": "eve.holt@reqres.in",
    "password": "cityslicka"
}'

Request JSON:

{
    "email": "eve.holt@reqres.in",
    "password": "cityslicka"
}

Response JSON:

{
    "token": "QpwL5tke4Pnpja7X4"
}

Create a postman collection having the Login API

In postman, create a collection with the name “ReqRes“. Create a new request with the name “Login” as shown below

Export postman collection

Export the postman collection “ReqRes” which would generate a JSON file.

The postman collection JSON file would look like below:

{
	"variables": [],
	"info": {
		"name": "ReqRes",
		"_postman_id": "1259b5b2-c7e5-6899-d937-5ba036c0c02d",
		"description": "",
		"schema": "https://schema.getpostman.com/json/collection/v2.0.0/collection.json"
	},
	"item": [
		{
			"name": "Login",
			"request": {
				"url": "https://reqres.in/api/login",
				"method": "POST",
				"header": [
					{
						"key": "Content-Type",
						"value": "application/json",
						"description": ""
					}
				],
				"body": {
					"mode": "raw",
					"raw": "{\n    \"email\": \"eve.holt@reqres.in\",\n    \"password\": \"cityslicka\"\n}"
				},
				"description": ""
			},
			"response": []
		}
	]
}

Now let us get back to IntelliJ Idea and see how do we call this API

Specify baseUrl

Open src/test/resources/api/hosts.json and specify baseUrl as below.

{
  "baseUrl": "https://reqres.in/"
}

Specify hosts in config

Open config/default.properties file & add the api.hosts property as below

# Api Config
api.hosts: hosts

Generate a model or POJO to represent Request and Response

As we understood from postman, Login API has a Request body and Response body. Let us generate model/POJO classes for both.

From postman, copy the request JSON of Login API to the clipboard.

Right-click on the api/user/login folder, choose New → Generate POJO from JSON



  1. Paste the JSON response from clipboard.
  2. Choose Lombok.
  3. Enter Root object name as LoginRequest.
  4. Click Generate button.


This would generate POJO class representing the JSON.


Note: Please replace the @Data annotation of Lombok with @Getter in all the generated classes.

LoginRequest.java

package ekam.example.api.login;
import lombok.Getter;

@Getter
public class LoginRequest{
	private String password;
	private String email;
}

In the same way, please generate LoginResponse POJO representing the response JSON.

LoginResponse.java

package ekam.example.api.login;
import lombok.Getter;

@Getter
public class LoginResponse{
	private String token;
}

Generate Retrofit Service & Client

Right-click on api/user/login New → Ekam Component → Retrofit Client. Enter name as Login


This would generate LoginClient class as below

package ekam.example.api.login;

import com.google.inject.Inject;
import com.google.inject.name.Named;
import com.testvagrant.ekam.api.retrofit.RetrofitBaseClient;
import com.testvagrant.ekam.reports.annotations.APIStep;
import retrofit2.Call;
import retrofit2.http.*;

public class LoginClient extends RetrofitBaseClient {

    private interface LoginService {
    }

    private final LoginService service;

    @Inject
    public LoginClient(@Named("baseUrl") String baseUrl) {
        super(baseUrl);
        service = httpClient.getService(LoginService.class);
    }
}

Generate Login Service method

Copy the postman collection JSON to the clipboard

Place the cursor within the interface body. Press Control + Enter (or Code → Generate… menu option) to invoke the below popup.
Choose the “Ekam Retrofit2 Generator” option.


This will open up a dialog “Postman collection“


Paste the postman collection JSON from the clipboard.


Click OK button. This will generate the below code.

@Headers({"Content-Type: application/json"})
@POST("/api/login")
Call<LoginResponse> login(@Body LoginRequest request);

The complete file would look like below.

package ekam.example.api.login;

import com.google.inject.Inject;
import com.google.inject.name.Named;
import com.testvagrant.ekam.api.retrofit.RetrofitBaseClient;
import retrofit2.Call;
import retrofit2.http.Body;
import retrofit2.http.Headers;
import retrofit2.http.POST;

public class LoginClient extends RetrofitBaseClient {

    private interface LoginService {

        @Headers({"Content-Type: application/json"})
        @POST("/api/login")
        Call<LoginResponse> login(@Body LoginRequest request);
    }

    private final LoginService service;

    @Inject
    public LoginClient(@Named("baseUrl") String baseUrl) {
        super(baseUrl);
        service = httpClient.getService(LoginService.class);
    }
}

Generate a method to invoke Login API

Let us generate a method that would invoke CreateUser API. To do this, Ekam provides a live template. Press Control+Enter (Code → Generate…) and choose API Step


Complete the template to generate code as below.

    @APIStep(keyword = "When", description = "I invoke Login API")
    public LoginResponse login(LoginRequest request) {
        Call<LoginResponse> call = service.login(request);
        return httpClient.execute(call);
    }

The LoginClient class would like as below:

package ekam.example.api.login;

import com.google.inject.Inject;
import com.google.inject.name.Named;
import com.testvagrant.ekam.api.retrofit.RetrofitBaseClient;
import com.testvagrant.ekam.reports.annotations.APIStep;
import retrofit2.Call;
import retrofit2.http.Body;
import retrofit2.http.Headers;
import retrofit2.http.POST;

public class LoginClient extends RetrofitBaseClient {

    private interface LoginService {

        @Headers({"Content-Type: application/json"})
        @POST("/api/login")
        Call<LoginResponse> login(@Body LoginRequest request);
    }

    private final LoginService service;

    @Inject
    public LoginClient(@Named("baseUrl") String baseUrl) {
        super(baseUrl);
        service = httpClient.getService(LoginService.class);
    }

    @APIStep(keyword = "When", description = "I invoke Login API")
    public LoginResponse login(LoginRequest request) {
        Call<LoginResponse> call = service.login(request);
        return httpClient.execute(call);
    }

}


Making CreateUser API accept authorization header

Add a dynamic header to the createUser service method

@Headers({"Content-Type: application/json"})
@POST("/api/users")
Call<CreateUserResponse> createUser(
        @Body CreateUserRequest request,
        @Header("authorization") String token);


Refactor createUser to include the token as parameter

@APIStep(keyword = "When", description = "I invoke createUser API")
public CreateUserResponse createUser(CreateUserRequest request, String token) {
    Call<CreateUserResponse> call = service.createUser(request, token);
    return httpClient.execute(call);
}

Create a Test which does Login and calls CreateUser API

Let us create a test which calls Login API to get the authorization token, then calls createUser API to create a user.

Here is the test

@Test(groups = "SmokeTest")
    public void shouldCreateUser() {

        LoginRequest loginRequest =  LoginRequest.builder()
                .email("eve.holt@reqres.in")
                .password("cityslicka")
                .build();

        String token = Client(LoginClient.class)
                            .login(loginRequest)
                            .getToken();

        CreateUserRequest createUserRequest = CreateUserRequest.builder()
                    .name("Bob")
                    .job("Builder")
                    .build();

        CreateUserResponse response = Client(UserClient.class)
                .createUser(createUserRequest, token);

        assertEquals(response.getName(), "Bob");

    }