hapijs / bell

Third-party login plugin for hapi
Other
624 stars 210 forks source link

Can't reliably authenticate (Safari+Auth0) #272

Closed garthk closed 7 years ago

garthk commented 7 years ago

Seems to be #191, but I'm on bell 8.3.0 and using Safari 10.0 on macOS 10.12.

Short stack:

161010/233309.984, [error] message: Missing auth0 request token cookie stack: Error: Missing auth0 request token cookie
    at Object.internals.refreshRedirect (/opt/anditi-roof-api/node_modules/bell/lib/oauth.js:318:27)
    at Object.authenticate (/opt/anditi-roof-api/node_modules/bell/lib/oauth.js:204:30)

bell plugin options, piped through my auth plugin and rejoice:

{
    "provider": "auth0",
    "config": {
        "domain": "$env.AUTH0_DOMAIN"
    },
    "ttl": 3600,
    "password": "$env.AUTH0_COOKIE_PASSWORD",
    "clientId": "$env.AUTH0_CLIENT_ID",
    "clientSecret": "$env.AUTH0_CLIENT_SECRET",
    "isSecure": true,
    "location": "$env.HAPI_URI"
}

If options.isSecure is true:

If options.isSecure is false:

garthk commented 7 years ago

This is close to reproducing the problem with the temporary auth0 client of your choice, but I'm getting Missing auth0 request token cookie stack even with isSecure false, and on Chrome:

// demo.js

'use strict';

const hapi = require('hapi');
const server = new hapi.Server();

server.connection({
    port: 30303,
    address: '127.0.0.1',
    uri: 'https://localhost:30303',
    tls: {
        key: '-----BEGIN RSA PRIVATE KEY-----\nMIICWwIBAAKBgQCsCmJo0uWqnmZ80GwCuB5oqsM8q0ruXyFrTm+sK/oUO1KegplE0fWq189P\nqzmRG+hWl7X8rEFGeKkuse4ljnIjupZgy0n/LQcdeeatrrDA6kLRslKl8XyNKvPhwp+ZLRYL\nKcJmTOJEzwWRsxH/WpHgXq8P0bcN+Up16Q7JKj6muQIDAQABAoGAPjbzJ5082Nq3jWOB6+nR\ndWBrgkEfs9xLJZcT41tz8GUTl6b67lxPTx0EJ3dwNf21o7rxYRKZ+HYiGHTX/lTpCVHcARu7\n9DxyA/DHrZYm3VYQQW9hnwbbjMeGL6CZKNAT57hX3KKEfGtdFBYRqYEgjneN86UW6YZcTcQh\nHYHhHgECQQDrwEMsVyWfP9iRFex55SvxopnclQ2m/VNzJE9JuyoAt7yrzqWJkmbyC2OBFA/s\nuTGz3jJFCtUJTbiKBHmHzjkJAkEAutE+lyjx6wmWXf8L+jO3OWAl3WX9IWEoUNEuEqgaNymN\nqFet/EohswzwKNs+ru/NYtQzdHMIGZ5rA7aaFzLcMQJATMaFWchbwTwKrF1GcQAYSo4Yq4SD\nOLHhXmshwzJH4In10MHwmRfrnMHmut+su/wn2prvJhr7/BaqlZAVgAvB+QJAEvb88KFydZbC\nkgY7NAod9pAhJ+mbmdDgI9woXjJ8fs8UF1vXSL5Jz4BnvO4M3ftwETFTi+XFk7w2Ruk5mVNL\ncQJAYG3+kVoaw/k+8N5W8HIfovshqxPLXpErxKuyv/2TNoubqTDQHzlzy9Fc67Ah+0uEpQ1W\nJgma7/FPm9dEYZneyw==\n-----END RSA PRIVATE KEY-----\n\n',
        cert: '-----BEGIN CERTIFICATE-----\nMIIC5DCCAk2gAwIBAgIBATANBgkqhkiG9w0BAQsFADBoMRIwEAYDVQQDEwlsb2NhbGhvc3Qx\nCzAJBgNVBAYTAkFVMQwwCgYDVQQIEwNOU1cxEDAOBgNVBAcTB1RlcmFsYmExDzANBgNVBAoT\nBkFuZGl0aTEUMBIGA1UECxMLRGV2ZWxvcG1lbnQwHhcNMTYxMDEwMjM1MTQzWhcNMTcxMDEw\nMjM1MTQzWjBoMRIwEAYDVQQDEwlsb2NhbGhvc3QxCzAJBgNVBAYTAkFVMQwwCgYDVQQIEwNO\nU1cxEDAOBgNVBAcTB1RlcmFsYmExDzANBgNVBAoTBkFuZGl0aTEUMBIGA1UECxMLRGV2ZWxv\ncG1lbnQwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAKwKYmjS5aqeZnzQbAK4Hmiqwzyr\nSu5fIWtOb6wr+hQ7Up6CmUTR9arXz0+rOZEb6FaXtfysQUZ4qS6x7iWOciO6lmDLSf8tBx15\n5q2usMDqQtGyUqXxfI0q8+HCn5ktFgspwmZM4kTPBZGzEf9akeBerw/Rtw35SnXpDskqPqa5\nAgMBAAGjgZ0wgZowDAYDVR0TBAUwAwEB/zAOBgNVHQ8BAf8EBAMCAqQwEwYDVR0lBAwwCgYI\nKwYBBQUHAwEwEQYJYIZIAYb4QgEBBAQDAgZAMDMGA1UdEQQsMCqCCWxvY2FsaG9zdIYXaHR0\ncHM6Ly9sb2NhbGhvc3Q6NTA1MDWHBH8AAAEwHQYDVR0OBBYEFB7CsKx3ukg7UCOrRQJKwj2R\nnVwNMA0GCSqGSIb3DQEBCwUAA4GBAA7lTSWPFpqzrgGRjNrZrMGbhFImzH5DkVQbbcydlQzS\nkmNmHgcdk+gxqyGuUWdWYhZeB9UGmVlbFPoj0IzszhGA1D5+/szydQW31cw6DTkA5SKd6HXW\nUAiPNgsfAvfP5YkIRC4rksA2YArmto8Iy/fGBdKDFE6gRrwj635FeI1K\n-----END CERTIFICATE-----\n-----BEGIN PUBLIC KEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCsCmJo0uWqnmZ80GwCuB5oqsM8q0ruXyFr\nTm+sK/oUO1KegplE0fWq189PqzmRG+hWl7X8rEFGeKkuse4ljnIjupZgy0n/LQcdeeatrrDA\n6kLRslKl8XyNKvPhwp+ZLRYLKcJmTOJEzwWRsxH/WpHgXq8P0bcN+Up16Q7JKj6muQIDAQAB\n-----END PUBLIC KEY-----\n\n'
    }
});

Promise.resolve(undefined)
    .then(() => server.register(require('bell')))
    .then(() => {
        server.on('log', (event, tags) => console.error(Object.keys(tags).join('+'), event));
        server.on('request-error', (request, err) => console.error(err.stack));
        server.on('request-internal', (request, event, tags) => console.error(Object.keys(tags).join('+'), event));
        server.auth.strategy('auth0', 'bell', {
            provider: 'auth0',
            config: {
                'domain': process.env.AUTH0_CLIENT_DOMAIN,
            },
            ttl: 3600,
            password: '82f96f69-aa7e-41f7-8b37-aef17a18376b',
            clientId: process.env.AUTH0_CLIENT_ID,
            clientSecret: process.env.AUTH0_CLIENT_SECRET,
            isSecure: false,
            location: 'https://localhost:30303'
        });
        server.route({
            method: 'GET',
            path: '/login',
            config: {
                auth: {
                    strategies: ['auth0'],
                    mode: 'required'
                }
            },
            handler: function (request, reply) {
                reply(`<html>
                    <head>
                        <title>Success!</title>
                    </head>
                    <body>
                        <p>Successfully logged in!</p>
                        <p>Here's the profile returned by Auth0:</p>
                        <pre>
                            ${JSON.stringify(request.auth.credentials.sid.raw, null, 2)}
                        </pre>
                    </body>
                </html>`);
            }
        });
    })
    .then(() => server.start())
    .then(() => {
        console.error(`Server running at: ${server.info.uri}`);
    });

Usage with node 6.7.0:

ldesplat commented 7 years ago

So, I have the following example https://bell.now.sh/ working and you can see the source code https://bell.now.sh/_src/?f=index.js

So, I know it works one way. You are indeed using the latest hapi and bell and node so that should all work together. I see you are creating a https server properly.

Maybe the issue here is that the domain is not matching localhost:port . Try creating a domain of your own choosing (ie. localhost.dev) and spoofing that in your /etc/hosts file. Then you can set the cookie domain to localhost.dev and auth0 to redirect to that.

It sounds like the browser does not want to send you the cookie that we ourselves are creating and I would bet it's because of the domain issue. I always create my own private local domain for my projects with project.dev address to get around these issues.

garthk commented 7 years ago

Fun dead end: the example I'd been using had ttl set to 3600, which they thought was 1hr but resulted in Max-Age=3 in the set-cookie header. Setting it to 300000 (Max-Age=300) got me through the login process with isSecure: false and isHttpOnly: false. ttl: null makes more sense crashes on startup; just leave it out.

Checking the cookie security variations: Chrome now works with isSecure: true and isHttpOnly: true… and so does Safari. That's annoying. Switching to my usual auth0 client rather than this test one…

garthk commented 7 years ago

Nope, it was all ttl: removing it entirely fixed the login problems with my original application. I can now run with isSecure: true and isHttpOnly: true. Thanks for the help, @ldesplat.

lock[bot] commented 4 years ago

This thread has been automatically locked due to inactivity. Please open a new issue for related bugs or questions following the new issue template instructions.