I am building a REST API.
Client side, I use Backbone.
Upon authentication, the API sends a token via ajax over to Backbone's Session model.
I place that token using jQuery's ajaxPrefilter method, to be send back the token towards the API on every request.
Everything works perfect, until the users refreshes the page.
If the page is refreshed, the token is lost, the model re-initializes and the user has to authenticate again.
How can I bypass this?
1. Store the token inside a cookie (very unsafe, bad idea) - defeats the REST purpose.
2. Store the token inside LocalStorage - equally bad, I believe.
Is there something else that can be done?
Thank you!
You can store the token both ways.
If you're using ssl, the token is only available to the client (and NSA, maybe) which brings no problem.
I rather store those token using localStorage unless the client doesn't supports it.
You can also check this answer
Keep Session Across Page Reload In Backbone JS
Related
I'm currently playing around with a KnockoutJS SPA template in ASP.NET Core 2.1, and I managed to implement an authorization flow exactly as this one which was made in Angular:
https://fullstackmark.com/post/13/jwt-authentication-with-aspnet-core-2-web-api-angular-5-net-core-identity-and-facebook-login
As you can see in their User front-end service, basically the only check for whether the user is logged in on the client side is the check if the "auth_token" key exists in the client's local storage:
https://github.com/mmacneil/AngularASPNETCore2WebApiAuth/blob/master/src/src/app/shared/services/user.service.ts
this.loggedIn = !!localStorage.getItem('auth_token');
// ?? not sure if this the best way to broadcast the status but seems to resolve issue on page refresh where auth status is lost in
// header component resulting in authed user nav links disappearing despite the fact user is still logged in
Simply put, anyone can open up the browser local storage and insert a random string with the "auth_token" key and they'll be able to see everything admin-related in the UI (even though they will fail on API requests).
Can someone suggest a better flow for this? Or is the only option to send a "log in request" to the API, whenever an admin page is "opened"?
P.S. I am relatively new to the authentication schemes front, should JWT perhaps not be used for client-side content validation?
Considering JWT best practices, all your validations should be done in your back-end, since any validation coded in your web app could be read by any of your clients, resulting in a huge security flaw: anyone would know how to create a valid JWT for your application.
Is it a big problem to be possible to see your admin-related UI, even without any data? Considering that all of the routes which can return sensitive data are protected by JWT authorization, if a user access any pages or parts of your UI which require data, they would trigger a request to retrieve it, which would probably return a 401 (Unauthorized) HTTP status, or similar. A common front-end practice in these situations is to erase client user data, and redirect to a login page.
So, a typical flow would be:
User inserts a fake access token into their storage
User opens an admin page/ui which uses sensitive data in any way (showing, using for any internal logic, etc)
Web app does a request to the API requesting data
API returns a response which will be interpreted as an authorization error
Web app receive the API response, erase user access token and redirect them to its login page
In most cases, this entire flow will happen fast enough to block your user to further interact and explore your web app.
Would be better if you provide more information about your scenario, so anyone could understand if your worries are something that needs to be considered and truly solved. However, in most cases, the behavior above is accepted.
Well I am trying to build a web app with angularjs. In my webApp there is a login page aside with register page. My main problem is how to implements a login page and maintenance session with the specific user, the warning dots that came up with this scenario is when the user going to log in my web app, I will probably send a post to the server and then will get a successful result if the user and password are okay. now during the whole application the user may use his own properties like: money, friends, age, etc... now in this situation I would like to use a session that contains all of the "data" of this specific user, but when I use angularjs, because the whole thing is on the side client, I dont think its a good idea to save the password and critical information about the user in the client side, but still i need any verify information for this user, to know that he is who is he.
I don't know how to implements this scenario good when i use angularjs, with php it may be more convenient, because there is session, which stays in the server side, and I have to worry a little bit lower than using angularjs. Can someone clear this situation?
You don't want to save classified data on the client. This data has to come from the server.
This means that the angular controller that supposed to show this data must retrieve is from the server.
You should have a service that will use $http to get this data from the server using Ajax.
In order to retrieve the data for a specific user your client should send a token to the server that uniquely identifies the user.
This token will be sent to the client as a result of a successful login.
The client will keep the token in a cookie or in the local storage and add it to every http request.
I've got a backbone webapp, It consists into several form pages w/o any authentication.
All users are anonymous but i need a kind of logic to identifying them along the process.
Actually this is a comparator service.
I consume thru CORS a API in charge to deliver some contents, such as querying a Vehicule database, things related to a insurance policy and geo location...
No issues regarding consuming datas.
Now the question is more regarding how to save the anonymous users datas thru a multi-step form in the API.
The Goal would be, each time a user click on the next step, anonymous user datas will be save ( this is for analytics reasons ) and secure a bit the API with these POST requests.
As the webapp is in pure JS, i was thinking to do something like this :
if a cookie doesn't exist, i generate on the client side a session_id with with a js crypto lib and store this session_id into a new cookie ( with a expiration ) . Then a backbone model ( Session/Singleton ) will be in charge to store this session_id into a redis-cache store thru a Backbone.save(). Expiration of the Redis Key will match expiration of the cookie. Id attribute of the Session Model will be the session_id.
If the cookie exist. i'll fetch() the session from the API thru a getSession verb.
In this way i could keep tracking of every anonymous users to save the datas in my API. Do you think this is a good pattern or too naïve ?
Now, about securing the API... i'm stuck.
I was thinking about HMAC but if the secret key is stored on the client side ( backbone app ), shared for all users, someone could inspect the js client code, even uglyfied, and find the key...
I read many docs about this, but all are talking about a username/pwd/token scheme, in my case i've got only anonymous users...
Maybe, in the REST paradigm, anonymous users means that the datas are not sensitive.. .
Any advices ?
Thanks,
Anything that is stored client side is not secure. When it comes to an SPA, you usually authenticate a user using a username and password. Once the user is authenticated, you send a an Authorization token in the header of every request. If I am understanding your question correctly, you are worried about sensitive data being sent and inspected when the user is registering? If that is the case, you are best using a secure connection. I am curious to know how you think this is different for a non-backbone or SPA app? You would still be sending the data over HTTP, REST or non REST.
I have an angular.js single page app that authenticates against a RESTful API (Servicestack). This all works fine. When the response from the authentication api is returned the username is stored on an Angular service and an isAuthenticated flag is set to true.
Any requests against an [Authenticate] attributed web service then returns data.
My issue is that when I refresh the browser my javascript angular objects are flushed and the fact the user authenticated is forgotten. Yet when I call the [Authenticate] attributed service they work correctly because the session is still live...
Apologies for the rather noob question but how does the browser pass the session to the web service when the javascript objects have been destroyed and recreated? How do I grab the same session on refresh and set my Angular service up with the username etc.?
ServiceStack Authentication uses cookies to store the session token by default. Which means your Angular application will receive the cookie when you first sign in. It will pass this for subsequent requests, and they will succeed while the session is still valid on the server.
The problem will be that Angular will lose the object state, when you refresh the page, that is telling it you have an active session. So you must restore this knowledge to Angular. There are two ways to tackle this:
Check for the ss-id cookie when you application starts and assume you have a valid session. In other words, so restore to a signed in state, until you get a 401 error from the server. This is the quickest approach, and doesn't require additional overhead to check the session if somebody refreshes the page.
Check for the ss-id cookie and make a test authenticated request to check the session is still valid.
If you need to restore other information such as the current logged in user's name etc, then you would need to store that in a cookie/local storage to restore it on refresh, or go with method 2, and retrieve it back from the server.
You can use $cookies provider to manage the session cookie.
When working on an Angular app, I have a single page app that communicates with a JSON web service for data.
A "login" in my Angular app is really just exchanging a username/password for a token. That token is passed as a header on all subsequent requests so the server can authorize them. This works great until the users refreshes their browser window of course (via refresh or leaving the "page" and returning).
Obviously one option would be to make the user enter their username/password again, but that seems like a good way to not have any users.
I can think of 4 options:
Store token in a secure session cookie. (What I'm doing now. I am only using so the client can read. Not used or wanted on the server.)
Store token using local storage of some kind. (Would be insecure and
require manual expiration maintenance.)
Prevent user from refreshing browser with some "onbeforeunload"
code. (I don't like when I get the "are you sure you want to leave
this page" messages and I assume others feel the same.)
Include token as part of url. (Could make url's look big and messy. Possible physical security risk. Might make for extra work with bookmarking and expired tokens.)
Is option 1 the best option for this functionality? Is there something better to do than all of these?
I think option 1 is the best one for your use case. All major web frameworks have support for this option.
In case you need to handle this manually you need to ensure these steps:
The web service will process the initial authentication request by creating and setting a secure authentication cookie. The auth cookie should be time based(only valid for a specific time interval) and its value should be a unique value if possible;
After the initial authentication request all subsequent requests will pass the authentication cookie with the request header automatically - this is handled by the browser.
The web service needs to handle cookie based authentication on subsequent requests by validating the cookie value and returning an error if the cookie has expired.
You need to ensure a client side global authentication handler captures any authentication exceptions and displays a friendly message to the user.