Automated web login
Many a times, especially during test automation you will find the need to automate the web login step.
In testing context, all tests that do not test the login-form should ideally not have to go through the login via webform sequence, as this causes substantial delays in every tests. Cumulatively, this results in a lot of time wasted for every test
Now there are multiple ways to do this, so listing a few
Once you know the POST call that is made on hitting the submit button in a web form, you can capture it as a curl request.
Once you have this fetch, you can try it out in the Console in your browser as
It could typically look like
await fetch("/api/authentication/token", {
"credentials": "include",
"headers": {
"Content-Type": "application/json",
"X-Requested-With": "XMLHttpRequest",
},
"referrer": "https://searchui.app/login?returnUrl=dec",
"body": "{"username":"UID","password":"pass"}",
"method": "POST"
});
Now you may need other things like set the token if your authentication is based off tokens
Setting this in the browser is at times all that is needed.
regarding the Token Expiry and server validations of the token and tokenExpiry
Note that the technique used to set the token and tokenExpiry will differ based on what the server expects it to be. In the case above the server is expecting a token expiry to be greater than the current epoch time instant.
- Using fetch in JavaScript calls within your browser
You can do this via JavaScript fetch, and try it in your console and check it works.
await fetch("/api/authentication/token", {
...
})
.then(res => res.json())
.then(data => {
// Extract token from the response
const token = data.token;
// Set token in session storage
localStorage.setItem('token', data.token);
localStorage.setItem('tokenExpiry', '1903163542236');
// redirect to home page after authentication is set
window.location.assign("https://homepageurl/");
});
Note that the window.location.assign() above does the redirect to the home page on the browser once the redirect is complete.
What if you want to do a chained request to something else once you’ve accomplished this that uses the token you fetched, for e.g. get a list of items with an api call, and that api call uses a Bearer token?
await fetch("/api/authentication/token", {
...
})
.then(res => res.json())
.then(data => {
const token = data.token;
localStorage.setItem('token', data.token);
localStorage.setItem('tokenExpiry', '1903163542236');
window.location.assign("https://homePageUrl/");
const auth_string = "Bearer " + token;
fetch("/api/filters", {
"credentials": "include",
"headers": {
"Content-Type": "application/json",
"X-Requested-With": "XMLHttpRequest",
"Authorization": auth_string,
},
"method": "GET"
});
});
And, how would you do this in the context of an automation framework, say Selenium (Java)
Execute the above fetch request via JavaScript executor
String fetchRequestString = "await fetch(...);"
((JavascriptExecutor) driver)..executeScript(fetchRequestString);
2. Calling the authentication API directly from java to fetch your token
You can shorten the time further and not rely on the browser executing the fetch and the delays associated with it by fetching the token without the browser. In this case the api is called using JSoup.
It’s easy to generate the request, and copy it from your browser POST in the the network tab as a Curl request, and use something like Convert curl commands to Java + jsoup to generate this easily.
String responseBody = Jsoup.connect("https://homePageUrl/api/authentication/token")
.header("Content-Type", "application/json")
.header("X-Requested-With", "XMLHttpRequest")
.requestBody("{\"username\":\"" + username + "\",\"password\":\"" + password + "\"}")
.method(Connection.Method.POST)
.ignoreContentType(true)
.execute()
.body();
String token = JSONObject(responseBody).get("token").toString();
Once you then have the token, set the token in your browser, either
via Java web-driver using local storage
LocalStorage local = ((WebStorage) driver).getLocalStorage();
local.setItem("tokenExpiry", String.valueOf(Instant.now().toEpochMilli() + 10000));
driver.navigate().to(getTestConfig().getSearchHost());
driver.navigate.to(homePageUrl);
Or via JavaScript and localStorage.setItem()
jsExecutor.executeScript("localStorage.setItem('token','" + token + "');");
jsExecutor.executeScript("localStorage.setItem('tokenExpiry', new Date().getTime() + 6000 * 1000);");
jsExecutor.executeScript("window.location.assign('" + homePageUrl + "');");
Note regarding the Token Expiry here
Note that the technique used to set tokenExpiry will differ based on what the server expects it to be. In the case above the server is expecting a token to be greater than the current epoch time instant. Hence it is set to a value higher than that.