ChatGPT解决这个技术问题 Extra ChatGPT

JWT vs cookies for token-based authentication

I read some posts about "JWT vs Cookie" but they only made me more confused...

I want some clarification, when people talking about "token-based authentication vs cookies", cookies here merely refer to session cookies? My understanding is that cookie is like a medium, it can be used to implement a token-based authentication(store something that can identify logged-in user on the client side) or a session-based authentication(store a constant on the client side that matches session information on the server side) Why do we need JSON web token? I was using the standard cookie to implement token-based authentication(not using session id, not use server memory or file storage): Set-Cookie: user=innocent; preferred-color=azure, and the only difference that I observed is that JWT contains both payload and signature...whereas you can choose between signed or plaintext cookie for http header. In my opinion signed cookie (cookie:'time=s%3A1464743488946.WvSJxbCspOG3aiGi4zCMMR9yBdvS%2B6Ob2f3OG6%2FYCJM') is more space efficient, the only drawback is that client cannot read the token, only the server can...but I think it's fine because just like claim in JWT is optional, it's not necessary for token to be meaningful


M
MvdD

The biggest difference between bearer tokens and cookies is that the browser will automatically send cookies, where bearer tokens need to be added explicitly to the HTTP request.

This feature makes cookies a good way to secure websites, where a user logs in and navigates between pages using links.

The browser automatically sending cookies also has a big downside, which is CSRF attacks. In a CSRF attack, a malicious website takes advantage of the fact that your browser will automatically attach authentication cookies to requests to that domain and tricks your browser into executing a request.

Suppose the web site at https://www.example.com allows authenticated users to change their passwords by POST-ing the new password to https://www.example.com/changepassword without requiring the username or old password to be posted.

If you are still logged in to that website when you visit a malicious website which loads a page in your browser that triggers a POST to that address, your browser will faithfully attach the authentication cookies, allowing the attacker to change your password.

Cookies can also be used to protect web services, but nowadays bearer tokens are used most often. If you use cookies to protect your web service, that service needs to live on the domain for which the authentication cookies are set, as the same-origin policy won't send cookies to another domain.

Also, cookies make it more difficult for non-browser based applications (like mobile to tablet apps) to consume your API.


"If you are still logged in to that website when you visit a malicious website which loads a page in your browser that triggers a POST to that address, your browser will faithfully attach the authentication cookies, allowing the attacker to change your password." Doesn't CORS prevent this?
@kbuilds Only is the malicious page is using AJAX to POST the form. If the attacker gets you to click the submit button on a regular form, CORS does not come into play.
but doesn't this mean that the site would only be vulnerable if there were no CSRF tokens being used?
Right, you can mitigate CSRF attacks by using CSRF tokens. But this is something you have to do explicitly.
It's worthwhile to mention that the Set-Cookie's SameSite attribute can effectively prevent CSRF attacks. developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/… And since browsers now use SameSite=Lax as a default value and if you do not make changes on GET requests, you are protected by default. However only in case of modern browsers. SameSite=Strict is even a more robust variant. A good article to read: netsparker.com/blog/web-security/…
C
Community

Overview

What you're asking for is the difference between cookies and bearer tokens for sending JSON Web Tokens (JWTs) from the client to the server.

Both cookies and bearer tokens send data.

One difference is that cookies are for sending and storing arbitrary data, whereas bearer tokens are specifically for sending authorization data.

That data is often encoded as a JWT.

Cookie

A cookie is a name-value pair, that is stored in a web browser, and that has an expiry date and associated domain.

We store cookies in a web browser either with JavaScript or with an HTTP Response header.

document.cookie = 'my_cookie_name=my_cookie_value'   // JavaScript
Set-Cookie: my_cookie_name=my_cookie_value           // HTTP Response Header

The web browser automatically sends cookies with every request to the cookie's domain.

GET http://www.bigfont.ca
Cookie: my_cookie_name=my_cookie_value               // HTTP Request Header

Bearer Token

A bearer token is a value that goes into the Authorization header of any HTTP Request. It is not automatically stored anywhere, it has no expiry date, and no associated domain. It's just a value. We manually store that value in our clients and manually add that value to the HTTP Authorization header.

GET http://www.bigfont.ca
Authorization: Bearer my_bearer_token_value          // HTTP Request Header

JWT and Token Based Authentication

When we do token-based authentication, such as OpenID, OAuth, or OpenID Connect, we receive an access_token (and sometimes id_token) from a trusted authority. Usually we want to store it and send it along with HTTP Requests for protected resources. How do we do that?

Option 1 is to store the token(s) in a cookie. This handles storage and also automatically sends the token(s) to the server in the Cookie header of each request. The server then parses the cookie, checks the token(s), and responds accordingly.

Option 2 is to store the token in local/session storage, and then manually set the Authorization header of each request. In this case, the server reads the header and proceeds just like with a cookie.

It's worth reading the linked RFCs to learn more.


is it safe to store sensitive data into local/session storage? or it's just whatever since tokens are ephemeral?
Once the app server receives the ID token (which contains claims), then does it send that token to the browser? So that subsequent api calla can pass that id token to allow app server to know who has invoked the endpoint.
In Option 2 is session storage not the same as cookie? What does session storage refer to?
@Gezim One important difference: the browser automatically sends cookies with all requests to their domain; the browser does not do that with session storage. Another important, related difference: many browsers block cookies to avoid tracking; the browsers tend not to block session/local storage, because they have less use for tracking.
k
kag0

In addition to what MvdD has said about cookies being automatically sent:

A cookie can be a medium, but its most significant function is how it interacts with the browser. Cookies are set by the server and sent in requests in very specific ways. JWT on the other hand is exclusively a medium, it is an assertion of some facts in a particular structure. If you were so inclined, you could put a JWT as your authentication cookie. When you read articles comparing them, they typically are talking about using a JWT sent as a bearer token by front end code vs an authentication cookie which corresponds to some cached session or user data on the back end. JWT offers many features, and puts them in a standard so they can be used between parties. A JWT can act as a signed assertion of some facts in many different places. A cookie, no matter what data you put in it or if you sign it, only really makes sense to use between a browser and a specific back end. JWT can be used from browser to back end, between back ends controlled by different parties (OpenId Connect is an example), or within back end services of one party. Regarding your specific example of your signed cookies, you can probably achieve the same functions ("not using session id, not use server memory or file storage") as JWT in that use case, but you lose out on libraries and peer-review of the standard, in addition to the CSRF issues talked about in the other answer.

In summary: the posts you're reading are probably comparing JWT as a bearer token to authentication cookie for browser to server authentication purposes. But JWT can do much more, it brings in standardization and features for use outside the use case you're probably thinking of.


Good job clarifying that the comparison is really between Bearer tokens and cookies.
P
Pang

While cookies can increase the risk of CSRF attacks by virtue of them being sent automatically along with requests, they can decrease the risk of XSS attacks when the HttpOnly flag is set, because any script that is injected into the page won't be able to read the cookie.

CSRF: a user clicks on a link (or views images) on an attacker's site, which causes the browser to send a request to the victim's site. If the victim uses cookies, the browser will automatically include the cookie in the request, and if the GET request can cause any non-read-only actions, the victim site is vulnerable to the attack.

XSS: an attacker embeds a script in the victim site (the victim site is only vulnerable if inputs are not sanitized correctly), and the attacker's script can do anything JavaScript is allowed to do on the page. If you store JWT tokens in local storage, the attacker's script could read those tokens, and also send those tokens to a server they control. If you use cookies with the HttpOnly flag, the attacker's script won't be able to read your cookie to begin with. That said, the script they successfully injected will still be able to do anything JavaScript can do, so you're still hosed IMO (i.e., while they may not be able to read the cookie to send it off to their own server for use later, they can send requests to the victim site using XHR, which will include the cookie anyway).


is there any solution to not allow the attacker get your JWT through localStorage or by sending a cookie with JWT in itself?
@DignityDignity You can store a JWT in localstorage or a cookie (as mentioned here); my answer is just to mention that cookie vs bearer token is a trade off (cookies can be more secure in one sense, and less secure in another)
CSRF is almost impossible because the default value of sameSite is lax.
B
Batman Rises

Ref - Need for JSON Web Token

Cookies

https://i.stack.imgur.com/fvrwn.png

Drawbacks of Cookies

Cookies/session id is not self contained. It is a reference token. During each validation the Gmail server needs to fetch the information corresponding to it.

Not suitable for microservices architecture involving multiple API's and servers

https://i.stack.imgur.com/kayrh.png

JWT

JWT is self contained. It is a value token. So during each validation the Gmail server does not needs to fetch the information corresponding to it.

It is digitally signed so if any one modifies it the server will know about it

It is most suitable for Microservices Architecture

It has other advantages like specifying the expiration time.

https://i.stack.imgur.com/sQXBZ.png


If the user clicks “log me out of all sessions”, then with each request the token must be validated by a database call - so the idea that it is self-contained doesn’t hold. Short expiries might help but it’s not perfect.