HtmlUnit stays logged in after removing "JSESSIONID" cookie - java

I'm setting up remember-me authentication for my Spring Boot application an want to write a HtmlUnit test.
The problem is that deleting the "JSESSIONID" cookie does not seem to log out the webClient.
The test using remember-me authentication works fine but the test in which there should be no authentication and thus a redirect to the login page does not work (the last assertion fails).
#Test
void NoRememberMeLogin() throws IOException {
HtmlPage loginPage = webClient.getPage(baseURL + "login");
HtmlForm loginForm = loginPage.getFormByName("loginForm");
HtmlInput username = loginForm.getInputByName("username");
HtmlInput password = loginForm.getInputByName("password");
HtmlCheckBoxInput rememberMe = loginForm.getInputByName("remember-me");
username.setValueAttribute("user");
password.setValueAttribute("password");
rememberMe.setChecked(false);
// login
HtmlElement submit = loginForm.getOneHtmlElementByAttribute("input", "type", "submit");
HtmlPage afterLogin = submit.click();
// login successful?
assertThat(afterLogin.getUrl().toString(), is(baseURL + "securedPage"));
// checkl cookies
Cookie sessionCookie = webClient.getCookieManager().getCookie("JSESSIONID");
Cookie rememberMeCookie = webClient.getCookieManager().getCookie("remember-me");
assertNotNull(sessionCookie);
assertNull(rememberMeCookie);
// delete the Session cookie
webClient.getCookieManager().removeCookie(sessionCookie);
sessionCookie = webClient.getCookieManager().getCookie("JSESSIONID");
// session cookie really is deleted
assertNull(sessionCookie);
// refresh tha page (works in browser)
afterLogin.refresh();
// check that we were redirected to login page (not working)
assertThat(afterLogin.getUrl().toString(), is(baseURL + "login"));
}
Hope you can help me, thanks!

Related

playwright how to get a response from a page after navigating and logging in

I looking at playwright and I want to return a response I have looked at the examples and there is the following snippit
Response resp = page.navigate(getPageRequest.getUrl(), new Page.NavigateOptions().setTimeout(60000));
But what I want to do is loggin on the first page which is a loggon page which will return the main page , and that page, I want to return the response, so I have the following code
// This page is the loggin page
page.navigate(logginURL, new Page.NavigateOptions().setTimeout(60000));
String title = page.title();
System.out.println("title : "+title);
page.fill("input[name='username']", "MyName");
page.fill("input[name='password']", "MyPassword");
page.click("text=Login");
Thread.sleep(300);
// This is the main page after a successful login
title = page.title();
Is there a way to navigate to a page login and return the successful have logged in page
I worked out a way, he feels hacky but I dont know playwright enough to know if there is a better way. Navigate to the login page, login, returns new page navigate to that page url.
page.navigate(getPageRequest.getUrl(), new Page.NavigateOptions().setTimeout(60000));
String title = page.title();
System.out.println("title : "+title);
page.fill("input[name='username']", "MyName");
page.fill("input[name='password']", "MyPassword");
page.click("text=Login");
Thread.sleep(300);
System.out.println("title : "+page.title());
System.out.println("URL : "+page.url());
resp = page.navigate(page.url(), new Page.NavigateOptions().setTimeout(60000));

How to authenticate and redirect to external application for SSO?

I am trying to implement a simple SSO feature in my spring-based web application. Scenario:
I have a main application Application1 and a secondary Application2. Both have their own login mechanisms (using spring-security login-forms) in place.
I want to implement SSO in Application1, so that when user logs-in to Application1, he can also seamlessly access Application2 via a link without having to fill up login details for Application2.
Here's what I have tried:
I created an API in Application2 which takes email as input, validates it, creates user session, and returns a url string.
#RequestMapping(path = "/sso/login", consumes = "application/json", method = RequestMethod.POST)
public String login(#RequestBody SSOparams params, HttpServletRequest req, ModelMap model) {
// 1. validates email from params
// 2. creates Authentication object:
UsernamePasswordAuthenticationToken authReq = new UsernamePasswordAuthenticationToken(username, password);
Authentication auth = authManager.authenticate(authReq);
SecurityContext sc = SecurityContextHolder.getContext();
sc.setAuthentication(auth);
HttpSession session = req.getSession(true);
session.setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, sc);
// 3. returns a url string:
return "/user/dashboard";
}
User logs-in to Application1.
Inside Application1's home-page, when user clicks on a Application2's link, a call is made to Application1's controller method.
Application1's controller method calls Application2's login API with an email parameter, and finally redirects to the url returned from the API.
Application1's controller method:
#RequestMapping(value = "/callapplication2", method = RequestMethod.POST)
public String callapplication2(ModelMap model,HttpSession session) {
String output = "";
String redirectionUrl = "";
try {
// 1. calling application2's login API
URL url = new URL("http://localhost:8080/application2/api/sso/login");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setDoOutput(true);
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "application/json");
String input = "{\"uniqueemail\":\"abc#gmail.com\"}";
OutputStream os = conn.getOutputStream();
os.write(input.getBytes());
os.flush();
BufferedReader br = new BufferedReader(new InputStreamReader((conn.getInputStream())));
while ((output = br.readLine()) != null) {
redirectionUrl = redirectionUrl + output;
}
conn.disconnect();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
// 2. returns a url
return "redirect:http://localhost:8080/application2" + redirectionUrl ;
}
All of the above is working fine. But when I login to Application1 and click on application2's link, I expect application should redirect to
http://localhost:8080/application2/user/dashboard
without having to fill up credentials.
But instead, Application2's login page opens. I can see in the network console of Chrome that /user/dashboard is being called, but since the page is secured, I am redirected to application2's login page.
Does this mean that the authentication I created using API is not being used. What am I missing?
Best approach is to set filter in web.xml and put it in top of the list.
Whenever your application will get any request it will first go to the filter and there you will check that session is present or not if its null then simply redirect to your sso login page else respective landing page.
Now in your case,
Solution i can see
1) Put filter into app2 web.xml
2) Now when you redirect from app1 to app2 (Pass one parameter anything like username, email whatever)
3) Store it into the session.
4) Whenever any request will come to app2 you will first verify session from filter, If username found that means user not need to login again else redirect to sso login page.
Thats standars steps (I belive)
5) Having a peek into your implementation.Specifically you have to add one more step into app filter. When you are redirecting from app1 for te first time with http://localhost:8080/application2/user/dashboard ( You will pass one parameter along with this url as explained above).
This let you to check 2 condition into your filter. Either request should have valid parameter or username should be into session. If any condition stated true you can let redirect request to further else you have to redirect to login page.
Hope this will help to resolve your issue.

Login to website with HtmlUnit

how can I login to http://minecraft-server-list.com/login/login.php using HtmlUnit? The login form doesn't seem to have an ID so I can't get it by using getFormByName.
You can get the form by using xpath HtmlForm form = page.getFirstByXPath("//form[#action='login.php']");
And then get username and password fields E.g.
final HtmlTextInput textField = form.getInputByName("Username");
final HtmlPasswordInput pwd = form.getInputByName("password");
After then set the credentials
textField.setValueAttribute("foo");
pwd.setValueAttribute("bar");
Get the login button and perform click
HtmlPage page = (HtmlPage) form.getInputByValue("Login").click();

Why are cookies not being destroyed in Java MVC website

I am attempting to prevent users viewing a webpage if they are not logged in.
Currently the user is able to "login" which sets a cookie for 24 hours. I achieve this using AJAX which forwards to the admin page after creating the "loggedIn" cookie.
When a user navigates to MainController?page=logout it should delete the cookie and forward the user to the login page, which it appears to do.
But when navigating to MainController?page=admin the user should be forwarded to the login page if no cookies exist, but instead the admin page loads. I'm assuming that I'm not deleting the cookies properly?
Here is the AJAX call to check user credentials when logging in:
$("#loginForm").submit(function(e){
e.preventDefault(); //STOP default action
var postData = $("#loginForm").serializeArray();
var username = $("#username").val();
var password = $("#password").val();
var botCatcher = $(".botCatcher").val();
if(username.length > 3 && password.length > 3 && botCatcher.length == 0){
$.ajax(
{
type: "POST",
url : "MainController",
data : postData,
success: function(data)
{
if(data == "success"){
window.location.href = "MainController?page=admin";
}else if(data == "nope"){
$(".test").html("<p>Login details incorrect. Please try again.</p>");
}
},
error: function(jqXHR, textStatus, errorThrown)
{
$(".test").html("<p>ss"+errorThrown+textStatus+jqXHR+"</p>");
}
});
}else{
$(".test").html("<p>Unable to login: ensure details are correct.</p>");
}
});
This is how I'm setting the cookie in the doPost method of the MainController servlet and outputing "success" to allow JQuery to forward to the admin webpage.
Cookie loggedIn = new Cookie("loggedIn", "true");
loggedIn.setMaxAge(60 * 60 * 24);
response.addCookie(loggedIn);
out.print("success");
This is how I control the navigation, as you can see the logout case should delete the cookie which means that the admin case should forward the user to the login page because the cookie object is null? Instead it loads the admin page. - This is actuated using a link on the admin page pointing to MainController?page=logout which is supposed to delete the cookie and forward to the login page, which it appears to do. But I can still navigate back to the admin page without needing to login.
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String page = getPageName(request.getParameter("page"));
Cookie cookies[] = request.getCookies();
switch (page) {
case "admin":
if (cookies == null) {
page = "login";
return;
}
break;
case "logout":
for (Cookie cookie : cookies) {
cookie.setMaxAge(0);
cookie.setPath("/");
response.addCookie(cookie);
}
page = "login";
break;
}
RequestDispatcher rd = getServletContext().getRequestDispatcher(views + getPageFilename(page));
rd.forward(request, response);
}
Why is it loading the admin page instead of forwarding to the login page ( and thus preventing users not logged in to view this page ). Am I not deleting the cookies correctly?

How do I pass cookies from an HttpURLConnection to WebDriver in Java?

I'm testing a website that requires some basic authentication. Upon successful login a session key is sent back in cookies. I've written some code to get this cookie via the web service. It ends like this:
public List<HttpCookie> getCookies(String Domain, String user, String pass) {
// Actual services to log in here
List<HttpCookie> cookies = cookieStore.getCookies();
for (HttpCookie cookie : cookies) {
System.out.println(cookie);
}
return cookies;
}
When I debug I can see my sessionKey in there with a valid value. It's got the same domain that I passed above, and a blank path like /.
Here's how I've tried adding the cookie to my WebDriver instance:
List<HttpCookie> cookies = getCookies(DOMAIN, USERNAME, PASSWORD);
for (HttpCookie cookie : cookies) {
String cookieName = cookie.getName();
String cookieValue = cookie.getValue();
String cookieDomain = cookie.getDomain();
String cookiePath = cookie.getPath();
Date cookieExpiry = new Date();
Cookie selCookie = new Cookie(cookieName, cookieValue, cookieDomain, cookiePath, cookieExpiry);
driver.manage().addCookie(selCookie);
}
driver.get(ROOT_URL+"/some/internal/page");
When I try to add selCookie I get the following error message:
org.openqa.selenium.InvalidCookieDomainException: You may only set cookies for the current domain
I'm copying the domain directly from the cookie I received. I even tried passing it as a bare String instead of relying on the getDomain() method, but it returned the same error. Any idea what could be causing it to complain?
To add a cookie to a WebDriver instance, the domain in the cookie has to match the current domain of the WebDriver instance. I was trying to add the cookie before driver had visited anything, so driver's current domain was blank. I fixed it by just sending driver to ROOT_URL before I retrieve the session cookie and add it to driver:
//Added this:
driver.get(ROOT_URL);
List<HttpCookie> cookies = getCookies(DOMAIN, USERNAME, PASSWORD);
for (HttpCookie cookie : cookies) {
String cookieName = cookie.getName();
String cookieValue = cookie.getValue();
String cookieDomain = cookie.getDomain();
String cookiePath = cookie.getPath();
Date cookieExpiry = new Date();
Cookie selCookie = new Cookie(cookieName, cookieValue, cookieDomain, cookiePath, cookieExpiry);
driver.manage().addCookie(selCookie);
}
driver.get(ROOT_URL+"/some/internal/page");

Categories