4

I'm stuck on this one issue trying to rewrite the Web Api SPA template with OAuth (in knockout.js) into AngularJS.

When I click an external login button a series of requests take place that eventually result in

Authentication.SignIn(claimsIdentity);

This is good! However, right after I return Ok() I get redirected to the external login (Google). After I sign-in with Google their authorization servers respond with a 302 redirect to the following location:

 http://localhost:59936/access_token=xxxx&token_type=bearer&expires_in=1209600&state=yyyy

Looking at the SPA template in knockout I'm supposed to parse the URL for the token, and make a call to getUserInfo() with the access token.

However what happens is that link just gets stuffed into my browser URL bar and Angular is oblivious to it. My httpInterceptor does not fire, neither does $routeChanged, and I think it would be silly/dirty/ and probably won't work to make a $routeProvider.when("/access_token")

I'm in 1.2.9 Angular (I saw someone mention a bug in angular that I can't find regarding its http interceptor handling of 302 and that it's fixed in 1.2.9 but does not seem to be the case.

What to do?

EDIT: Actually, thinking about how the code is structured it wouldn't actually be that dirty to be able to catch that using routeProvider. This is because the HomeController looks something like this:

function HomeController(...) {

   //Parses the url above
   var fragment = getFragment();

   ... All kinds of fragment checks (fragment.access_token, fragment.state, etc)...
}

The problem is the HomeController does not get instantiated when this URL gets stuffed into the browser.

Is there any way to match the above URL to a route? Something like when('/access_token*rest') --However this does not work.

A potential workaround I can think of is to catch the URL change in $locationChangeStart and stuff the access_token into local/session storage but this would require a lot of code restructuring since all of the logic is already in the HomeController. The best would be just get it to instantiate when that URL gets hit.

Unsatisfactory workaround: Here's another the workaround but I'm really not happy with it. It's hackish and requires a lot of restructuring.

 app.run(['$rootScope', '$location', '$http', '$controller', 'AuthenticationService', 

    '$window', 'StorageService', //HomeController Dependencies

    function ($rootScope,
              $location,
              $http,
              $controller,
            AuthenticationService,

        $window, StorageService)
    {       
        $rootScope.$on("$locationChangeStart", function (event, next, current) {
            if (next.indexOf("access_token") > -1) {

                var homeController = $controller(Controllers.Authentication.HomeController, {
                    '$rootScope': $rootScope,
                    '$scope': {},
                    '$window': $window,
                    '$location': $location,
                    'AuthenticationService': AuthenticationService,
                    'StorageService': StorageService  
                });
            }
        });
    }

1 Answer 1

2

Is there any way to match the above url to a route? Something like when('/access_token*rest') --However this does not work.

If your URL were http://localhost:59936/?access_token=xxxx&token_type=bearer&expires_in=1209600&state=yyyy (notice the added ?) then the router could match it like this $routeProvider.when('/') (since the router will ignore the param string) then in your controller you can parse the url parameters.

Is this external login causing the page containing your angular app to redirect to the external webpage? If this is the case, then your app will be unloaded, which probably isn't ideal. To handle external login, I usually open a popup window so that my app doesn't get unloaded.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.