I'm setting up an HTML5 and JavaScript web application to consume Azure Mobile Services tables using the JavaScript client library. I've managed to get authentication setup successfully with the MicrosoftAccount identity provider. On load, my application checks if the user is already logged in, or if we have a token and username stored locally. If true, I hide the login button, and display the logout button, and proceed to load application data.
My problem is that when a token that is stored locally expires, my application still thinks the user is logged in. Therefore when I request table data, I get a 401 Unauthorized HTTP response.
Is there a graceful pattern to renew an expired token without burdening the user with relogging in every time their token expires?
You will need to log the user in every time, unfortunately. The token must have a lifetime associated with it. On some client platforms, you can get much longer lifetimes via single-sign flows, but these are generally not available for HTML. The common pattern is to, upon receiving the 401, retrigger your login code. Here is a blog post showing the approach for the Mobile Services Managed SDK. The same concepts should apply for JS.
Related
I'm new to react but i have previously worked on server side rendering websites
My objective is to make a website where at first only a sign-up, login page is shown and if the login was successful the user would be able to access other pages
I'm using and api which provide jwt tokens and jwt refresh tokens for authentication, the main token expires in 1hr and i need to auto generate new token by then in the background without the user knowing
So how should i go about implementing this any example code would be helpful
This site is about helping to solve specific programming issues, noone will write your app for you. The idea is to acquire the token via authentication, persist it in browser (local/session storage), then attach it as auth header to every api request. For refreshing the token implement some setInterval.
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.
I've been reading up on token based authentication for a project that's part of my trainee-ship. My task is to implement some sort of user authentication and we've settled on token based authentication.
Now I get the basic principles, like passing the token in the xhr header for xhr requests. But I do not understand how you would pass the token on an initial page call.
Let's say we're working on a single page application with a navigation bar that has a login button for users that are not currently logged in, and a profile button for users that are logged in.
Seeing as that navigation bar is delivered on the initial call of the website, how do I know how to serve the right button to the user? From what I can gather I can pretty much only authenticate on xhr.
Do I have a misunderstanding about token based authentication?
A little clarification:
Assume a User already is logged in and has received a token from the Server.
He then closes the Tab and later goes to my app again.
At this point, server-side I do not know the user, as I could not have sent the token at the initial request.
A coworker suggested using AngularJS' onload to send the token after the initial page load to verify and get my JSON data from the server, which is then used to create the app with Angular
Also the point of the project is to not use an existing library like JWT, so I can actually grasp the concept and the inner workings of such mechanisms.
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.
So I'm developing my own API for my website - I'm mimicking the Facebook JS SDK in regards to how my system works. API client displays a button, popup comes up and the user can log in. Login popup issues an event to the opener window and the parent window now knows the user is logged in. That all works.
What I'm having trouble understanding is how they can verify that the refresh requests are valid. If the API client needs to send a request to the server to ask if the user is logged in and it's all in JS, then everything is transparent. The API client says, "Hi, I'm application 4jhkk2l3bnm389, is the user that's logged in on Facebook also authenticated with me? If so, can you send me a new token so I can make API calls?" and Facebook says, "Oh, you're application 4jhkk2l3bnm389? Yeah, the user is logged in and has allowed you to access their information, here's an access token."
But how does Facebook prevent an outside application that isn't the authentic application from saying, "Hey, I'M actually application 4jhkk2l3bnm389, I promise I'm not lying. Can I have an access token?"
I have no idea how they determine the difference. Obviously if it was all done through AJAX calls in modern browsers then you could just provide an Access-Control-Allow-Origin header. But if a malicious client were to use cURL then I don't think I could ever tell the difference. How does Facebook do it? A good explanation is much appreciated! Thanks!
All access tokens belongs to an app/user pair, and in order for Facebook to return such an access token to the app, these has to be verified.
The app, or client_id, is verified against the domain specified in the redirect_uri - if the page tries to use a client_id/redirect_uri pair it does not own, then it will not receive the access token as this will be passed to the valid redirect_uri (the mechanism the JS SDK uses follows the same rule).
The user, or uid, is verified using the cookie Facebook sets when you sign in.
While you can easily spoof the client_id/redirect_uri pair using curl, the same does not apply to the uid, as you would have to be in the possession of the users cookie. And if this is the case, well, then you could simply grant your own application access.
Facebook uses OAuth 2.0 for authentication. You can find details of how Facebook deals with OAuth right here: https://developers.facebook.com/docs/authentication/. There are many different ways OAuth can be used, depending on whether you're on a mobile device, a page on facebook.com itself, or, in your case, just a web page outside of facebook.com. The details of that final flow can be found here: https://developers.facebook.com/docs/authentication/client-side/.
Basically, Facebook knows what applications you have given permission to view your information. When you run one of those applications, they first make sure you are logged in to Facebook, then they request a user access token from Facebook, essentially saying, "Hey Facebook, I don't know this person, nor should I. Can I get access to their information?". And then Facebook looks internally and if it decides this particular application should have access to this user's information, it sends a user token.
That's the simple way of describing it. There are many different ways the authentication flow can happen, depending as I said earlier on what kind of device the request is happening from, whether this is a page on facebook.com, etc., essentially based on your security constraints. Best to read the Facebook authentication docs referred to earlier for the details since it can get quite tricky.