On the surface, it seems like "token auth" is basically the same thing as traditional "cookie auth".
Token auth:
User submits username/password to API
API responds with access token
Client stores access token for identifying user in future requests
Cookie auth:
User submits username/password to API
API responds with cookie
Client stores cookie for identifying user in future requests
It seems that token auth is basically the same as cookie auth, except that most HTTP clients already know how to deal with managing cookies automatically, whereas you have to manually manage API tokens.
What am I missing? What are the benefits of using token auth? Is it really worth the extra effort?
Whether the extra effort is worth it, depends on what you are protecting and who is consuming the API.
Token based authentication is much easier when your clients are non-browser based. So if you're targetting mobile applications, token based authentication is worth considering.
But also in a browser scenario it has some advantages. As the browser does not automatically send the Authorization header, security token are not vulnerable to CSRF attacks.
If your web application lives on another domain than you API, cookies will not be sent because of the same-origin policy. Security tokens are not affected by this.
Related
When building SPA style applications using frameworks like Angular, Ember, React, etc. what do people believe to be some best practices for authentication and session management? I can think of a couple of ways of considering approaching the problem.
Treat it no differently than authentication with a regular web application assuming the API and and UI have the same origin domain.
This would likely involve having a session cookie, server side session storage and probably some session API endpoint that the authenticated web UI can hit to get current user information to help with personalization or possibly even determining roles/abilities on the client side. The server would still enforce rules protecting access to data of course, the UI would just use this information to customize the experience.
Treat it like any third-party client using a public API and authenticate with some sort of token system similar to OAuth. This token mechanism would used by the client UI to authenticate each and every request made to the server API.
I'm not really much of an expert here but #1 seems to be completely sufficient for the vast majority of cases, but I'd really like to hear some more experienced opinions.
This question has been addressed, in a slightly different form, at length, here:
RESTful Authentication
But this addresses it from the server-side. Let's look at this from the client-side. Before we do that, though, there's an important prelude:
Javascript Crypto is Hopeless
Matasano's article on this is famous, but the lessons contained therein are pretty important:
https://www.nccgroup.trust/us/about-us/newsroom-and-events/blog/2011/august/javascript-cryptography-considered-harmful/
To summarize:
A man-in-the-middle attack can trivially replace your crypto code with <script> function hash_algorithm(password){ lol_nope_send_it_to_me_instead(password); }</script>
A man-in-the-middle attack is trivial against a page that serves any resource over a non-SSL connection.
Once you have SSL, you're using real crypto anyways.
And to add a corollary of my own:
A successful XSS attack can result in an attacker executing code on your client's browser, even if you're using SSL - so even if you've got every hatch battened down, your browser crypto can still fail if your attacker finds a way to execute any javascript code on someone else's browser.
This renders a lot of RESTful authentication schemes impossible or silly if you're intending to use a JavaScript client. Let's look!
HTTP Basic Auth
First and foremost, HTTP Basic Auth. The simplest of schemes: simply pass a name and password with every request.
This, of course, absolutely requires SSL, because you're passing a Base64 (reversibly) encoded name and password with every request. Anybody listening on the line could extract username and password trivially. Most of the "Basic Auth is insecure" arguments come from a place of "Basic Auth over HTTP" which is an awful idea.
The browser provides baked-in HTTP Basic Auth support, but it is ugly as sin and you probably shouldn't use it for your app. The alternative, though, is to stash username and password in JavaScript.
This is the most RESTful solution. The server requires no knowledge of state whatsoever and authenticates every individual interaction with the user. Some REST enthusiasts (mostly strawmen) insist that maintaining any sort of state is heresy and will froth at the mouth if you think of any other authentication method. There are theoretical benefits to this sort of standards-compliance - it's supported by Apache out of the box - you could store your objects as files in folders protected by .htaccess files if your heart desired!
The problem? You are caching on the client-side a username and password. This gives evil.ru a better crack at it - even the most basic of XSS vulnerabilities could result in the client beaming his username and password to an evil server. You could try to alleviate this risk by hashing and salting the password, but remember: JavaScript Crypto is Hopeless. You could alleviate this risk by leaving it up to the Browser's Basic Auth support, but.. ugly as sin, as mentioned earlier.
HTTP Digest Auth
Is Digest authentication possible with jQuery?
A more "secure" auth, this is a request/response hash challenge. Except JavaScript Crypto is Hopeless, so it only works over SSL and you still have to cache the username and password on the client side, making it more complicated than HTTP Basic Auth but no more secure.
Query Authentication with Additional Signature Parameters.
Another more "secure" auth, where you encrypt your parameters with nonce and timing data (to protect against repeat and timing attacks) and send the. One of the best examples of this is the OAuth 1.0 protocol, which is, as far as I know, a pretty stonking way to implement authentication on a REST server.
https://www.rfc-editor.org/rfc/rfc5849
Oh, but there aren't any OAuth 1.0 clients for JavaScript. Why?
JavaScript Crypto is Hopeless, remember. JavaScript can't participate in OAuth 1.0 without SSL, and you still have to store the client's username and password locally - which puts this in the same category as Digest Auth - it's more complicated than HTTP Basic Auth but it's no more secure.
Token
The user sends a username and password, and in exchange gets a token that can be used to authenticate requests.
This is marginally more secure than HTTP Basic Auth, because as soon as the username/password transaction is complete you can discard the sensitive data. It's also less RESTful, as tokens constitute "state" and make the server implementation more complicated.
SSL Still
The rub though, is that you still have to send that initial username and password to get a token. Sensitive information still touches your compromisable JavaScript.
To protect your user's credentials, you still need to keep attackers out of your JavaScript, and you still need to send a username and password over the wire. SSL Required.
Token Expiry
It's common to enforce token policies like "hey, when this token has been around too long, discard it and make the user authenticate again." or "I'm pretty sure that the only IP address allowed to use this token is XXX.XXX.XXX.XXX". Many of these policies are pretty good ideas.
Firesheeping
However, using a token Without SSL is still vulnerable to an attack called 'sidejacking': http://codebutler.github.io/firesheep/
The attacker doesn't get your user's credentials, but they can still pretend to be your user, which can be pretty bad.
tl;dr: Sending unencrypted tokens over the wire means that attackers can easily nab those tokens and pretend to be your user. FireSheep is a program that makes this very easy.
A Separate, More Secure Zone
The larger the application that you're running, the harder it is to absolutely ensure that they won't be able to inject some code that changes how you process sensitive data. Do you absolutely trust your CDN? Your advertisers? Your own code base?
Common for credit card details and less common for username and password - some implementers keep 'sensitive data entry' on a separate page from the rest of their application, a page that can be tightly controlled and locked down as best as possible, preferably one that is difficult to phish users with.
Cookie (just means Token)
It is possible (and common) to put the authentication token in a cookie. This doesn't change any of the properties of auth with the token, it's more of a convenience thing. All of the previous arguments still apply.
Session (still just means Token)
Session Auth is just Token authentication, but with a few differences that make it seem like a slightly different thing:
Users start with an unauthenticated token.
The backend maintains a 'state' object that is tied to a user's token.
The token is provided in a cookie.
The application environment abstracts the details away from you.
Aside from that, though, it's no different from Token Auth, really.
This wanders even further from a RESTful implementation - with state objects you're going further and further down the path of plain ol' RPC on a stateful server.
OAuth 2.0
OAuth 2.0 looks at the problem of "How does Software A give Software B access to User X's data without Software B having access to User X's login credentials."
The implementation is very much just a standard way for a user to get a token, and then for a third party service to go "yep, this user and this token match, and you can get some of their data from us now."
Fundamentally, though, OAuth 2.0 is just a token protocol. It exhibits the same properties as other token protocols - you still need SSL to protect those tokens - it just changes up how those tokens are generated.
There are two ways that OAuth 2.0 can help you:
Providing Authentication/Information to Others
Getting Authentication/Information from Others
But when it comes down to it, you're just... using tokens.
Back to your question
So, the question that you're asking is "should I store my token in a cookie and have my environment's automatic session management take care of the details, or should I store my token in Javascript and handle those details myself?"
And the answer is: do whatever makes you happy.
The thing about automatic session management, though, is that there's a lot of magic happening behind the scenes for you. Often it's nicer to be in control of those details yourself.
I am 21 so SSL is yes
The other answer is: Use https for everything or brigands will steal your users' passwords and tokens.
You can increase security in authentication process by using JWT (JSON Web Tokens) and SSL/HTTPS.
The Basic Auth / Session ID can be stolen via:
MITM attack (Man-In-The-Middle) - without SSL/HTTPS
An intruder gaining access to a user's computer
XSS
By using JWT you're encrypting the user's authentication details and storing in the client, and sending it along with every request to the API, where the server/API validates the token. It can't be decrypted/read without the private key (which the server/API stores secretly) Read update.
The new (more secure) flow would be:
Login
User logs in and sends login credentials to API (over SSL/HTTPS)
API receives login credentials
If valid:
Register a new session in the database Read update
Encrypt User ID, Session ID, IP address, timestamp, etc. in a JWT with a private key.
API sends the JWT token back to the client (over SSL/HTTPS)
Client receives the JWT token and stores in localStorage/cookie
Every request to API
User sends a HTTP request to API (over SSL/HTTPS) with the stored JWT token in the HTTP header
API reads HTTP header and decrypts JWT token with its private key
API validates the JWT token, matches the IP address from the HTTP request with the one in the JWT token and checks if session has expired
If valid:
Return response with requested content
If invalid:
Throw exception (403 / 401)
Flag intrusion in the system
Send a warning email to the user.
Updated 30.07.15:
JWT payload/claims can actually be read without the private key (secret) and it's not secure to store it in localStorage. I'm sorry about these false statements. However they seem to be working on a JWE standard (JSON Web Encryption).
I implemented this by storing claims (userID, exp) in a JWT, signed it with a private key (secret) the API/backend only knows about and stored it as a secure HttpOnly cookie on the client. That way it cannot be read via XSS and cannot be manipulated, otherwise the JWT fails signature verification. Also by using a secure HttpOnly cookie, you're making sure that the cookie is sent only via HTTP requests (not accessible to script) and only sent via secure connection (HTTPS).
Updated 17.07.16:
JWTs are by nature stateless. That means they invalidate/expire themselves. By adding the SessionID in the token's claims you're making it stateful, because its validity doesn't now only depend on signature verification and expiry date, it also depends on the session state on the server. However the upside is you can invalidate tokens/sessions easily, which you couldn't before with stateless JWTs.
I would go for the second, the token system.
Did you know about ember-auth or ember-simple-auth? They both use the token based system, like ember-simple-auth states:
A lightweight and unobtrusive library for implementing token based
authentication in Ember.js applications.
http://ember-simple-auth.simplabs.com
They have session management, and are easy to plug into existing projects too.
There is also an Ember App Kit example version of ember-simple-auth: Working example of ember-app-kit using ember-simple-auth for OAuth2 authentication.
If I have an app and an api. If the app logs in through authorization server and sends the authorization: Bearer xxx header with each request, the api can verify the token locally.
When the user logs out (through the auth server), but the token has not yet expired if someone retrieves this token they will be able to make requests (if the authentication of the token is done locally on the server), is that correct? If thats the case, why is such a logout flow considered secure?
Edit: Clarifying the main question: why PKCE flow is considered secure if when a user logs out their access token is still valid (given we do local token verification)
BEHAVIOUR OVERVIEW
With OAuth there is a greater separation of concerns than in older standalone web apps:
You log into UIs
This is externalised to an Authorization Server
An access token is issued with a fixed / short lifetime
Access tokens are used as API message credentials
The access token can potentially be sent to other components and used from there
When you logout:
You remove tokens from your app
You redirect to tell the Authorization Server the user is no longer logged into any UI
This doesn't invalidate access tokens
TOKEN STORAGE
Tokens should be stored in private memory or protected storage so that attackers cannot access them easily. Your app then removes tokens as part of the logout process so that they are no longer available for attackers to try to access.
THREATS
The OAuth Threat Model has a section on stolen tokens, where it recommends the above storage and to keep tokens short lived. The most common industry default for an access token is 60 minutes.
The main risk of a malicious party stealing a token is via cross site scripting. XSS risks are not related to logout. Security testing should be performed regularly to ensure that XSS risks are mitigated.
BALANCE BETWEEN SECURITY AND PERFORMANCE
It may be possible for the UI to tell the Authorization Server that a token is revoked. However, the API would then need to call the Authorization Server on every API request to check for token revocation. This would lead to poor performance.
API ARCHITECTURE
I always aim to use Claims Caching and introspection in OAuth secured APIs, since it gives the actual API best control, along with good extensibility and performance.
With this in place, if you really wanted to make access tokens non usable after logout, without ruining performance, your UI could perform these actions as part of the logout process:
Revoke the access token at the Authorization Server (if supported)
Call APIs to ask them to remove cached claims for the access token
Okta /introspect can tell you if active is true or false, you could check that on every request if you are not slamming the API https://developer.okta.com/docs/reference/api/oidc/#introspect
It's hard to get access to the token, that's probably a good reason why it's not per definition insecure.
However, providing a logout option is a good idea. OAuth2 has a 'revoke' feature to make sure that tokens are revoked:
https://www.rfc-editor.org/rfc/rfc7009
Not every server supports this.
I have a new SPA with a stateless authentication model using JWT. I am often asked to refer OAuth for authentication flows like asking me to send 'Bearer tokens' for every request instead of a simple token header but I do think that OAuth is a lot more complex than a simple JWT based authentication. What are the main differences, should I make the JWT authentication behave like OAuth?
I am also using the JWT as my XSRF-TOKEN to prevent XSRF but I am being asked to keep them separate? Should I keep them separate? Any help here will be appreciated and might lead to a set of guidelines for the community.
TL;DR
If you have very simple scenarios, like a single client application, a single API then it might not pay off to go OAuth 2.0. On the other hand, if there are lots of different clients (browser-based, native mobile, server-side, etc) then sticking to OAuth 2.0 rules might make it more manageable than trying to roll your own system.
As stated in another answer, JWT (Learn JSON Web Tokens) is just a token format. It defines a compact and self-contained mechanism for transmitting data between parties in a way that can be verified and trusted because it is digitally signed. Additionally, the encoding rules of a JWT also make these tokens very easy to use within the context of HTTP.
Being self-contained (the actual token contains information about a given subject), they are also a good choice for implementing stateless authentication mechanisms (aka Look mum, no sessions!). When going this route, the only thing a party must present to be granted access to a protected resource is the token itself, and the token in question can be called a bearer token.
In practice, what you're doing can already be classified as bearer token -based. However, do consider you're not using bearer tokens as specified by the OAuth 2.0 related specs (see RFC 6750). That would imply relying on the Authorization HTTP header and using the Bearer authentication scheme.
Regarding the use of the JWT to prevent CSRF: Without knowing exact details it's difficult to ascertain the validity of that practice. To be honest, it does not seem correct and/or worthwhile. The following article (Cookies vs Tokens: The Definitive Guide) may be a useful read on this subject, particularly the XSS and XSRF Protection section.
One final piece of advice. Even if you don't need to go full OAuth 2.0, I would strongly recommend on passing your access token within the Authorization header instead of going with custom headers. If they are really bearer tokens, follow the rules of RFC 6750. If not, you can always create a custom authentication scheme and still use that header.
Authorization headers are recognized and specially treated by HTTP proxies and servers. Thus, the usage of such headers for sending access tokens to resource servers reduces the likelihood of leakage or unintended storage of authenticated requests in general, and especially Authorization headers.
(source: RFC 6819, section 5.4.1)
OAuth 2.0 defines a protocol, i.e. specifies how tokens are transferred, JWT defines a token format.
OAuth 2.0 and "JWT authentication" have similar appearance when it comes to the (2nd) stage where the Client presents the token to the Resource Server: the token is passed in a header.
But "JWT authentication" is not a standard and does not specify how the Client obtains the token in the first place (the 1st stage). That is where the perceived complexity of OAuth comes from: it also defines various ways in which the Client can obtain an access token from something that is called an Authorization Server.
So the real difference is that JWT is just a token format, OAuth 2.0 is a protocol (that may use a JWT as a token format).
Firstly, we have to differentiate JWT and OAuth. Basically, JWT is a token format. OAuth is an authorization protocol that can use JWT as a token. OAuth uses server-side and client-side storage. If you want to do real logout you must go with OAuth2. Authentication with JWT token can not logout actually. Because you don't have an Authentication Server that keeps track of tokens. If you want to provide an API to 3rd party clients, you must use OAuth2 also. OAuth2 is very flexible. JWT implementation is very easy and does not take long to implement. If your application needs this sort of flexibility, you should go with OAuth2. But if you don't need this use-case scenario, implementing OAuth2 is a waste of time.
XSRF token is always sent to the client in every response header. It does not matter if a CSRF token is sent in a JWT token or not, because the CSRF token is secured with itself. Therefore sending CSRF token in JWT is unnecessary.
JWT (JSON Web Tokens)- It is just a token format. JWT tokens are JSON encoded data structures contains information about issuer, subject (claims), expiration time etc. It is signed for tamper proof and authenticity and it can be encrypted to protect the token information using symmetric or asymmetric approach. JWT is simpler than SAML 1.1/2.0 and supported by all devices and it is more powerful than SWT(Simple Web Token).
OAuth2 - OAuth2 solve a problem that user wants to access the data using client software like browse based web apps, native mobile apps or desktop apps. OAuth2 is just for authorization, client software can be authorized to access the resources on-behalf of end user using access token.
OpenID Connect - OpenID Connect builds on top of OAuth2 and add authentication. OpenID Connect add some constraint to OAuth2 like UserInfo Endpoint, ID Token, discovery and dynamic registration of OpenID Connect providers and session management. JWT is the mandatory format for the token.
CSRF protection - You don't need implement the CSRF protection if you do not store token in the browser's cookie.
It looks like everybody who answered here missed the moot point of OAUTH
From Wikipedia
OAuth is an open standard for access delegation, commonly used as a way for Internet users to grant websites or applications access to their information on other websites but without giving them the passwords.[1] This mechanism is used by companies such as Google, Facebook, Microsoft and Twitter to permit the users to share information about their accounts with third party applications or websites.
The key point here is access delegation. Why would anyone create OAUTH when there is an id/pwd based authentication, backed by multifactored auth like OTPs and further can be secured by JWTs which are used to secure the access to the paths (like scopes in OAUTH) and set the expiry of the access
There's no point of using OAUTH if consumers access their resources(your end points) only through their trusted websites(or apps) which are your again hosted on your end points
You can go OAUTH authentication only if you are an OAUTH provider in the cases where the resource owners (users) want to access their(your) resources (end-points) via a third-party client(external app). And it is exactly created for the same purpose though you can abuse it in general
Another important note:
You're freely using the word authentication for JWT and OAUTH but neither provide the authentication mechanism. Yes one is a token mechanism and the other is protocol but once authenticated they are only used for authorization (access management). You've to back OAUTH either with OPENID type authentication or your own client credentials
find the main differences between JWT & OAuth
OAuth 2.0 defines a protocol & JWT defines a token format.
OAuth can use either JWT as a token format or access token which is a bearer token.
OpenID connect mostly use JWT as a token format.
JWT is an open standard that defines a compact and self-contained way for securely transmitting information between parties. It is an authentication protocol where we allow encoded claims (tokens) to be transferred between two parties (client and server) and the token is issued upon the identification of a client. With each subsequent request we send the token.
Whereas OAuth2 is an authorization framework, where it has a general procedures and setups defined by the framework. JWT can be used as a mechanism inside OAuth2.
You can read more on this here
OAuth or JWT? Which one to use and why?
Jwt is a strict set of instructions for the issuing and validating of signed access tokens. The tokens contain claims that are used by an app to limit access to a user
OAuth2 on the other hand is not a protocol, its a delegated authorization framework. think very detailed guideline, for letting users and applications authorize specific permissions to other applications in both private and public settings. OpenID Connect which sits on top of OAUTH2 gives you Authentication and Authorization.it details how multiple different roles, users in your system, server side apps like an API, and clients such as websites or native mobile apps, can authenticate with each othe
Note oauth2 can work with jwt , flexible implementation, extandable to different applications
JWT tokens require, at most, a one-time communication between the resource server and the authorization server at runtime. The
resource server needs to request the authorization server for the
public key to decrypt the JWT tokens. This can be done at resource
server startup. This can even be stored in the resource server in a
properties file avoiding the query at all.
OAuth2 solve a problem that user wants to access the data using client software like browser-based web apps, native mobile apps, or
desktop apps. OAuth2 is just for authorization, client software can
be authorized to access the resources on behalf of end-user using an
access token.
OAuth2 can be used with JWT tokens or access token which is a bearer
token.
We're looking to implement web (external user) SSO and an API gateway to support web apps and mobile apps, and potentially 3rd party apps and even B2B scenarios.
My thought is to have the SSO gateway handle user-level access to websites and APIs, authenticating end users using OAuth or OpenID Connect.
Sitting behind this, for any API URLs, is the API gateway. This is intended to handle the client-/application-level authentication using something like a client ID and secret.
The idea would be that the user would log into a website or mobile app, and then if/when that app needed to call an API it would need to send its own credentials (client credentials flow) as well as a bearer token proving who the user is as well (resource owner password flow).
The client credentials are less about security and more about coarse-grained access to API functions, giving visibility of API usage, traffic shaping, SLAs etc., but the user identity is needed to enforce data-level authorisation downstream.
Most API gateways I've looked at appear to only support a single level of authentication, e.g. we're looking at Apigee at the moment that can use OAuth to authentication to handle either a user or an app, but it's not obvious how to do both at once.
Is there any way to get the SSO gateway's user bearer token to play nicely with the API gateway's client bearer token or credentials, preferably in a fairly standards-based way? Or do we just have to hack it so that one comes through in the auth header and the other in the payload? Or is there a way to have a combined approach (e.g. hybrid bearer token) that can serve both purposes at once?
I'm kind of surprised that with all the work going on in identity management (OAuth2, OpenID Connect, UMA, etc.) nobody is looking at a way of handling simultaneously the multiple levels of authentication - user, client, device, etc.
Unfortunately I don't have enough reputation points to comment on the previous post, so I'll add my two cents here. Full disclosure: I work for Apigee.
http://apigee.com/docs/api-services/content/oauthv2-policy#accesstokenelement explains how to give the access token to the Apigee OAuthV2 policy in a place other than the Authorization header. If you've stored the SSO bearer token as an attribute of the Apigee OAuth token then once the Apigee token is validated you'll automatically get the SSO bearer token as a flow variable and can use it as needed.
For example, if you send the token as a "token" query parameter on the request you can code the following in the OAuthV2 policy
request.queryparam.token
and the policy will pull it from that query parameter.
A lot of APIs use token auth for authentication and authorization. I thought the original use of token auth schemes were that cookies were intended for browsers and that you could not guarantee that your API consumer would be a browser.
But then when you think about, cookies are almost exactly the same as many token auth schemes that people invent, except that cookies are supported and understood by every web framework out there and have most of the features of token auth, such as expiration dates. Cookies just have a "Cookie:" and "Set-Cookie:" header instead of the usual X-Auth-Token. Why do so many API implementers go out of their way to re-invent the wheel?
Why not make API clients conform to cookie usage (since they will have to learn your token auth scheme anyway)?