Angularjs $ http não parece entender “Set-Cookie” na resposta

Eu tenho uma API REST de nodejs express com o módulo Passport para autenticação. Um método de login (GET) retorna um cookie no header. Quando eu o chamo do Chrome ele funciona bem, meu cookie é definido no meu navegador.

Mas se eu chamá-lo através de $ http do Angularjs, o cookie não está definido.

Set-Cookie:connect.sid=s%3Ad7cZf3DSnz-IbLA_eNjQr-YR.R%2FytSJyd9cEhX%2BTBkmAQ6WFcEHAuPJjdXk3oq3YyFfI; Path=/; HttpOnly 

Como você pode ver acima, o Set-Cookie está presente no header da resposta do serviço http.

Talvez o HttpOnly possa ser a fonte desse problema? Se sim, como posso mudar isso? Aqui está minha configuração expressa:

 app.configure(function () { app.use(allowCrossDomain); app.use(express.bodyParser()); app.use(express.cookieParser()) app.use(express.session({ secret: 'this is a secret' })); app.use(flash()); //passport init app.use(passport.initialize()); app.use(passport.session()); app.set('port', process.env.PORT || 8080); }); 

obrigado pela ajuda

Certifique-se de configurar sua solicitação $ http para usar credenciais. Da documentação do XHR:

https://developer.mozilla.org/pt-BR/docs/HTTP/Access_control_CORS

O recurso mais interessante exposto tanto pelo XMLHttpRequest quanto pelo Access Control é a capacidade de fazer solicitações “credenciadas” que tenham conhecimento de cookies HTTP e informações de autenticação HTTP. Por padrão, nas chamadas XMLHttpRequest entre sites, os navegadores não enviam credenciais. Um sinalizador específico deve ser definido no object XMLHttpRequest quando ele é invocado.

Você pode usar o object options para definir o uso de credenciais, consulte

http://docs.angularjs.org/api/ng.$http

Exemplo:

 $http({withCredentials: true, ...}).get(...) 

Como você está verificando a existência do cookie?

$http é apenas um invólucro em torno do XHR do navegador, assim como o $.ajax e os amigos do jQuery. Isso significa que seu navegador manipulará os cookies normalmente.

Meu palpite é que o cookie está sendo definido, mas você está tentando lê-lo através do document.cookie . HttpOnly impede que o script tenha access ao cookie. Isto é uma coisa boa.

HttpOnly ajuda a mitigar contra ataques XSS. Isso torna impossível que um script mal-intencionado roube o token de session de um usuário (e, portanto, seu login). Não desligue o HttpOnly .

Você não deve precisar do cookie de qualquer maneira. Como $http é apenas um wrapper em torno do XHR, o navegador enviará automaticamente o cookie na próxima vez que você fizer uma solicitação. Você pode verificar isso observando as solicitações no painel de Rede das Ferramentas do Desenvolvedor.

Eu resolvi o problema definindo {withCredential : true} no pedido $http angular e definindo:

 res.header("Access-Control-Allow-Credentials", true); 

na minha configuração do servidor expresso. Ao fazer isso, meu cookie aparece bem na minha lista de cookies do navegador.

Você pode alterá-lo configurando express.session :

 app.use(express.session({ secret : 'this is a secret', cookie : { httpOnly : false, maxAge : XXX // see text } }); 

Mas eu não acho que o Angular se preocupa muito com cookies, esses são manipulados pelo navegador (e eu concordo com o @josh3736 que você deve manter o httpOnly como true ).

Pode ter algo a ver com seus cookies sendo cookies de session (navegador). Você pode tentar e ver se funciona melhor definindo explicitamente um maxAge para o cookie (em milissegundos).