Link to part 1. Please read it as I will build upon it here.

The series was originally ment to be just the code presentation. How to write performance test,using gatling, for your app so it would include your authentication/authorization infrastructure. But in the process i realize how this is also a good oportunity to explain various scenarios of authentication flow. In the previous part I talked about the ‘Authorization code flow’ in keycloak called ‘Standard Flow’. In this peace I will describe the ‘Implicid flow’. Just to recap a little bit in standart flow after successful authentication we recive code that can be exchanged for access_token by POST-ing a message to apoppriate endpoint. In ‘Implicit Flow’ that step is omited and in the redirect url after you authenticate one of the parameters is the access token.

Because of that the implicit flow is considered less secure. But there might be cases when it is beneficial to use it. For example you have a static resource that you want to protect (page, document etc…) there are some performance benefits event if you do have a back chanel, as you don’t make one round trip to the server.

There is one last think what to do when your token expires. In keycloak there is a separate timeout for tokens issued during the implicit flow. There is no refresh token to use. In these cases we can utilize what is called: ‘Silent Refresh’ it is a concept that described quite well in this article. Basically if you are trying to access any resource after your token expires but before your sso session expires you will get ‘ 401 Unauthorized’. You can still recover by making a separate request in a iframe to the keycloak with the prompt parameter set to null. In response you should get new token. Full disclosure I didn’t test that scenario so it is all theoretical. Sorry.

Now for the example. Not much has changed. But still i created a separate folder in the repo. Link below. The full test looks like this:

val scn = scenario("experiment")
.exec(http("get_login_page")
.get(authUri)
.queryParam("client_id", client_id)
.queryParam("redirect_uri", uri3)
.queryParam("state",UUID.randomUUID().toString())
.queryParam("nonce",UUID.randomUUID().toString())
.queryParam("response_mode", "fragment")
.queryParam("response_type", "id_token token")
.queryParam("scope", "openid")
.headers(headers_3)
.check(status.is(200))
.check(css("#kc-form-login")
.ofType[Node]
.transform(variabe => { variabe.getAttribute("action") })
.saveAs("loginurl"))
)

first we have to get the login page, the only difference here is that you have to put “id_token token” in the response. id_token is optional if you don’y need user data in the response, and token is also optional if you just want to be authenticated for the static resource and no communication with backend app is necessary. It all depend on the scenario. I requested both.

.exec(http("login")
.post("${loginurl}")
.headers(headers_3)
.formParam("username", "user")
.formParam("password", "user")
.check(status.is(302))
.check(header("Location")
.transform( t=>{
t.substring(t.indexOf("access_token=") + 13 , t.indexOf("&token_type"))
})
.saveAs("acces_token"))
.check(header("Location").saveAs("nextPage"))
)

Next we give our credenitals and extracting acces_token from the response.

.exec(http("fetch_error_codes")
.get(backEndService)
.header("Authorization","bearer ${acces_token}")
.headers(json_headers)
.check(status.is(200))
)

and then we use that token to call the backend server. That is it. All you have to do is to esablish your own test secenatios and present your gatling results.

If you are intersted in running the bellow demo check the part 1. As nothing changed.

--

--

piotr szybicki
12 developer labors

Piotr Szybicki’s, Programmer, Java Developer, ML Entusiast