Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

angular-ui replace'?' with '#' on redirect from facebook oauth

I'm implementing facebook ouath login in angularjs without SDK.

Everything works as expected except one thing.

When user click on login button, which redirects to facebook login page, after successfull login, facebook fires redirect_uri URL, and user is again in the app.

Problem is, that ui-router (probably) replaces '?' with '#' in path, so

http://localhost/fbauth?access_token=xxx&code=yyy
becomes
http://localhost/fbauth#access_token=xxx&code=yyy

Because of that, i cannot use $stateParams to get object with query params.

Suprisingly, when I manually enter in browser or click link to http://localhost/fbauth?access_token=xxx&code=yyy
everything works properly, and ui-router does not replace '?' with '#'.

I guess, that it's related to redirection scenario itself.

Can someone point me what I do wrong, or how to change ui-router behaviour in this case?

This is the state, that handles fb redirect:

.state('fbauth', {
  url: '/fbauth?access_token&code&expires_in',
  templateUrl: 'static/public/public.html',
  controller: 'publicCtrl'
});

PS ui-router is set to work in html5 mode with $locationProvider.html5Mode(true);

like image 798
Jarema Avatar asked May 15 '15 10:05

Jarema


2 Answers

You can add this resolve function to your state, which will replace a hash url with the query string url:

resolve: {
    'urlFix': ['$location', function($location){
        $location.url($location.url().replace("#","?"));
     }]
}
  • So a url of /fbauth#access_token=123456&code=abcde&expires_in=99999999 would be redirected automatically
  • Becoming /fbauth?access_token=123456&code=abcde&expires_in=99999999
  • $stateParams would be populated correctly.
  • The value would be {access_token: "123456", code: "abcde", expires_in: "99999999"}
  • $location.url() doesn't update if the location matches already, so the state won't redirect when there is no # present.

Full example code:

<!DOCTYPE html>
<html>
<head>
    <script src="https://code.jquery.com/jquery-1.11.1.min.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.2/angular.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.15/angular-ui-router.js"></script>
    <meta charset="utf-8">
    <title>FBAUTH</title>
</head>
<body ng-app="app">
    <base href="/">
    <div ui-view></div>
    <script>
        angular.module('app', ['ui.router'])
            .controller('publicCtrl', ['$scope','$stateParams', function($scope, $stateParams) {
                // $stateParams should be correctly set (even for hash route)
                console.log($stateParams);
            }])
            .config(['$locationProvider','$stateProvider', function($locationProvider, $stateProvider){
                $stateProvider
                    .state("fbauth",
                    {
                        url: '/fbauth?access_token&code&expires_in',
                        templateUrl: 'fbauth.html',
                        controller: 'publicCtrl',
                        resolve: {
                            'urlFix': ['$location', function($location){
                                $location.url($location.url().replace("#","?"));
                            }]
                        }
                    });

                $locationProvider.html5Mode(true);
            }]);
    </script>
</body>
</html>
like image 123
Scott Avatar answered Nov 15 '22 22:11

Scott


I would not prefer passing query parameters(using ? mark) in client side routing. Instead you can use route/state params as follows:

http://localhost/#/fbauth/access_token/:access_token/code/:code

and you can access these values using $stateParams. e.g. ($stateParams.access_token)

like image 27
vs4vijay Avatar answered Nov 15 '22 23:11

vs4vijay