HttpServletResponse: Keep, Save or Persist the response for later use...? - servlets

I am using Spring to create my webapp. I have a scenario like:
An ExternalService sends a GET request to my Controller that has a mapping /DoOperation with some user info as param. I get the param check the user if he is logged into my system or not if NOT i send him to OpenId verification with returnUrl, which is in same webapp say /Authenticated.
The ExternalService does not provide a returnUrl (Not related to OpenId returnUrl) and forces to respond the same request it made at /DoOperation.
Now, How could I keep the very HttpServletResponse (if there is a way, apparently there is not) so that I can write a response once I have gone somewhere else e.g. at OpenID page to verify user and then /Authenticate in this case... so that ExternalService could read it.
Could Servlet Filter help here?

Related

Create session with BASIC authentication

I want to write a servlet with which I can create a new session.
The servlet requires the user to authenticate with BASIC authentication and returns the standard session cookie (using HttpServletRequest#getSession(true)). However, if the client uses the received session cookie in his next request instead of BASIC authentication it is not authenticated. The server recognizes the session but it doesn't contain the user information.
I'm using Tomcat and after a bit of debugging the reason is also obvious: the user information (Principal) is added to session upon authentication. However when the first BASIC authentication is taking place no session exists yet as this will be created by the servlet. Does anyone have idea how to solve this problem?
After one night of sleep [1] I believe I have come up with a working solution myself. The following snippet (using JAX-RS, but it shouldn't be too difficult to translate it to plain servlet code) does the trick if the calling client will follow redirects:
public Response getSessionCookie() {
boolean sessionExists = m_servletRequest.getSession(false) != null;
if (sessionExists) {
return Response.noContent().build();
} else {
HttpSession session = m_servletRequest.getSession();
return Response.status(Status.TEMPORARY_REDIRECT)
.header("Location",
m_uriInfo.getAbsolutePathBuilder().matrixParam("jsessionid", session.getId()).build())
.build();
}
}
The first request will create a session and redirect the client to the same address but with the session ID in the URL (which is important). The client will follow the request and send the same BASIC authentication data again but now it will be registered in the existing session. The second invocation of the method above will simply return an empty response with the session cookie that can now be used for subsequent requests.
Note that the session cookie is different for me in the second response but looking at Tomcat code this seems to be deliberate (successful authentication will always create a new session).
[1] Sleep is highly underestimated!

SpringSession SecurityContext Auth token not persisting

I'm working on implementing SpringSession on an application with SpringSecurity using xml configuration. I followed this guide and the application is working 95%, confirmed that it is hitting the redis backend: http://docs.spring.io/spring-session/docs/current/reference/html5/guides/security.html
The application stores some information in a custom authentication token that extends UsernamePasswordAuthenticationToken. After implementing spring session, it seems like the data stored in the token is going to the wrong place or not persisting. The flow is like this:
Request is made and mapped to the Controller
The Controller gets the AuthorenticationToken in a fashion like this SecurityContextHolder.getContext().getAuthentication()
This token is the custom token that extends UsernamePasswordAuthenticationToken and a custom field is set like token.setFoo("bar")
The controller is finished and returns a ModelAndView with a redirect command like this redirect:/nextController
In the logs I see after the controller is finished, Chain processed normally and SecurityContextHolder now cleared and later, Obtained a valid SecurityContext from SPRING_SECURITY_CONTEXT
At this point, the field that I set in the auth token inside the SecurityContext, token.setFoo("bar"), is null.
If I disable the SpringSession configuration I can see that application uses a cookie called JSESSIONID instead of a cookie called SESSION and that the authentication token is populated and persists correctly.
Any help on this very troublesome bug would be greatly appreciated, thanks!

How does http security hasRole() method work

I have developed a RESTful API in Spring which retrieves user info from a database (MongoDB) and returns that data to a client that consumes this REST API. But before the data is retrieved the REST API checks to see if the user is an admin or not. Only the admin can perform GET operations to retrieve user info
So in my securityconfig.java class I have this:
http.authorizeRequests()
.antMatchers("/users/get/**", "/users/get/**").hasRole("ADMIN");
http.httpBasic();
Now, the users all have their roles and everything is working as expected in the sense that when I call curl adminusername:adminpassword#localhost:8080/users/get/AllUsers
I am able to retrieve all the users because the user with the username of adminusername is an admin and he has permission. But if I replace adminusername with a non-admin username, I get an access denied error.
My question is, is the adminusername:adminpassword part before the #localhost:8080.... the header of the HTTP request?
The reason I ask is because I need to create a client that is able to log in, have his credentials (username and password) verified, and have the username and password used as the session id, so that any time the client makes HTTP request calls after being logged in, the username and password is appended to the header and is processed by the REST API.
The hasRole() of the
http.authorizeRequests()
.antMatchers("/users/get/**", "/users/get/**").hasRole("ADMIN");
in the security config is dependent on the username:password before the #localhost:8080.... is this the same thing as #RequestHeader of the spring rest API?
First of all, Http Basic is a way, to send user credentials through header -
var header = {'Authorization': 'Basic '+btoa(username+':'+password)} //javascript
Second thing are authorities for a user. You in your system have to create user, and add them priviliges, for example:
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("mati").password("qwerty").roles("ADMIN", "USER").and()
.withUser("mati2").password("qwerty").roles("USER");
}
These users became later objects from class Principal which has their granted Authorities (like "ROLE_USER" or "ROLE_ADMIN").
When you are calling for example
curl adminusername:adminpassword#localhost:8080/users/get/AllUsers
Spring Security will check for proper Principal (with given username and will check if password matches), load it to the SecurityContext and will check if Principal has authority "ROLE_ADMIN" (by hasRole("ADMIN")). I must add that this was tricky, and I don't remember exactly, if you it washasRole("ADMIN") or hasRole("ROLE_ADMIN").
I hope this will answer your question(s).

Cache database results in WebAPI authentication

I am creating a RESTful web service using ASP.NET WebApi. I am requiring that all incoming requests go over SSL because I will be using Basic HTTP Authentication. The client is responsible for including the credentials in the request header and the web service will authenticate the client on each request.
The actual authentication requires making a database call. Is there a way to cache the database results (the username and password) so that I don't have to make a database call for every incoming request that occurs in a short period of time?
So when a request comes in the web service will look for the username/password combo in the cache. If it is found it will process the request. If it isn't found, it will make the database call to authenticate and then add the username/password to the cache.
The easiest cache that I can think of to use would be using System.Web.Caching. Below is an extremely simplified version of adding a value to the current cache and then retrieving it for processing. I would not recommend using this code as is.
// GET api/values/5
[HttpGet]
public string GetValue(int id)
{
HttpContext.Current.Cache.Insert("2", "test1");
var value = Convert.ToString(HttpContext.Current.Cache.Get(id.ToString()));
return !string.IsNullOrEmpty(value) ? value : "nothing found";
}

Is it possible to forward the current user's FormsAuthentication Identity to another Controller action?

I'd like to use ASP.NET MVC's views as mail template engine. For that, I am calling one controller action from another controller action using a System.ComponentModel.Component.WebClient, parse the returned web page and send it via e-mail.
In this scenario, is it possible to forward the current user's login credentials (I am using FormsAuthentication) to the controller action requested by the WebClient? User passwords are encrypted, so I can't just create a new NetworkCredentials instance with his user name and password.
Yes, you can just copy the .ASPXAUTH cookie from your current Request object to the WebClient
EDIT: I haven't actually tried this myself, so maybe the .ASPXAUTH cookie is removed from the Request object for security reasons.
But since you have access to the machine key, you can create your own cookies on the fly. Here's the code that should do it (I can't find the project where I actually did that)
var ticket = new FormsAuthenticationTicket(User.Identity.Name, true, 5);
string aspxAuthCookieValue = FormsAuthentication.Encrypt(ticket);
This code creates a forms authentication cookie for your current user name and with an expiration time of 5 minutes.
Instead of performing a http request, aren't you looking for something like "rendering a view to a string"

Resources