netlify-serverless-oauth2-backend icon indicating copy to clipboard operation
netlify-serverless-oauth2-backend copied to clipboard

Authentication window does not close on callback

Open ArcaneTSGK opened this issue 6 years ago • 8 comments

I am trying to implement GitHub OAuth flow as detailed in your blog, except that I am using Gatsby as my static site generator.

Issue The serverless endpoints are working with 'serverless offline' on localhost, but in a production environment the auth window popup does not close on callback.

The github:success token can be seen when you view the source of the callback in the popup.

Expected Behaviour Auth window closes and I am logged in to the netlify-cms GitHub backend

netlify-cms version: 1.9.3

I took a look at your config.yml and the only difference is your base_url: is your home page whereas mine is the lambda endpoint https://[].execute-api.us-east-1.amazon.aws/prod

ArcaneTSGK avatar Aug 07 '18 08:08 ArcaneTSGK

Interestingly, with the script the callback returns below, the alerts in the receiveMessage function is not hit in prod but does get hit on localhost

function getScript(mess, content) {
  return `<html><body><script>
  (function() {
    function receiveMessage(e) {
      alert('alert');
      console.log("receiveMessage %o", e)
      window.opener.postMessage(
        'authorization:github:${mess}:${JSON.stringify(content)}',
        e.origin
      )
      window.removeEventListener("message",receiveMessage,false);
    }
    window.addEventListener("message", receiveMessage, false)
    console.log("Sending message: %o", "github")
    window.opener.postMessage("authorizing:github", "*")
    })()
  </script></body></html>`;
}

ArcaneTSGK avatar Aug 07 '18 11:08 ArcaneTSGK

The issue was with my config.yml after discussing the issue on gitter netlify, the base URL should not include the /prod

If you follow your blog post after the PR you initiated with the auth window issue (where you can now set an auth_endpoint) it is actually slightly incorrect and will cause a breaking bug.

The config.yml in your blog post should be updated to:

base_url: https://RANDOMSTUFF.execute-api.us-east-1.amazonaws.com auth_endpoint: /prod/auth

It's also worth mentioning that when deploying a cloned version of your serverless app to AWS it doesn't prepend /oauth/ to [stage]/[method] which may also confuse readers of the blog post (hence why I omitted /oauth/ from the auth_endpoint above).

ArcaneTSGK avatar Aug 08 '18 06:08 ArcaneTSGK

I do have exactly the same issue - and will now follow instructions from above posts as provided by @ArcaneTSGK -

chrismade avatar Aug 10 '18 19:08 chrismade

I confirm that my issue was fixed by changing config.yml to this format: base_url: https://RANDOMSTUFF.execute-api.us-east-1.amazonaws.com auth_endpoint: /prod/auth

chrismade avatar Aug 11 '18 08:08 chrismade

For my site I'm doing some magic with CloudFront, so that might be part of the issue that most folks seem to be having. When I have time I'll revisit this.

marksteele avatar Feb 13 '19 03:02 marksteele

The issue was with my config.yml after discussing the issue on gitter netlify, the base URL should not include the /prod

If you follow your blog post after the PR you initiated with the auth window issue (where you can now set an auth_endpoint) it is actually slightly incorrect and will cause a breaking bug.

The config.yml in your blog post should be updated to:

base_url: https://RANDOMSTUFF.execute-api.us-east-1.amazonaws.com auth_endpoint: /prod/auth

It's also worth mentioning that when deploying a cloned version of your serverless app to AWS it doesn't prepend /oauth/ to [stage]/[method] which may also confuse readers of the blog post (hence why I omitted /oauth/ from the auth_endpoint above).

Many many Thanks @ArcaneTSGK you saved me from lots of problems. Documentation must have this point. I was struggling a lot to figure out the issue. Thanks a lot man, cheers 👍

jagyas avatar Feb 17 '19 05:02 jagyas

I've been following the docs and blog post but am still seeing a similar situation to this.

Everything is working as expected until the successful callback fires and tries to do the postMessage to the opener window.

At that point I see the following error in the opener's console:

Failed to execute 'postMessage' on 'DOMWindow': The target origin provided ('http://localhost:3000') does not match the recipient window's origin ('http://localhost:4000').
  • localhost:3000 is the server of my serverless backend
  • localhost:4000 is my jekyll site

The issue appears to be in the postMessage call:

      window.opener.postMessage(
        'authorization:github:${mess}:${JSON.stringify(content)}',
        e.origin
      )

It is passing in e.origin as the expected origin of the target window which is only true if you do some DNS wizardry to have both blog and auth function operating at the same origin.

I have confirmed that the auth flow completes successfully if I change this e.origin to '*' in the postMessage params.

Could there be another setting (e.g. TARGET_ORIGIN) that could be set in the Secrets declaration and used here (falling back to e.origin if TARGET_ORIGIN is not set)?

I'll have a go and if successful will push a PR.

kpopper avatar Jun 07 '19 10:06 kpopper

I'll push my fix to my fork but here's the summary of my (pretty hacky) change to allow me to specify the target origin:

In Secrets declaration:

  TARGET_ORIGIN: 'http://localhost:4000',

Update to getScript() function:

function getScript(mess, content, targetOrigin = '') {
  return `<html><body><script>
  (function() {
    function receiveMessage(e) {
      console.log("receiveMessage %o", e)
      window.opener.postMessage(
        'authorization:github:${mess}:${JSON.stringify(content)}',
        (window.targetOrigin) ? window.targetOrigin : e.origin
      )
      window.removeEventListener("message",receiveMessage,false);
    }
    window.targetOrigin = '` + targetOrigin + `'
    window.addEventListener("message", receiveMessage, false)
    console.log("Sending message: %o", "github")
    window.opener.postMessage("authorizing:github", "*")
    })()
  </script></body></html>`;
}

Change to callback response handler:

          body: getScript('success', {
            token: token.token.access_token,
            provider: 'github',
          }, secrets.TARGET_ORIGIN),

kpopper avatar Jun 07 '19 11:06 kpopper