hash in callback url

(BTW, I just posted this a few minutes ago, but the “sign in and POST” failed and I lost my question - probably because of the un-validated email address?)

I have my callback URL configured to be
https://myspa.example.org/#/callback

However, after the resource owner step (Twitter, etc), I get
https://login.eu.auth0.com/login/callback?oauth_token=<token>&oauth_verifier=<verifier>
…which has the Location header:
https://myspa.example.org/#access_token=<jwt>

Note the missing #/callback/before #access_token=<jwt>

Why is this?

If this is standard fare, and there’s a good reason hash in callbacks aren’t allowed, please let me know how to fix the usual “single page app in an S3 bucket” problem, even if my “redirection rules” are:

<RoutingRules>
  <RoutingRule>
    <Condition>
      <HttpErrorCodeReturnedEquals>404</HttpErrorCodeReturnedEquals>
    </Condition>
    <Redirect>
      <HostName>myspa.example.org</HostName>
      <ReplaceKeyPrefixWith>#/</ReplaceKeyPrefixWith>
      <Protocol>https</Protocol>
    </Redirect>
  </RoutingRule>
</RoutingRules>

(or <ReplaceKeyPrefixWith>#!/</ReplaceKeyPrefixWith> depending on the HTML5mode flavour I’m experimenting with)

Some more thoughts: Auth0 use #access_token because it’s an OAuth implicit grant, so server-side code won’t get their grubby hands on the access token.
Still, wondering why you don’t allow hashes in callbacks, because it should be easy enough to parse #access_token from a multi-hash URL.

https://httpbin.org/get?foo=bar#/callback/#access_token=jwt

> window.location.hash
"#/callback/#access_token=jwt"
> window.location.hash.substring(window.location.hash.indexOf('#access_token'))
"#access_token=jwt"

Another thought is to add a file called callback in the bucket which will hand off the access token to my SPA.

I fixed the immediate problem by adding this callback.html to my bucket and adding https://myspa.example.org/callback.html to my allowed callbacks.

<!doctype html>
<html>
  <script>
    var hash = window.location.hash;
    var idx = hash.indexOf('#access_token');
    if (idx >= 0) {
      // has '#access_token' in URL
      var at_str = hash.substring(idx);
      var access_token = at_str.substring(at_str.indexOf('=') + 1).trim();
      if (access_token !== "") {
        // we're good to go
        window.location.href = "https://myspa.example.org/#/callback#access_token=" + access_token;
      } else {
        console.error('This page found an empty access_token in the location hash.');
      }
    } else {
      console.error('This page expected an access_token in the location hash.');
    }
    </script>
</html>

Some more thoughts: Auth0 use #access_token because it’s an OAuth implicit grant, so server-side code won’t get their grubby hands on the access token.
Still, wondering why you don’t allow hashes in callbacks, because it should be easy enough to parse #access_token from a multi-hash URL.

https://httpbin.org/get?foo=bar#/callback/#access_token=jwt

> window.location.hash
"#/callback/#access_token=jwt"
> window.location.hash.substring(window.location.hash.indexOf('#access_token'))
"#access_token=jwt"

Another thought is to add a file called callback in the bucket which will hand off the access token to my SPA.