How to deal with extra hash in route? (AngularJS 1.5 + new/component router)

470 views Asked by At

We're attempting to build an app using Angular 1.5 with the new component router bits. We've run into a bit of an edge case and we're wondering if there's any way around it.

The Key Players

  • IdentityServer v2: our client uses this for OAuth currently. It causes a part of this problem. It's legacy, and we don't have control over its usage.
  • AngularJS 1.5 as our front-end framework.
  • The new angular router, called ngComponentRouter now I believe? We figured this style would help us bridge between Angular v1.5 and Angular v2, and it was easy enough to port.
  • oauth-ng as a wrapper for our OAuth implicit flow..
  • Older browsers: In the sense that we have to support IE9+, meaning we can't use Angular's HTML5 mode.

The Goal

We'd like to take a URL such as http://mysite/#!/auth/#auth_token=xyz123 (structure not under our control, e.g. can't remove second hash) and:

  • Get it into an actual auth controller
  • Have the auth_token value available, either through parameters or directly through $location. (it currently is scrubbed before it ever gets to the controller).

Background / Problem

Our client has a central login system where they're using IdentityServer v2. As far as I understand, when we request a token from IdSrv v2, it responds by appending #auth_token=xyz123 to your redirect URL. It was written back when it thought you'd have my.com/login.html, thus resulting in login.html#auth_token=xyz123.

With an Angular app that uses a hash already, though, it becomes a problem, as the URL ends up along the lines of mysite.com/#/auth#auth_token=xyz123.

This, as you might expect, makes Angular angry. We have yet be able to find a way to get this to work under the component router.

How it Would Work With the Older Routers

Per the oauth-ng docs, if we were using the older router without html5 enabled, we'd do something like the following:

angular.module('app').config(function ($routeProvider) {
  $routeProvider
    .when('/access_token=:accessToken', {
      template: '',
      controller: function ($location, AccessToken) {
        var hash = $location.path().substr(1);
        AccessToken.setTokenFromString(hash);
        $location.path('/');
        $location.replace();
      }
    })

What We've Tried

  • Defining a component route in a similar way. This didn't work, because /access_token=:accessToken contains an =, which doesn't appear to be allowed by component router.
  • Seeing if we can get IdentityServer v2 to change the format of the response. It doesn't seem like it's possible; the response seems to be hard-coded to [URL we define]#auth_token=xyz123.
  • Faking out the URL using other hashes, etc. Generally wound up with bad / inconsistent behavior.

What We Think our Options Are

  • Use a catch-all / not found controller. If we let the route fall all the way through to /**, we can retrieve the token value from $location. That's sort of gross though; we'd like to avoid it.
  • Find a way to get the full URL into the controller. We can capture the route and put it through to a controller, but the URL isn't available at that point.
  • Go back to using the older router or ui-router (which we'd like not to do at this point).

Anything that could point us in the right direction would be greatly appreciated!

1

There are 1 answers

0
SeanKilleen On BEST ANSWER

To follow up on this: in the end, we decided that this was a strange enough edge-case that it warranted returning to ui-router.

While we think the component router makes the most sense, the deciding factor here is that, unfortunately, we don't have 100% control over our routes. The route constraint included the edge case that component-router did not seem capable of handling at the current time.

For those who are working with older oauth server systems, I hope this will serve as a warning / some background as you're making your choice of router.

Hopefully ngComponentRouter will better support this edge case in the future, though I wouldn't blame them for leaving it out.