On refresh browser go to last finished step using cookies(java + react) - java

Ok, so I have simple website which force user to start from last finished step. Whenever user refresh page he needs to call at application initialization to:
REST /user/{id}/step
This endpoint will tell where user finished. The problem is I am using http only cookie. So I cannot get this {ID} from cookie in javascript.
At the moment I have added additional cookie(NOT http only) named clientId. So application can get his id from cookie, and call to this particular endpoint.
It is working but I feel that it is kinda not best approach. It has few side effects like taking care of clearing this stupid cookie on logout, etc situations.
What is best practice ? I've been thinking about creating additional endpoint which will be used on every application initialization
REST /user/status
// I want to be restfull, so I dont want REST user/logged/step
which will return setCookie clientId="" or setCookie clientId={ID} whenever user is logged or not, in this case I even don't need to care about clearing cookies on frontend side, any ideas?

The problem is I am using http only cookie.
So this http only cookie contains what? I presume a user's session? Then why do you need to specify this user ID in the URL if you should be able to get the ID from the session token?
I believe you should just have the following endpoint REST /user/step which returns the step number for a current user (defined by the session token in the http only cookie) or it returns 401 code (Unauthorised) if the user is not logged in..

Related

Implementing a token style security when doing GET requests

I'm implementing a temporary and very simple token-style authentication mechanism for an application.
The idea is very simple. Whenever a user logs in to the application, a token is returned to the client, which stores it in the sessionStorage data structure of the browser.
Now, whenever I do a request through AJAX I can send the token with the request and the server can verify if this token is associated with an authentication or username. If it is, it parses the request normally, if not, a error page or the initial page is returned or displayed.
I'm not sure if this is the way that token-style authentication and authorization is implemented in real or serious applications, but I've now no idea how to send the token when doing GET requests by just clicking on the link of a view.
My only idea would be to intercept the get requests so that I can fill them with the token, but this all seems to be quite odd, and I've already a lot of links and views.
Search for Json Web Tokens and for implementations on java. This is exactly what you need.
If you want to send to the user some sensitive data inside the jwt, use Json Web Encryption.
You can send that token on each request header or as a request parameter
You can set a cookie, ensure to set it httponly (ans secure if you are on an https site) and read the cookie on every request that reach the server.
You can use JWT token (see https://jwt.io/introduction/). JWT is basically a JSON data structure. Usually, the token is passed along in the authorization http header.

CSRF Protection: Methods to send CSRF token for each request

My initial code generated tokens for the requests that could alter state of my database, like CRUD operations. The token was generated for each request. Sent to client side in JSON-format along with other data and I expected this token to be returned with the request and changed it after completion of the request. But, as I implemented it to only parts of my code (CRUD operations), I was told to redo it and make it web-app wide. I think the best way to do this is with filters.
My problem is, how do I make the client send "the token" for each request? Do I set it in cookies? What are my options? Please advice.
best way is , all links should be GET request, and within get requests no modification should be made to application state. So for GET requests there will be no need for CSRF tokens.
For POST request s which make modifications in application state you have to generate, csrf hidden fields in your forms and validate the token in server during form submit.

Spring MVC strange behavior

I have a method that handles request with a URI of "/home". This request is generated upon successful log-in procedure. Here is a little code to support my situation:
<security:form-login login-processing-url="/static/j_spring_security_check"
login-page="/login" authentication-failure-url="/login?login_error=t"
default-target-url="/home"/>
The method body demonstrates what I am attempting to achieve:
String userMail = SecurityContextHolder.getContext().
getAuthentication().getName();
logger.info(userMail);
Person p = userService.retrieveUserByEmail(userMail);
session.setAttribute("person", p);
return "user/home";
This bit is important as the person p is used as data source for other requests.
Now the problem. I don't know if it is the property of Google Chrome, but for some reason the browser remembers the request you've done before log-in and instead of going through /home request after successful log-in procedure, it generates the previous request bypassing this /home gate, resulting in null pointer exception as person p was never set up, as session wasn't populated by /home request.
I know that for other requests I should do validation, but I don't like the idea of letting user generate any request without prior going through /home .
Done with text description and now to explain how I get unwanted behaviour in steps:
ask for request that you know exist such as:
myApp/nameOfSomething/viewThisSomething - you are brought to log-in page as expected(you must be authenticated for request to be accepted)
you enter correct credentials and instead of going to default-target-url="/home"
you are automatically making previous request myApp/nameOfSomething/viewThisSomething without populating session with necessary data and resulting in nullpointer exception.
What else is interesting is that logger shows the mail, so it might be that they are both executed at the same time but /home request is slower - can that happen?
I resolve the situation in other method by checking if null and forcing to go back to /home which works as expected, but I am control freak and don't like when user is doing what he is not intended to do.
Thank You for Your time,
It's not a bug, it's a feature. It's much more user-friendly to let the user go where he wants to go after login than forcing him to go to the home page. He could have bookmarked one of the protected pages, or simply browsed some non-protected pages containing a link to a protected page.
From http://static.springsource.org/spring-security/site/docs/3.1.x/reference/springsecurity-single.html#ns-form-target:
If a form login isn't prompted by an attempt to access a protected
resource, the default-target-url option comes into play. This is the
URL the user will be taken to after successfully logging in, and
defaults to "/". You can also configure things so that the user always
ends up at this page (regardless of whether the login was "on-demand"
or they explicitly chose to log in) by setting the
always-use-default-target attribute to "true"
IMHO, you should keep things as is, but make sure that the required sesion attribute is set once the login is successful, instead of setting this attribute in the home page. This would ensure that every protected page has access to the session attribute, even if the user didn't go to the home page.
You could do this easily by using a custom UsernamePasswordAuthenticationFilter subclass, that sets the appropriate attribute in session once the authentication has succeeded.

Java: Session attribute is only in next operation

I'm posting some strings in my Session with the call
request.getSession().setAttribute(key, value);
And making the redirect with
response.sendRedirect(urlRedirect);
In almost all cases the values is there after the redirect.
But sometimes I can only read this value in the next page view, not in the redirect. There is no common behavior.
Someone has faced the same problem?
Sessions are backed by a HTTP cookie. On first-time session creation, a cookie will be set in the response header. By default, cookies are bound to a specific context only.
So, if you redirect while the cookie hasn't been set yet, the session will get lost. To go around this, you need to encode the redirect URL.
response.sendRedirect(response.encodeRedirectURL(url));
This appends the jsessionid identifier to the URL which allows the servletcontainer to locate the right session without help of a cookie.
If you don't like the jsessionid thing, then consider implementing a filter like this which ensures that the client is aware of the session cookie before the request enters your controller wherein you fire the redirect.
Also, if you redirect to a different context, it won't be able to access the same session. To go around this, you need to configure the servletcontainer to share the session among the contexts. In for example Tomcat, check the emptySessionPath attribute of the <Connector> element in /conf/server.xml.
Such a behaviour can be caused by caching.
If the page you are redirecting to is retrieved from the browser cache, you obviously can't see the result of setAttribute() on it. So make sure it's actually requested by the browser.
Are you sure you need to do redirect through browser (response.sendRedirect()) and not on the server side (RequestDispatcher.forward())? Latter is faster as there are no network round trip.
The problem was solve by changing the way of submit.
The page was submitting the data only changing the value of location.href to the Servlet Action.
We only call the submit function from the page form, and the session attributes works fine!

Cookie available in the same request/response

I have found a strange behaviour (strange for me, a novice :D) in my project.
Basicly after an action I create or update a cookie (if it exists or not) and send it to the client. The strange thing is that in the jsp I can read the cookie ONLY when I update its value (and I get the updated value, not the old one) but not the first time, when I create it (I can see the cookie using a browser tool but seems that the jsp can't read it).
Is this a normal behaviour? If yes, what do you suggest to do in order to have the cookie information available also at the first time?
Thanks very much!
Roberto
If you create or update a cookie, it will be stored in the response header. If you request a cookie, it will be requested from the request header.
I think your problem is that you're forwarding the same request from servlet to JSP and that you expect that the new cookie is already available in the request header. This is not true. The new cookie is only available in the subsequent requests.
You have 2 options:
Redirect to JSP. A redirect will create a new request.
Store the data of interest as request attribute and let EL in JSP access it.
By the way, I saw in one of your comments that you're using plain Java code to read cookies in a JSP. I would only say that using scriptlets in JSP is a bad practice. You can access cookie values easily in EL as follows:
${cookie.cookiename.value}
[Edit] oh my, now I see that this is an old topic. Hopefully my effors weren't all for nothing :/
Cookies are stored on client, and so if the response doesn't gets to the client yet, its value is not updated, but it should be available on the next requests.
cookies are used to identify clients when they send you any requests. here's what you are doing when you set the cookie up. you are sending the cookie to the client along with response. And when that client send his next request the cookie that you set comes along with it. so, in the jsp page where you are setting up the cookie, you don't have a request from the client with cookie! so you can't read it. but what you can do like what jerjer has said above. (i.e use a temp and store cookie's value in it and don't try to retrieve cookie. just read the temp value). And i see you say you can read the cookie only when you update. You will be able to read cookie's value from future reqests after cookie is set even if you don't update it. Hope this helps.

Categories