Hi I'm trying to implement auth protected audio/video stream in angular app via REST api. The goal is to secure audio/video to not to be shared with other not logged users. I tried single use token so flow looks like this:
Angular ask for single use token after you click play button POST: file/1/token
Angular get the token and paste token into url ?token=...
Stream request is send to the server GET: file/1?token=...
Server checks the token and removes it from database
If token is right stream begin
The problem came when you click on timeline where stream is not buffered yet so the browser automatically sends another request which of course is unauthorized because token has been already removed.
I want to keep api stateless but as you see some kind of state is forced by html media.
I would love to hear your hints or solutions on that problem.
Problem is solved for now. Maybe it's not the best solution but it covers all requirements.
We decided to use session which breaks the REST principles but simply works.
Now we getting token as it was before POST: file/1/token
Getting file with provided token GET: file/1?token=...
The difference is that in the controller we open new PHP session, save token into session and remove it from database. Now we are able to check whether token is in database or in the session.
So if you send link to other people they don't have an access. Only you have access as long as token is in the PHP session.
Related
I'm working on a e-commerce using next.js and sylius API and the API admin routes are secured using JWT. So in order to fetch products (for example), i need to login to the API, get the token and then fetch the products using the token. The most common method to be able to send the token on every new requests to the API is to store it in a HTTP-only cookie.
As the pages are generated statically, i feel i don't need (and want) to expose the API token to the client. So i'm wondering the best way to store the token ?
Here the different options i have in mind right now:
store the token as a http only cookie and use it server side (with a proxy using next js API pages) in order to call the sylius API. Like i said, i'm not confortable to store the API token into the client, it seems risky to me, as it will be exposed to everyone, and with that token you can access the admin API.
configure the API in order to prevent the token from expiring, and store it in the next js app as an environnement variable (.env.local), so that it's not exposed to the client and can be used for fetching the api when generating static pages. The official ecommerce theme of Next.Js seems to use that method (https://github.com/vercel/commerce/blob/f770ad7a91059a2ecfbb9de1bac111dfe7016124/framework/bigcommerce/api/index.ts#L82)
store the token somewhere in the next js structure but not as an environnement variable (maybe a config file?), so that it can be replaced if necessary (if the token expires etc).
get the token and store it in the react state as is it will be used once only for generating all static pages. On each build the token will be asked again by the API and then used for fetching the API for exporting the static pages with the content. It don't need to be saved more time than the building step.
For me the last option seems better but i feel i'm missing something there, i'm kinda new to next, so i'm not sure exactly if its a good solution.
Thanks :)
I get a great answer from a reddit user ("supermaguireray"), so i post it as an answer here:
"First of all, in any session management mechanism the correct information needs to live on the correct domains, what I mean is that your client can only have access to a identification information, but never to data used in the server, these can be applied to a server-side session, when a ID for the user data stored on the server is sent to the client (preferably encrypted), or in a JWT where a encrypted string is sent to the client (identification), and decrypted on the server (Data).
With that said, the only reason you should send the API token to the client is if you need to fetch data directly from a browser. Storing as a httpOnly cookie is the most secure way.
In case you only need the cookie fetch data to the next backend, to render your SSG or ISR pages, there is no need to send a cookie to the client. Just store the token in your server. I would store it as env variable. Use next.config.js->runtime-configuration.
Or, you can keep a expiration date for the token, and store the credentials, maybe even in a DynamoDB or FaunaDB app."
So I created a react-redux webapp, in which the login/signup is done using JWT authentication. This app uses a lot of server api, and due to security reasons each api request needs to accept a valid token, only then it sends back a valid response, else, it simply sends an error object back saying the token is not valid.
Now the problem arises when suppose I open my account in one browser, lets say chrome, and then I also open the same account in Firefox, now, obviously the token has expired in chrome, so when I make requests from chrome I simply get the error object returned, what would be good that I have a middleware before each server request which would check the validy of the token and then redirect to login if the token is invalid.
I am quite new to redux and was wondering if something like that is possible, any kind of help is appreciated, Thank you.
I'm using JWT for authentication in my Angular.js application, with Express.js on the server side.
Basically, when user logs in, a new token is created (using https://github.com/auth0/node-jsonwebtoken) and send back to the client. If token is valid also on the client side (angular.js part, using https://github.com/auth0/angular-jwt), a new user is created and the token gets stored in a cookie.
So, each request to certain path on the server is protected by a token validation. However, my token has an expiration time. Now let's say for the sake of argument that expiration time is 30 seconds; user can actively use my application for 30 seconds and after that, he gets logged out. That's not exactly user friendly.
So what I did was that with each request to the server, I create a NEW token and send it back in the head of response. When I receive the response in my Angular.js client-side, I read the token and overwrite the token in the cookie. That way, as long as client is active (or rather, makes requests to the server side), the token gets refreshed.
Now I'd like to know the following:
Is such an approach correct? The downside is, that token gets created at each request and send back in each head of response. Cookies get overwritten quite often (performance issues?)
What would be the correct approach?
Is it OK that the token expires if there are no requests to the server? Client might still be using the application, however, if he's only writing on client side something (or reading), the token does not get refreshed.
Thanks for your time and responses!
Yes, that is a valid approach. It is the same approach many take,
including the popular Angular module ng-token-auth. You might
consider saving the tokens to local storage, with a fall back to
cookie storage if the browser doesn't support it (see
http://caniuse.com/#feat=namevalue-storage for coverage).
I would do what you describe.
One solution is to use $interval to basically ping the API. All you need to do is send in a token a get a new one back (i.e., in headers like you are now). Keep track of how many "pings" you've sent. You can reset the number of "pings" upon certain actions like on ui-router's $stateChangeSuccess (i.e., navigating to a new view) or anything you like, including submitting a form or other non-ping requests. When the number of "pings" reaches your threshold, warn the user that their session is expiring, and after a delay, erase the stored token and log them out. Check your ping responses for authentication errors from the API, indicating that the user might need to be logged out and/or redirected.
Perhaps you just gave 30 seconds as an example token lifespan. I would recommend getting closer to the browsing session timeout that you want. As points of reference, consider that the Ruby gem devise_token_auth defaults to 2 weeks and that .NET defaults to 10 hours. Your needs may vary.
The problem is also addressed by using refresh tokens. Your access token has a short life and is verified by signature. The refresh token has a longer life and is used to get new access tokens.
When the refresh token is used to get a new access token, that is a good time to do extra checks: has the refresh token been revoked? Is this user account still valid?
Both tokens can be stored in secure cookies and supplied on every request. Doing this allows your server to transparently use the refresh token when needed and set new access tokens in cookie responses.
This is the approach we've taken for Express-Stormpath and is documented in our Authentication section of the documentation. If you'd like to offload your authentication layer, I'd suggest Stormpath. (Disclaimer: I work there, and wrote that module).
My context:
An AngularJS application using the Javascript Facebook SDK, and my distinct server (REST APIs).
Workflow:
User is logged in the client through the FB SDK using the method FB.login(callback).
This later gives a short-lived token that is then sent to the server in order to transform it to a long-lived token.
I'm interested in the mechanism of refreshing the long-lived token after 60 days.
So, reading the doc, we found this:
Even the long-lived access token will eventually expire. At any point,
you can generate a new long-lived token by sending the person back to
the login flow used by your web app - note that the person will not
actually need to login again, they have already authorized your app,
so they will immediately redirect back to your app from the login flow
with a refreshed token - how this appears to the person will vary
based on the type of login flow that you are using, for example if you
are using the JavaScript SDK, this will take place in the background,
if you are using a server-side flow, the browser will quickly redirect
to the Login Dialog and then automatically and immediately back to
your app again.
If I interpret it well, when user is ALREADY logged in through FB.login(callback), a simple redirect to the Angular Application's login flow would allow to get a new short-lived token.
I imagine that the FB.login is immediately run anew in this case, without user interaction, as written.
I want to test it simply, so what I've done is:
Logged in into the application through FB.login(callback).
Clicked on a dummy link making a simple redirect with: window.location.replace('/');
My application being a single page application, every URL should be considered as the authentication page.
But the FB.login isn't run in the background, as I expected from the doc.
What would be the reason?
Does it work only when the domain making the redirect is distinct from the client? (I just can't test this case right now)
Did I misinterpret the doc?
I've read almost every answer on SO and some blog postings, but I can't figure out one simple thing. In a simple token authentication scheme where the server generates a token and sends it back to the user after verifying credentials, how does the client store and then resend that token in each request? I have seen both cookie examples and header examples. I would like to use the HTTP Headers if possible, but I can't figure out the mechanics of how to send the token to the client, where it will sit, and then have it sent back in the header upon requesting a REST resource.
I am using Jersey/Guice with AngularJS on the front end. Here are the resources I started with:
http://porterhead.blogspot.co.uk/2013/01/writing-rest-services-in-java-part-6.html
Session management : How to generate Authentication token for REST service ? (Jersey)
It depends on your needs. You can use HTTP basic or digest auth, if it is appropriate for you. If not, then if you don't need a permanent storage, you can store credentials in memory. If you need a permanent storage, then you can store them in localstorage, or any other client side storage, but aware, that they are considered not secure.
Anyways I think if your client or service is compromised somehow with xss, then you lost, and it does not matter what else you do about it. Otherwise you can send the credentials in plain text securely as long as you use HTTPS with proper settings. (But that's just an opinion, I am not a security expert, at least not in this topic.) So I think you should concentrate on not being xss vulnerable. For example you should use the proper headers and filter the input against js injection (and by firefox data URI injection). And use TextNode in your client instead of innerHTML wherever it is possible.
For example if you are using Javascript you can store the token in localstorage like window.localStorage["token_id"] on the client side.