A practical way to automate testing Oauth 2.0 Service

Angela T.T.
5 min readSep 5, 2018

--

Nowadays Oauth 2.0 has become the most commonly used authentication framework for Restful API services. Among the different grant types, The Authorization Code Grant Type is probably the most common of the OAuth 2.0 grant types that you’ll encounter. It is used by both web apps and native apps to get an access token after a user authorizes an app.

How to automate testing this kind of service, especially for CI/CD?

Here we’re going to introduce how Restbird solve this particular case using its global environment and task.

Case Study: Box API Testing automation

Take Box API for example, Box uses the standard OAuth 2 three-legged authentication process, which proceeds as follows:

  • The application asks an authentication service to present a login request to a user.
  • After a successful login, the authentication service returns an authorization code to the application.
  • The application exchanges the authorization code for an access token.

Add Authorize API to get authorization code

  • Create rest API to get authorization code

Method: GET

Url: https://account.box.com/api/oauth2/authorize

Url parameter

  • response _ type: code
  • client _ id: {{client _ id}}
  • redirect _ uri: https://localhost
  • state: BOX

Here is how the request looks in Restbird

  • Click “Run test”, and then Copy the Url into web browser
  • Enter user credentiaL and click “Authorize”
  • Click “Grant access to Box”
  • The browser will then redirect to “redirect_ur” as the request specified, in this case, it’s https://localhost, with the authorization code as the “code” parameter

Add the Get access token API to get access token

  • Create rest API to get access token

Method: POST
Url: https://api.box.com/oauth2/token

Req Body (application/x-www-form-urlencoded):

  • grant _ type: authorization _ code
  • client _ id: {{client _ id}}
  • rclient _ secret: {{client _ secret}}
  • code: Copy Code from last API

Here is how the request looks in Restbird

Creat Response Check Scripts to save access token and referesh token to global environment

Here golang is used as sample language, access taken and referesh token will be extracted from response json data and saved into global environment.

Note: [callapi]() is Restbird defined golang lib which has variaty of APIs for core scripting functionality.

package api
import "callapi"
import "net/http"
import "io/ioutil"
import "encoding/json"
import "fmt"

type MyDATA struct {
Access_token string `json:"access_token,omitempty"`
Refresh_token string `json:"refresh_token,omitempty"`
}

func (c CallBack) ResponseValidate(resp *http.Response, ctx *callapi.RestBirdCtx) bool {
var body []byte
var err error
var data MyDATA = MyDATA{}

if body, err = ioutil.ReadAll(resp.Body); err != nil {
fmt.Println("read body failed.")
return true
}
if err = json.Unmarshal(body, &data); err != nil {
fmt.Println("conver body to json failed")
return true
}

callapi.SetGlobalString("box_access_token", data.Access_token)
callapi.SetGlobalString("box_refresh_token", data.Refresh_token)

_, box_access_token := callapi.GetGlobalString("box_access_token")
_, box_refresh_token := callapi.GetGlobalString("box_refresh_token")

fmt.Println("box_access_token: " + box_access_token)
fmt.Println("box_refresh_token: " + box_refresh_token)

return true
}
  • After clicking “run test”, you can see refresh_token in response body.

click ”Globals” to verify that the variables have been saved into global enviroment.

Add the Refresh access token API to refresh access token

  • Create rest API to refresh access token

Method: POST

Url: https://api.box.com/oauth2/token

Req Body (application/x-www-form-urlencoded):

  • grant _ type: refresh _ token
  • client _ id: {{client _ id}}
  • rclient _ secret: {{client _ secret}}
  • code: {{box _ refresh _ token}}

Note: {{}} is the syntax for using both local and global environment variables.

Here is how the request looks in Restbird

  • Creat Response Check Scripts to save access token and referesh token to global environment

Similar as the get access token API, after referesh token API been called, the two gloabl variables box_access_token and box_referesh_token need to be updated accordingly.

package api
import "callapi"
import "net/http"
import "io/ioutil"
import "encoding/json"
import "fmt"
type MyDATA struct {
Access_token string `json:"access_token,omitempty"`
Refresh_token string `json:"refresh_token,omitempty"`
}
func (c CallBack) ResponseValidate(resp *http.Response, ctx *callapi.RestBirdCtx) bool {
var body []byte
var err error
var data MyDATA = MyDATA{}

if body, err = ioutil.ReadAll(resp.Body); err != nil {
fmt.Println("read body failed.")
return true
}
if err = json.Unmarshal(body, &data); err != nil {
fmt.Println("conver body to json failed")
return true
}

callapi.SetGlobalString("box_access_token", data.Access_token)
callapi.SetGlobalString("box_refresh_token", data.Refresh_token)

_, box_access_token := callapi.GetGlobalString("box_access_token")
_, box_refresh_token := callapi.GetGlobalString("box_refresh_token")

fmt.Println("box_access_token: " + box_access_token)
fmt.Println("box_refresh_token: " + box_refresh_token)

return true
}

Create Task to automate token retrival

Up to now, we have already done creating all the pieces, now there need a glue to hold everything together. Here comes task to complete the job, task is pure script that can do everything. In this example, we use task to implement a timer, inside the timer function, we call the refresh token API to periodically update the two gloabl variables box_access_token and box_referesh_token, so that we can have valid token as long as the Restbird server is up.

package main
import "callapi"
import "fmt"
import "time"
import api2 "restbird/Box/Token/api2"func main() {
for {
select {
case <-time.Tick(time.Millisecond * 60000 * 60 ):
mytime := time.Now()
callapi.SetGlobalVars("starttime", mytime)
callapi.DoHttpRequestWithEnv("Box/Token", "api2", api2.CallBack{}, "Box")

callapi.GetGlobalVars("starttime", &mytime)
fmt.Println("starttime: ", mytime, "current Time:", time.Now())

_, box_access_token:= callapi.GetGlobalString("box_access_token")
fmt.Println("++box_access_token: " + box_access_token, "\n")
_, box_refresh_token:= callapi.GetGlobalString("box_refresh_token")
fmt.Println("--box_refresh_token: " + box_refresh_token, "\n\n")
}
}
}

Note:

  • import api2 “restbird/Box/Token/api2” , the syntax of reference a Rest API is restbird/[path to rest case]/[rest case]/api[index], where index starts from 0.
  • callapi.DoHttpRequestWithEnv(“Box/Token”, “api2”, api2.CallBack{}, “Box”), if local environment has been used in the API, DoHttpRequestWithEnv need to be called with the name of the environment passed as the last argument.

In this article, we have introduced a way to automatically retrieve the access token for testing oauth 2.0 service, where user only need to login once to get the autorization code, after that, the Restbird test server will keep refereshing the token in given time interval to maintain a valid token.

Next: A practical way to automate testing Oauth 2.0 Service — Part 2, DevOps Integration

--

--