Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AngularJS not intercepting direct requests from Address Bar

I'm creating an AngularJS application that uses the JWT token for authentication. The token is being passed using the AngularJS interceptor as shown below.

'request': function(config)
        {
            if (store.get('jwt_token') != null)
            {
                config.headers['x-access-token'] = store.get('jwt_token');
            }
            else
            {
                config.headers['x-access-token'] = '';
            }

            return config;
        }

Whenever I'm accessing any /restricted pages, everything is working fine. The issue is when I'm going to the /restricted page by directly typing the URL in the address bar (or refreshing the page), the AngularJS gets circumvented, and hence, the Interceptors don't intercept the request, and the token is not passed.

I've been searching for a while, I found some solutions like responding with a piece of code that loads the AngularJS then makes a redirect from there. However, I'm looking for a simpler/neater approach if possible as I might be missing something here.

I can detect if the request came from AngularJS or not by checking for the x-access-token since I'm always passing it (empty value if user is not authenticated).

Solution

Alex's answer is pointing to the exact problem, thanks Alex.

I finally figured it out yesterday. The solution I went with was to make sure all the requests come from AngularJS, I have a list of the restricted pages, if any of them is requested, I'm calling a function to verify and validate the JWT token on server side, if it's valid, proceed, otherwise, go to login page. The key thing is to ensure that ALL requests should go to the index.html to make sure AngularJS is handling the routing.

This link helped me greatly to solve this issue.

http://arthur.gonigberg.com/2013/06/29/angularjs-role-based-auth/

like image 432
NightwareSystems Avatar asked Jun 22 '15 19:06

NightwareSystems


2 Answers

It sounds as if there's a confusion between Angular's router and server endpoints.

You are presumably triggering the $http configuration while navigating through the application, using URL's tracked by Angular's router (which works fine), whereas the /restricted URLs are server URLs.

Therefore, when you ask for anything /restricted outside of the Angular app (in the browser), it is sending the request straight to the server, and not via the Angular router or application.

Basically, you need to create routes in your Angular app that are within the restricted context, that when initialized, run the $http configuration. You should never be calling server end-points directly in the address bar, except for index.html (/).

I'd suggest having an Angular route called /restricted-area so that when a user hits it, it will always use the $http methods you have, by being a dedicated Angular route, calling the server's /restricted endpoint internally, via a controller.

like image 86
Alex Avatar answered Oct 23 '22 11:10

Alex


I had asked the similar question 2 months ago. What I have understood is, normally before javascript frontend frameworks how the http request were served was:

  • We type a url in address bar.
  • The browser sends the request.
  • The server gets the request.
  • serves the necessary html, js and css files.
  • browser renders it.

But as the recent shift to various javascript frontend frameworks and use of RESTful api.s has begun, the request needs to have authorization header. Thus in many of the single page web apps with javascript frameworks like angularjs,

  • the initial request for '/' router is sent
  • the server serves the web application to your browser
  • all the further routing in the web application is done within your front end application, hence the "#" after your url.
  • Requests are made by the application to fetch, update, delete or post from your application through angular js.

So when you make request from angular application. Your request is intercepted from angular application and intercepted by your interceptor. However when you enter the url from your address bar, the browser sends request directly to server, because at that point of the request, the browser has not loaded your angular web application.

What I suggest is you set html5mode to false and put a # before your route.

like localhost/#/restricted and do the routing from your route provider. When there is # before your route, the request for / goes to server, your application loads, and make some controller in /restricted from your application make http request to desired server end point. In this way the request is sent through your application and will be intercepted by your interceptor. The refresh and directly typing the address in address bar works as well.

like image 20
Pravin Avatar answered Oct 23 '22 09:10

Pravin