Token vs Cookie for SPA - ruby-on-rails

I'm using devise_token_auth for a rails application with react on the frontend and rails as the backend acting as the backend.
In the readme the author states that
If you're building SPA or a mobile app, and you want authentication,
you need tokens, not cookies.`
Why? I understand the basic differences between tokens and cookies, but don't understand why you couldn't just use cookies (simply including the headers with any XHR requests)?

There are a few major reasons.
First of all most SPA's are designed as stateless and using cookie based authentication is not stateless. Using cookies also makes every request take a little bit longer because there is a lookup on every request.
Cookies are also tied to a domain. Most SPA's use multiple services across multiple domains which is a no go with cookie based authentication. This also applies to SPA's which have a web app and mobile app, using token based authentication means scaling this is much easier.
Tokens can also be used to store data and only need to be generated once, after that there is no work involved except for the server reading the token. This means you can store user permissions in there etc and the server can get this information with very little work.

Related

Consuming my own Public API on my website

I have a website that exposes a public API. I want to secure this public API using OAuth 2. In order to minimize the number of code paths to maintain, I want to refactor my website to use the OAuth 2-secured public API endpoints.
The way I intend to do this is to register an OAuth 2 Client in my server as "my website", and then have that fetch a short-lived token. I see 2 problems with this approach:
My client would have to effectively have every scope, since the
website encompasses every possible action. The API is just a subset
of this (though I'm hoping to change that). The second issue is
security and caching of the token. The token would live for an hour.
If the user refreshes the page, do I fetch another token? If I store
it locally in a cookie or localStorage, is there a security
vulnerable of some sort?
Let's say I register a different OAuth Client for each page of my UI. The would make it so that the token in #2 would have limited scope if stolen, but it gets extremely tedious.
The alternative is to not use the public API on my website, and protection relies on CORS. Malicious attackers cannot access these endpoints because they are only allowed to come from the domain the user is on (and things like nonces).
Sounds like you want towards a model based on a Browser UI calling APIs directly, which is certainly the most attractive architecturally.
This may be the first step to a Single Page App architecture, which tends to provide the simplest and cleanest solution.
See Open Id Connect for browser apps for latest standards.
In an SPA the UI is cookieless and it is common to store short lived access tokens in HTML5 session storage, which means the user can refresh the page ok
It is true that all scopes are retrieved after login, but if you keep scopes simple and authorize in your API based on user rights you can mitigate that
The above token storage is the default behaviour for the certified OIDC Client Library and widely used.
There is a cross site scripting risk, that malicious content in your browser tab can get a token and call the API - but you should be protecting against this anyway.
Older solutions such as use of auth cookies tend to have their own (and bigger) risks such as cross site request forgery, where any malicious content in any browser tab can send the cookie to your API.
Evaluating whether to use HTML5 storage of tokens is about more than just the technical mechanism - it is about acceptable trade offs around usability and what can be done with the token. My blog post on UI token storage drills into this.
If it helps, my blog also has quite a few posts and code samples on SPAs, in case it is of interest.

How to handle authorization and authentication on SPA with OAuth2?

I am developing an SPA and would like to have SSO.
As I understood so far, OAuth2 with OIDC is the best solution for SPA SSO.
Better than, for example, SAML.
What I didn't understand so far is how to use authorization token in SPA's JS code to handle authorization on various resources of SPA. For example, I would like the users with a role 'buyer' to have access to the shopping history tab, where other users won't have access to.
Should I parse access token obtained from Authorization server in JS code and check whether a user has an appropriate role to see the tab, or should this decision be made on server (API) side, in which case SPA's code would just read the answer from API and based on that customize UI?
In case of the first approach, is there any standard way of doing the checking (in form of some JS library)?
When it comes to authentication, what is the better approach (more secure, etc):
to let SPA (at that point already loaded in the browser) do the authentication flow and based on result let the user use it's protected functionalities. This is pseudo authentication actually since the code is in the user's browser and means the user is authenticating himself to the code in his hands i.e. to himself. Does this authentication make sense at all?
require the user to authenticate himself in order to be able to even load the SPA in his browser. This is probably not SPA architecture then since backend which serves the SPA should be able to create a backchannel with the Authentication server.
According to user description, your application must vary depending on user type. If this is the case I would suggest you to use a backend for authentication and decide application content to be served from the backend. Otherwise, as you have figured out, running authentication on browser and altering user view is not secure.
IMO this not necessarily break SPA architecture. What you are doing is altering what you server based on tokens presented to you. Also, maintaining a session will be required with this approach. And SPA's calls for backend will require to contain this session to obtain contents.
As soon as the User is logged in, you would request for authentication and based on his UserId, and the role he belongs to you should receive all the permissions that User is entitled to.
You convert these permissions into claims and can send them back to UI and use it appropriately to show the features accordingly.
You also enforce same on the server side api to prevent any unauthorized access besides from your UI.

Rails: Auth Token in Full, Non-API App?

I'm building a rails app and I want to have token authentication but I don't want to build a separate API, I want it to be all integrated into one rails app.
Is this possible? Every single tutorial about token authentication I can find is about APIs, and every API seems to need to be its own standalone entity running in parallel with the main app.
Is what I'm asking impossible, or stupid? If not, how do I do it?
For "classical" web applications you want to use session based authentication instead of tokens.
Token based authentication is stateless and requires the token to be sent along with every request. This is done via HTTP headers or by placing it in the request body. Which is how you use API's.
For a classical web application there is simply no practical way to send the token along on GET requests.
Session based authentication instead works by using cookies to store the authentication claim (usually a user id). While you could use a token and store it in the session its just an overly convoluted solution since it defeats the whole purpose of token based auth.

Browser applications and auth tokens again

I've been reviewing how we should handle OAuth authentication in our browser application (SPA), and there's a whole bunch of articles out there that makes it all really confusing... I'm really missing something concrete and best practice guidance for a very simple setup.
We have this ASP.NET Web API 2 that's protected using tokens issued by IdSvr3. So far so good. Works with native clients and server apps.
Now to the browser stuff... Looking at a sample such as JavaScriptImplicitClient which uses the oidc-client-js library to retrieve tokens using the implicit flow. The token is stored in the browser which is accessible using JavaScript and there by open to XSS attacks.
In order to avoid that, suggestions indicates storing the token in a cookie and then setup a mechanism to prevent CSRF attacks.
Seems simple, but what sets that cookie?
Is it the IdSvr? Doesn't make sense since it's the API that needs the cookie.
Is it the API? During Implicit Flow login, are the user then redirected to the API which sets up the session and then redirects the user back to the SPA with a Set-Cookie header? Then the cookie will be present to the API on subsequent requests.
Third solution? Some is mentioning creating a second 'API' that proxies requests to the 'real' API, but sets the auth header.
Do you have any samples of such a setup, or can you maybe provide some hints about how you'd do it?
Personally, most of the times the avoidance of Web Storage for tokens due to XSS seems to be exacerbated a bit. There is one important question, if your application is vulnerable to XSS, will the impact of this vulnerability be significantly increased because you also leaked tokens or you already got totally pwned even if you didn't store tokens there and you're in the same type of trouble.
I made a comparison of the pros and cons of a few approaches to store access tokens in web browser application which you can check in this answer to a related question.
In the end each case ends up having their own specifics which may tip the balance between one approach versus the other (cookies or web storage). Just don't ignore any option from the start and look at all of them based on your requirements.
I bet that there are implementations out there that store them in HTTP-Only cookies to avoid the XSS issue with Web Storage and then end-up using a CSRF mitigation strategy that is vulnerable in the face of XSS.

In which cases do you need to implement these complex token authentication on devise (Rails 3.2)

I'm building a Rails app on Heroku.
I installed devise to manage user authentication on which I wanted to add "token authenticatable".
I basically used this tutorial and it works great
However, I ran across more complex tutorial about token authenticatable like these two ones:
http://matteomelani.wordpress.com/2011/10/17/authentication-for-mobile-devices/
http://mojoware.com/posts/mobile-rails-api-with-devise
I don't understand why they get much more complex than what I implemented? They seem to mention "mobile" stuff so does that mean it's a more complex way to use "token authenticatable" because it allows to authenticate in more cases of use such as on mobile?
Really in the dark so I appreciate any help.
For the most part, authentication in a (native) mobile app works pretty much the same way as authentication through a browser: the user gives his credentials, these are sent over the wire to the server/app, and the app responds by giving the user a 'token' representing an authenticated session.
The main differences: browser-based clients will generally submit said credentials using HTTP POST of an HTML form, using application/x-www-form-urlencoded. The returned token is usually given as a session cookie, which the browser presents with every subsequent HTTP request.
Native mobile clients, on the other hand, while functioning as the browser aren't restricted to the HTML way of doing things, and most of them don't use cookies.
The typical mobile client uses a Web service API. Most APIs are designed to be as stateless as possible (unlike browser/cookie-based sessions).
Most Web service APIs also need/want to be able to send & receive as much hierarchical, complex data as possible, using as little bandwidth as possible. Hence, they favor more compact representations of structured data such as JSON (or in some cases, BSON).
In most cases, as well, it is undesirable to present the authentication token as a URL query parameter (or, if you're sending over a JSON payload you might as well include the token in there).
For that reason, the stock Devise session controller and token authentication mechanism is inadequate, and hence numerous examples of how to provide alternative, REST-ful or JSON-based authentication that extends Devise.

Resources