How do I create a new HttpSession in a RESTful webapp? - java

I have a need to create a HttpSession (via cookie) whenever a client invokes a particular UI.
Assumptions:
Let's assuming that I'm not going to worry about any deep oAuth-like authentication dance. JESSIONSID cookie impersonation is not an issue for now.
The server is tomcat, thus a JSESSIONID cookie is sent down to the client if a new session is created.
Design issues:
I'm grappling with how to design the URI. What is actually the REST resource ? I already have /users and /users/{someuserid}. I wanted to use /auth/login but in one previous SO question, one cited article says that we should not have verbs in the url. I've noticed that even Google makes the same mistake by having https://www.google.com/accounts/OAuthGetRequestToken. So in your opinion, are /auth/login/johndoe (login) and /auth/logout/johndoe (logout) good options ?
UPDATE:
I've changed my design. I'm now thinking of using the URIs /session/johndoe (PUT for login, DELETE for logout). It should still be within the limits of the REST ethos ?

Aren't sessions irrelevant in REST Style Architecture?
http://www.prescod.net/rest/mistakes/

I am in the midst of creating a REST endpoint that recognizes sessions. I've standardized on:
POST /sessions => returns Location: http://server/api/sessions/1qazwsxcvdf
DELETE /sessions/1qazwsxcvdf => invalidates session
It is working well.

Related

Using Vert.x `AuthenticationHandler` from vertx-web, we hit the authentication provider for every call?

I'm using Vert.x for my web service, where a part of it required authorization. I've set an AuthenticationHandler (using the OAuth2 implementation from vertx-auth-oath2) to listen on the protected paths (lets say "/*") and it is correct called, sends a redirect to the authentication provider, which redirects back and then correctly to the real handler. This works fine.
But the next time we call the protected endpoint - it does the whole thing again. I see that in the abstract AuthenticationHandlerImpl class it checks if the context already has a user() and if so - will not run the actual auth handler, which is the behavior I need - but it obviously doesn't happen because every call is a new request with a new RoutingContext.
What is the "correct" way to retain the User object across requests, so that the auth handler will be happy?
I'm guessing it has something to do with session storage but I've never used that - up until now I was using a custom "API key" style solution, and I'm trying to do this "The Right Way(tm)" in this new project.
I'm using the latest Vert.x 4.3.5.
You will need CookieHandler and SessionHandler to store and handle session with user. This will work out of the box with provided vertx-auth-oath2.
Here is a simple example to get you started:
https://github.com/vert-x3/vertx-examples/blob/master/web-examples/src/main/java/io/vertx/example/web/auth/Server.java

SSO using spring-security-oauth2 : Authentication Code never read

Using :
spring-security 3.2.5
spring-security-oauth 2.0.7
I have a working oauth2 provider built with spring-security-oauth (oauth2).
I have my client configured in it to use authorization_code grant type.
The provider works perfectly :
Testing with curl, I can get an authorization code and exchange it for an access token.
So on the service provider part, all is fine.
Now I'm trying to implements the client application, also with spring-security-oauth.
I'm using xml configuration, strongly based on the example here, but using my own provider (mentionned above) instead of google.
When I make a call to a protected resource on my client, the OAuth2ClientAuthenticationProcessingFilter tries to obtain an access token, so it redirect to my service provider. That one force the user to log in, as expected, and then redirect him to the configured redirect_uri (the redirect uri is the one configured for my OAuth2ClientAuthenticationProcessingFilter : something like http://myClient/context/external/login).
The problem is : the client never read the authorization code in the request returned from the service provider. So the OAuth2ClientAuthenticationProcessingFilter restarts the flow, asking for an authorization code.
I've been able to make it work by modifying the OAuth2ClientAuthenticationProcessingFilter to read the request and set the authorization code in the AccessTokenRequest. Here is the snippet :
OAuth2AccessToken accessToken;
try {
String code = request.getParameter("code");
if(code != null) {
restTemplate.getOAuth2ClientContext().getAccessTokenRequest().setAuthorizationCode(code);
}
accessToken = restTemplate.getAccessToken();
...
Before trying this, I tried to make a "call hierarchy" on the method org.springframework.security.oauth2.client.token.AccessTokenRequest.setAuthorizationCode(), to find where in the code spring does call the method, but it returned nothing.
Is that a bug ?
I really would like not to have to replace the OAuth2ClientAuthenticationProcessingFilter with my own.
Does someone made it work ( in that version or another) ?
Update
It's the setAuthorizationCode() method that is never called (error in my initial question). But I digged a little more and I realized this is not the problem.
I can assert that the OAuth2ClientContextFilter is called before OAuth2ClientAuthenticationProcessingFilter (I checked that with a debugger).
What I found, but don't know if it is normal :
The default constructor of DefaultAccessTokenRequest is only called once : at the application startup. The other constructor (the one taking the parameter's map), is never called. Since I've seen in RestTemplateBeanDefinitionParser that the access token request is scoped 'request', I would expect the constructor taking the parameter's map to be called on each new http request to my client application.
In the RestTemplateBeanDefinitionParser :
BeanDefinitionBuilder request = BeanDefinitionBuilder.genericBeanDefinition(DefaultAccessTokenRequest.class);
request.setScope("request");
request.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
request.addConstructorArgValue("#{request.parameterMap}");
request.addPropertyValue("currentUri", "#{request.getAttribute('currentUri')}");
That can explain my problem with the authorization code never read from the request. The hack I mentionned in my initial question just pushed back the problem. Now I get csrf protection errors because the AccessTokenRequest always remembers some stateKey when I presume it does not need anymore once I get the access token.
Again, maybe I just misunderstand the hole think, so feel free to tell me :)
I did not post my configuration because it's pretty the same as that one here.
You need an OAuth2ClientContextFilter and it needs to fire before the authentication processing filter (it basically does that stuff you have in your custom filter). I can't tell from the code you posted if you have one and it isn't firing or you don't have one.
Sorry for all of you that spent precious time trying to help me. I was so focused debugging that I missed a configuration problem.
Do never configure Oauth2RestTemplate like this :
<beans:bean id="myRestTemplate" class="org.springframework.security.oauth2.client.OAuth2RestTemplate">
<beans:constructor-arg ref="myResourceId"/>
</beans:bean>
That explain why the DefaultAccessTokenRequest was not request scoped, hence it's default controller called instead of the one taking request's parameter map.
Don't do like me and use the xml namespace ! :
<oauth:rest-template id="myRestTemplate" resource="myResourceId"/>
Still wondering why I've done that :P

How to initialise a session in Play

Well, this is from a developer newly using Play. When it came to using session, I found its not at all like I have been doing in servlets or jsps.
I have tried reading documentation and found session in Play are stored in HTTP cookies rather. I have tried importing HTTP class of play.
My problem however is I am unable to initialise a new session to set values in it.
I have obviously tried using 'new' session as in Java and that obviosly didnt work out.
Session session = new session();
Also after looking somewhere I have used:
Session session = Http.Context.current().session();
which shows me error in identifying context and current
I have tried looking at sample codes and codes on net. each of them however is different and I don't get the basic way of using sessions in Play, so that after that I can use put and get to keep and retrieve.
I know the question seems too basic but believe me there is no exact answer available anywhere to what I need. So please help me regarding this.
Any answer, any piece of code, or any Link on this will be highly appreciated.
Forget everything about the sessions from the jsp and servlets world while working with the Play's session. Play doesn't store anything on the server side and by design it's completely stateless. The Play session is just a cookie attached to every http request and it's stored on the client side. Word 'session' may be misleading in your case.
Working with the session is pretty straight forward. All you need is inherited from play.mvc.Controller which you have to extend when creating your own controller. To put a value in it you simply call the session(String key, String value) method from within a controller. For example:
public class Application extends Controller {
public static Result login() {
session("key", "example value");
return ok("Welcome!");
}
}
If there is no session cookie stored on client side this method will create new one and attach it to the HTTP response. Otherwise it will modify the existing one.
To read stored value use:
String value = session("key");
You can also remove value from the session:
session().remove("key");
or completely destroy it:
session().clear();
These are helper methods to work with the particular cookie witch in Play's terminology is called session. Nothing stops you from creating another cookie with similar purpose. But it'll require more writing. These helper methods saves your time and in many cases are more than enough.
You can specify session cookie name in your application.conf by setting session.cookieName property.
In play 2.8 the Http.Context was deprecated. This means, among other things, that the method "session()" is no longer available in a controller.
This is the updated way of doing it:
public Result info(Http.Request request) {
//This is the equivalent to the old session()
request.session() ...
}
The Http.Request needs to be passed down through the route defined in routes. More information here.

Spring Access Control

I working on Spring MVC app. The app funcionality is accessible through ReST API which jsp containing ajax logic consume. I am using spring security with defined roles (USER, COMPANY, ADMIN). Methods use requestMapping with responseBody such as:
www.app.com/auth/{userId}/request/{requestId}
It, of course, support GET for obtaining resource and POST for its creating or updating.
The problem is that after succesful login with, for example, userId = 1 I want GET request with requestId = 99. But when I run WebDev client for Chrome, I can also access another resource with easy request in format
www.app.com/auth/5/request/{requestId}
So basically, I can access resources, which I am not allowed to see. I hope you got the idea, where I am heading.
My question is - What is the best approach to secure this?
I was thinking about storing logged user Id (Integer) in session and comparing it everytime request for resource is made, but it seems to me that I am pulling the wrong end of rope :)
Thank you for any advice
You should have a look into the Expression-Based Access Control section of the spring security documentation.
Example copied from the documentation:
#PreAuthorize("#contact.name == authentication.name")
public void doSomething(Contact contact) {
..
}
This would check if name of the contact is equal to the name of the currently logged in user.
Using this this feature you can build much more sophisticated access rules than you could do with simple roles. However, this does not exclude using roles. You can still keep roles for basic security checks.

Several different login forms for Spring Security

I'm using spring-security web authentication with spring-mvc with a custom authentication and all is well so far:
My problem is: /login loads a view with a fully-featured page, but now I have to provide authentication for iframe/popup format (e.g. for an authenticated bookmarklet), so loading a different view (or with different parameters).
I see two solutions that are not overcomplicated:
In my /login action, I have a way (unkown to me so far) to retrieve the original request and check it against a set of URLs that use the simpler view, then choose the matching view. => How do I retrieve this original request?
I make another login action/form, say /login/minimal, which also POSTs to the spring security URL /j_spring_security_check, but I need to implement the request storage/retrieval mechanism, so that the original request is performed after successful login. => I see this has something to do with SecurityContextPersistenceFilter, yet I don't know how to implement it or call it.
If I understand your question correctly, you're looking to vary the login page based on the original request string. Check out this forum post for accessing the original request url from the session. It's for an older version, but you should be able to use it to get started.
Edit I haven't had a chance to validate this, but it looks like the key changed between Acegi security and Spring Security 3. It looks like you can access it from session using the constants in the WebAttributes class. Effectively
//request is a HttpServletRequest object
SavedRequest savedRequest = (SavedRequest)request.getSession().getAttribute(WebAttributes.SAVED_REQUEST);
String url = savedRequest.getRequestURL();
For your first question:
there is a class org.springframework.security.web.authentication.WebAuthenticationDetails
It contains only the IP of the client and its Session, but
it has a method
protected void doPopulateAdditionalInformation(HttpServletRequest request) {}
I belive you could enhance this by subclassing and add the request url. -- But check first if the request is the request from the login form, or the "blocked" request.
Added
Chris Thompson posted an other part of the puzzle to answer your question:
He mentioned that the saved request can be obtained from the session:
//request is a HttpServletRequest object
SavedRequest savedRequest = (SavedRequest)request.getSession().getAttribute(WebAttributes.SAVED_REQUEST);
String url = savedRequest.getRequestURL();
So you can combine this, instead of enhanding the WebAuthenticationDetails you just need to read its already inclueded session.
#see Chris Thompson answer

Categories

Resources