Skip to content
This repository has been archived by the owner on Mar 22, 2022. It is now read-only.

jwt cookie is not set after the correct authentication #514

Closed
PavelPolyakov opened this issue May 20, 2017 · 14 comments
Closed

jwt cookie is not set after the correct authentication #514

PavelPolyakov opened this issue May 20, 2017 · 14 comments

Comments

@PavelPolyakov
Copy link

Steps to reproduce

https://github.com/PavelPolyakov/feathers-authentication-cookie-bug

The reproduction repo is based on the simple generated app. The only thing to highlight is that I've packed https://github.com/feathersjs/feathers-authentication-client and put it as auth.bundle.js, as it's not possible to include it from the CDN.

In order to reproduce:

  1. run the app
  2. visit the index page, check in the console that we logged in
  3. check in the developer tools, that there is no feathers-jwt cookie
  4. in case you need a clean test - restart the app

Expected behavior

It is stated in the documentation:
https://docs.feathersjs.com/api/authentication/server.html#default-options

That in case we enable cookie, then the appropriate cookie would be set after the successful authentication.

Actual behavior

The cookie is not there.

System configuration

nothing special

Module versions (especially the part that's not working):
feathers-client 2.2.0
feathers-authentication-client 0.3.2

NodeJS version:
v6.3.1

Operating System:
Mac OS

Browser Version:
latest Chrome

React Native Version:

Module Loader:

Please, let me know if it's a bug. Seems that the same behaviour is mentioned here: #389 , however, there the main topic is react native.

Regards,

@snewell92
Copy link

snewell92 commented Jul 10, 2017

While using the feather's client, I've got authentication returning a token and even storing the token in localStorage, but it doesn't set the cookie. Thus subsequent redirects won't be authenticated.

I've looked at trying to have middleware set the cookie after the auth service authenticates but I don't think that works anymore, and I don't want to expose cookies to all my hooks, I just would like the authentication after hook to set the jwt-cookie cookie value so my express routes can authenticate with an http only cookie.

@snewell92
Copy link

In the chrome debug inspector, after the client authenticate I get this response back

setcookieheaderset

This is in the then right after I authenticate. So... does the server assume it can defer setting the cookie on the client? Even though it is an http only cookie? (which can't be set by the client)

@snewell92
Copy link

It's worth noting too, that localStorage works as expected. In my client I set localStorage, but I still am expecting the cookie to be set, since the server still has the cookie options enabled.

@snewell92
Copy link

This is odd... I see two set-cookies, and in the cookies tab there are two jwt-cookies...
twocookies

@snewell92
Copy link

snewell92 commented Jul 10, 2017

Well, for my issue I think res.clearCookie is adding that blank cookie. I put console log statements in set-cookies.js and printed out res._headers before clear cookie, after clear cookie, and after res.cookie invocations.

Excerpt from debugging session

debug

Code changes in set-cookie.js starting on line 49 of the file in my node_modules folder (feathers-authentication v1.2.6)

if (res.data && res.data.accessToken) {
  // Clear out any old cookie since we are creating a new one
  console.log('all resp headers\n\n****\n' + JSON.stringify(res._headers) + "\n****\n");
  debug('Clearing old \'' + cookie + '\' cookie');
  console.log('clearing cookie...\n\n');
  res.clearCookie(cookie);
  console.log('all resp headers\n\n****\n' + JSON.stringify(res._headers) + "\n****\n");

  // Check HTTPS and cookie status in production.
  if (!req.secure && app.get('env') === 'production' && options.secure) {
    console.warn('WARN: Request isn\'t served through HTTPS: JWT in the cookie is exposed.');
    console.info('If you are behind a proxy (e.g. NGINX) you can:');
    console.info('- trust it: http://expressjs.com/en/guide/behind-proxies.html');
    console.info('- set cookie[\'' + cookie + '\'].secure false');
  }

  // If a custom expiry wasn't passed then set the expiration
  // to be that of the JWT expiration or the maxAge option if provided.
  if (options.expires === undefined) {
    if (options.maxAge) {
      options.expires = makeExpiry(options.maxAge);
    } else if (authOptions.jwt.expiresIn) {
      options.expires = makeExpiry(authOptions.jwt.expiresIn);
    }
  }

  // Ensure that if a custom expiration was passed it is a valid date
  if (options.expires && !(options.expires instanceof Date)) {
    return next(new Error('cookie.expires must be a valid Date object'));
  }

  // remove some of our options that don't apply to express cookie creation
  // as well as the maxAge because we have set an explicit expiry.
  var cookieOptions = (0, _lodash2.default)(options, 'name', 'enabled', 'maxAge');

  debug('Setting \'' + cookie + '\' cookie with options', cookieOptions);
  res.cookie(cookie, res.data.accessToken, cookieOptions);
  console.log('setting cookie...\n\n');
  console.log('all resp headers\n\n****\n' + JSON.stringify(res._headers) + "\n****\n");
}

And output:

all resp headers                                                                                                                                                                                                     
                                                                                                                                                                                                                     
****                                                                                                                                                                                                                 
{"access-control-allow-origin":"*","x-dns-prefetch-control":"off","x-frame-options":"SAMEORIGIN","x-download-options":"noopen","x-content-type-options":"nosniff","x-xss-protection":"1; mode=block","allow":"POST,DE
LETE"}                                                                                                                                                                                                               
****                                                                                                                                                                                                                 
                                                                                                                                                                                                                     
clearing cookie...                                                                                                                                                                                                   
                                                                                                                                                                                                                     
                                                                                                                                                                                                                     
all resp headers                                                                                                                                                                                                     
                                                                                                                                                                                                                     
****                                                                                                                                                                                                                 
{"access-control-allow-origin":"*","x-dns-prefetch-control":"off","x-frame-options":"SAMEORIGIN","x-download-options":"noopen","x-content-type-options":"nosniff","x-xss-protection":"1; mode=block","allow":"POST,DE
LETE","set-cookie":"jwt=; Path=/; Expires=Thu, 01 Jan 1970 00:00:00 GMT"}                                                                                                                                            
****                                                                                                                                                                                                                 
                                                                                                                                                                                                                     
setting cookie...                                                                                                                                                                                                    
                                                                                                                                                                                                                     
                                                                                                                                                                                                                     
all resp headers                                                                                                                                                                                                     
                                                                                                                                                                                                                     
****                                                                                                                                                                                                                 
{"access-control-allow-origin":"*","x-dns-prefetch-control":"off","x-frame-options":"SAMEORIGIN","x-download-options":"noopen","x-content-type-options":"nosniff","x-xss-protection":"1; mode=block","allow":"POST,DE
LETE","set-cookie":["jwt=; Path=/; Expires=Thu, 01 Jan 1970 00:00:00 GMT","jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6ImFjY2VzcyIsInR5cGUiOiJhY2Nlc3MifQ.eyJ1c2VybmFtZSI6ImFkbWluIiwiZmlyc3RuYW1lIjoiQWxleGFuZGVyIiwibGFzdG5hbWU
iOiJIYW1pbHRvbiIsImVtYWlsIjoidGVzdF90ZXN0MTIzQHRlc3QuY29tIiwiaWF0IjoxNDk5NzIxNDM2LCJleHAiOjE0OTk4MDc4MzYsImF1ZCI6ImxvY2FsaG9zdCIsImlzcyI6ImZlYXRoZXJzIiwic3ViIjoiYW5vbnltb3VzIn0.4frbiUi9RJWvAwnXvc4Cq8_X6o0rJOnEKhX5
UMSB7JA; Path=/; Expires=Tue, 11 Jul 2017 21:17:16 GMT; HttpOnly"]}
****

Edit - I commented out the clearCookie and the cookies just aren't being set at all... So the headers are set but in chrome the cookies aren't persisting. Pretty sure I'm not in incognito or anything - so weird!

@kernwig
Copy link

kernwig commented Jan 14, 2018

Suddenly I'm running into this too with feathers 2.2.4 / feathers-authentication-hooks@0.1.6 / feathers-client 2.4.0.

Cookie is both set and cleared by the server response.

image

@metamas
Copy link

metamas commented Mar 4, 2018

I set up a protected route as outlined in docs.feathersjs.com/guides/auth/recipe.express-middleware.html, and am experiencing the same lack of cookie storage. Auth flow withfeather-jwt in localStorage still works fine, but even with that present on the client a user can't access the protected route when there is no feathers-jwt cookie to parse.

@green3g
Copy link

green3g commented Mar 27, 2018

I am also seeing duplicate Set-Cookie headers. One is empty, so is it possible that this is interfering with the cookie that is set? Chrome doesn't show a cookie in Application -> Cookies.

Version info:

    "@feathersjs/authentication": "^2.1.3",
    "@feathersjs/authentication-jwt": "^2.0.0",
    "@feathersjs/authentication-local": "^1.1.1",
    "@feathersjs/configuration": "^1.0.2",
    "@feathersjs/errors": "^3.3.0",
    "@feathersjs/express": "^1.2.0",
    "@feathersjs/feathers": "^3.1.3",

Cookie headers:

Set-Cookie: feathers-jwt=lots.of.cookie.jwt.content.stuff; Path=/; Expires=Wed, 28 Mar 2018 16:35:14 GMT
Set-Cookie: feathers-jwt=; Path=/; Expires=Thu, 01 Jan 1970 00:00:00 GMT

Edit:

It looks like this extra header is getting set here: https://github.com/feathersjs/authentication/blame/master/lib/express/set-cookie.js#L33

@sebastiangrebe
Copy link

I experienced the same problem.
I was using isomorphic-unfetch as fetch client.

const fetch = require('isomorphic-unfetch');
const app = feathers(); 
 
export default app 
  .configure(rest().fetch(fetch))  

I switched to axios and the cookie was saved without any problems.

const axios = require('axios');
const app = feathers();

export default app
  .configure(rest().axios(axios))

@artbelikov
Copy link

Same here. Two Set-Cookie headers. One is normal and one is empty.

@rxb
Copy link

rxb commented Oct 10, 2018

Did anyone discover any workarounds in the meantime?

@joelklint
Copy link

I am experiencing this issue too. Seems like feathers are phasing out cookies altogether though. feathersjs/feathers#1045. @rxb

@r3gisc
Copy link

r3gisc commented Feb 5, 2019

I had a similar issue: cookie for feathers-jwt was in the Header (even 2 of it: one is perhaps set to clear the other - see @feathers/authentication/lib/express/set-cookie), and none was stored in the browser on production ... But it was working for me ... on dev server only !

Finaly i found the problem came from cookie's domain (to be precise: subdomain) set by feathers/auth

On dev server everything was fine because node and front server was sharing the exact same domain:
front: sub.domain.com:443
node: sub.domain.com:8443

But in production subdomains were differents:
front: app.domain.com:443
node: srv.domain.com:8443

@feathers/authentication may have set the cookie's domain to srv.domain.com or none (not totally sure).

My theory is that app.domain.com was then not allowed by the browser to store it.

Anyway, after trying different workarounds if found the simplest ... that is not documented in feathers doc :

Add a 'domain' option in node config for authentication.cookie key:

     authentication:{
            cookie: {
                enabled: true,
                name: conf.cookies.auth,
                httpOnly: false,
                secure: true,
                domain: 'domain.com'  // <====  
                     // or domain: 'app.domain.com' in my case 
                     // (i had issues with config loader and "dot" '.domain.com')
                     // this option is not documented but is passed trough to res.cookie(
            },
       }

Pull request for doc

@r3gisc r3gisc mentioned this issue Feb 5, 2019
@daffl
Copy link
Member

daffl commented May 8, 2019

oAuth has been changed significantly in Feathers v4 authentication and does no loner use cookies to transmit the token.

Please see the migration guide for more information. Closing this issue in order to archive this repository. Related issues can be opened at the new code location in the Feathers main repository.

@daffl daffl closed this as completed May 8, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests