Amplify-js: CookieStorage with httpOnly

Created on 5 May 2019  路  25Comments  路  Source: aws-amplify/amplify-js

* Which Category is your question related to? *
Auth

* What AWS Services are you utilizing? *
Cognito

* Provide additional details e.g. code snippets *
I'm using Amplify with my React app and would like to secure my API using JWTs (not using AWS API Gateway).

Is it possible to use Amplify Auth with CookieStorage and httpOnly? I'd like to prevent XSS with the httpOnly flag but looking at the interface for ICookieStorageData it looks like this isn't supported. Is it even possible to add support for this?

Alternatively what's the recommended authentication configuration/flow from a security perspective? I've seen the doc mention things like localStorage but from my understanding it's not secure from a XSS perspective.

Auth Security question

Most helpful comment

I would just like to say that this issue is one of the biggest reasons my company is considering the removal of Cognito from our stack (and not being able to set session expiration for less than a day). If there's anything I can do to elevate the priority of this issue, let me know because I'd love to avoid the pain of migrating away.

All 25 comments

Im very surprised this is the only issue in this repo I'm finding regarding the security of a web app using Amplify.

LocalStorage (which seems to be currently used) is definitely not secure from XSS attacks.

@andrewoh531 hi, you can use the cookieStorage in Amplify, please check the doc: https://aws-amplify.github.io/docs/js/authentication#manual-setup

@altin-selimi you can choose to use cookie or your own storage object to secure your tokens. Please check the doc: https://aws-amplify.github.io/docs/js/authentication#managing-security-tokens

@powerful23 - My question wasn't whether auth tokens could be stored in a cookie. It was whether httpOnly flag could be set on those cookies.

@andrewoh531 you can do that by setting secure to true:

cookieStorage: {
        // REQUIRED - Cookie domain (only required if cookieStorage is provided)
            domain: '.yourdomain.com',
        // OPTIONAL - Cookie path
            path: '/',
        // OPTIONAL - Cookie expiration in days
            expires: 365,
        // OPTIONAL - Cookie secure flag
        // Either true or false, indicating if the cookie transmission requires a secure protocol (https).
            secure: true
        },

@powerful23 secure and httpOnly are different. See this reference from Mozilla for reference:
```
A secure cookie is only sent to the server with an encrypted request over the HTTPS protocol. Even
with Secure, sensitive information should never be stored in cookies, as they are inherently insecure
and this flag can't offer real protection. Starting with Chrome 52 and Firefox 52, insecure sites
(http:) can't set cookies with the Secure directive.

To help mitigate cross-site scripting (XSS) attacks, HttpOnly cookies are inaccessible to
JavaScript's Document.cookie API; they are only sent to the server. For example, cookies that
persist server-side sessions don't need to be available to JavaScript, and the HttpOnly flag should
be set.```

@andrewoh531 Sorry about that. Seems like for now there is no way to use the CookieStorage in Amplify with httpOnly. As a workaround, You can implement your own storage object if you want to secure the tokens in a customized way.

Thanks for the response. In general is there a recommended and secure way of using Amplify? Aside from implementing my own storage, it seems as though the examples for using Amplify with Cognito aren't secure from XSS.

Just following up on this to see if there's a response. To be frank I'm not getting much confidence in how secure my application will if I were to use Amplify, so I'm strongly considering looking at alternatives like auth0.

@andrewoh531 yeah it seems rather disappointing having such a big vulnerability in your application from such a popular library. Its either auth0 or kicking user out to login screen everytime they do a refresh/visit app a second time (in-memory self implemented storage).

@andrewoh531 I did want to provide a little more information on HttpOnly

Not sure if you have seen this so wanted to provide this. Hope it helps!

Hi @sammartinez, I understand what httpOnly flag will do. My question is whether this is supported by aws-amplify.

I would just like to say that this issue is one of the biggest reasons my company is considering the removal of Cognito from our stack (and not being able to set session expiration for less than a day). If there's anything I can do to elevate the priority of this issue, let me know because I'd love to avoid the pain of migrating away.

Hmm...

Per my understanding, a JavaScript client cannot set an HTTPOnly cookie. Since Amplify is a client-side, JavaScript based solution, I don't see how the framework itself could provision an HTTPOnly cookie solution - without some server-side backing.

It seems one option may be to eliminate the client-side storage of tokens (by disabling cookie storage), and instead, following successful sign-in and return of the tokens (in-memory), transmit them to a back-end REST service which validates signatures and creates HTTPOnly cookies from the server-side. This should eliminate the need to retain them in XSS vulnerable areas on the client-side.

Drawbacks - I'm thinking token management (e.g. refresh tokens) would need to be handled from the server side... or at least, I haven't thought of a secure way to handle refreshing tokens from the client-side...

I would just like to say that this issue is one of the biggest reasons my company is considering the removal of Cognito from our stack (and not being able to set session expiration for less than a day). If there's anything I can do to elevate the priority of this issue, let me know because I'd love to avoid the pain of migrating away.

You can set the expiration for less than a day by using a fractional number. For example, by setting the timeout to .5, it will be set for 12 hours.

also curious as to how best to securely store sessions across subdomains. I've heard to use httponly cookies, but found no docs in amplify about it

I'm also looking forward this feature. Any news on this?

Any updates?

What I would really like is to use Amplify but instead of going directly to Cognito, it hits my webserver instead and I can then route the relevant calls to Cognito. This would allow me to use this great package, but still get the extra security of httpOnly cookies. Currently I am going to have to rewrite this SRP workflow in my own library. Hopefully I can copy/paste a lot of what amplify offers to accomplish this.

@rmclaughlin-nelnet how is your solution gonna work with Google Login for example? I am facing very same situation and it looks like I am migrating to Auth0 due this security hole. However your solution could work, but how about 3rd party IDP like Google or FB

My application will not support 3rd party IDP so I have not considered that situation. Do 3rd party IDP even support SRP? If not then you would just develop a separate login workflow for those.
https://docs.aws.amazon.com/cognito/latest/developerguide/google.html
https://docs.aws.amazon.com/cognito/latest/developerguide/facebook.html

Sad to see that this is still an open issue especially when Amazon pushing Amplify big time.

Also seems that AWS has removed mentions of CookieStorage from their documentation.

it would be possible if you implemented auth endpoints using your own lambdas. That would be a great alternative if easily wrapped in libraries. Pretty sure i've seen it implemented using cognito aws sdk/cdk for nextjs (IIRC) somewhere.

Hi everyone,

I looked into this as part of #5435 and, as others have correctly noted, httpOnly cannot be set on the client, but only from the server.

Because Amplify is aimed at frontend applications, we're restricted to what's available on the client-side. Others (https://github.com/aws-amplify/amplify-js/issues/3224#issuecomment-582552254) have had success with having a server between the app & Cognito for setting cookies.

What I found with localStorage vs document.cookie (in absence of httpOnly) is that both rely on the same mitigation steps, such as using modern frameworks and expiring access tokens sooner (we default to 1 hour).

I do want to caution those using a custom "cookie" adapter for credentials (https://docs.amplify.aws/lib/auth/manageusers/q/platform/js#managing-security-tokens) that there are real size constraints to be aware of (#5330). If there are enough claims, the token can grow large enough that you'll get 431s! This is another reason why localstorage is our default storage mechanism vs. cookies.

Thanks for the explanation
I was just wondering why Amazon.com themselves store the user access tokens in http-only cookies (assuming probably due to legacy reasons) - but even Facebook, Instagram, Google, Stripe, ... - all of them use http-only cookies to store user access tokens

As well - do understand, that HTTP-ONLY with "lax" do not protect you from XSS .. but also from the malicious frontend browser extensions or a malicious client-side library that the unaware FE developer might have installed (the way DENO protects the backend code)

There might be a disconnect between the amplify team and the cognito - but at the end of the day I thought this was an end-end secure solution

Was this page helpful?
0 / 5 - 0 ratings