12

I have a WebAPI 2 / AngularJS SPA application that uses Identity 2 for authentication. Locally my code stores a token for authentication. I would like to implement functionality that allows my application to request additional javascript for authenticated users after my initial index.html page has been downloaded.

Is there a way I can make my server code give out the javascript files to only authenticated and authorized users? Something similar to the way a controller action method returns data to only authenticated and authorized users.

  • I would do this by outputting the JS via PHP, or in your case ASP, checking the authentication then using `Content-type: application/javascript` so that the browser knows it's JS, e.g. `somescript.js.asp` or `javascript.asp?querystring=if_you_want` – Popnoodles May 27 '14 at 01:28

4 Answers4

5

You can force the static files to go through the server in order to ensure authentication by setting it up on the web.config:

Web.config

<compilation>
    <buildProviders>
        <add extension=".html" type="System.Web.Compilation.PageBuildProvider" />
        <add extension=".htm" type="System.Web.Compilation.PageBuildProvider" />
         <add extension=".js" type="System.Web.Compilation.ForceCopyBuildProvider"/>
    </buildProviders>
</compilation>

<system.webServer>
     <handlers>
         <add name="HTML" path="*.html" verb="GET, HEAD, POST, DEBUG"   type="System.Web.UI.PageHandlerFactory" resourceType="Unspecified" requireAccess="Script" />
         <add name="HTM" path="*.htm" verb="GET, HEAD, POST, DEBUG" type="System.Web.UI.PageHandlerFactory" resourceType="Unspecified" requireAccess="Script" />
     </handlers>
</system.webServer>

This will allow me to set up <authorization> in my web.config for the locations I want, like:

Location: scripts/secured/demo

<authorization>
  <allow roles="demo" />
</authorization>

or Location: scripts/secured/

 <authorization>
   <deny users="?" />
 </authorization>

http://msdn.microsoft.com/en-us/library/h0e51sw9(v=vs.85).aspx

A similar question was recently if it helps:

Secure angular app access and Web API Service

Community
  • 1
  • 1
Dalorzo
  • 19,834
  • 7
  • 55
  • 102
4

If you host your site in IIS you can configure the IIS to serve *.js files via the .Net framework. Then you'll need to create an HTTPHandler to serve these files (checking if the user is authenticated within the HTTPHandler's code).

If you aren't sure where to start, you can read Combine, minify and compress JavaScript files to load ASP.NET pages faster or some similar article. Although the purpose there is different, it does explain how to serve js files via ASP .Net. You'll just add your authentication checks to the HTTPHandler.

Update: Here is an explanation how to setup IIS for this. Just make sure you know which version of IIS you have.

Dalorzo
  • 19,834
  • 7
  • 55
  • 102
H.Wolper
  • 699
  • 1
  • 13
  • 26
  • thanks for your advice. I was not aware I could configure IIS to serve *.js via .Net. I hope someone can give me some more advice with this. –  May 27 '14 at 14:26
  • 1
    @marifemac, I updated my answer to help with that. The link has a clear step-by-step explanation how to do it. Please mark my answer as accepted if you feel I've answered your question properly, Thanks. – H.Wolper May 27 '14 at 15:02
  • I think your answer may be one solution but I have a few problems in that I don't have access to configure my IIS other than through web config. I would also like to wait a short while to see if I can see other possible solutions to this problem. Thanks for your help so far. –  May 28 '14 at 13:30
  • With IIS Integrated mode (not classic mode), all requests go through the Authorize/Authenticate portion request lifecycle regardless of the handler mappings in IIS. http://msdn.microsoft.com/en-us/library/vstudio/bb470252(v=vs.100).aspx#Stages – Jeremy Bell May 30 '14 at 02:37
  • @JeremyBell - This is an Azure WebRole application. Does that mean IIS Integrated Mode? Also I don't have access to the IIS so how could I set up the authorization. I tried the web-config example below but it does not seem to work. I am still looking into this. –  May 30 '14 at 08:10
1

Another Option: Serve your js from webapi!

This is surely not the best performing way to do it, but it works great, gives you a lot of control, is super easy to wrap your brain around, and requires no IIS or config file changes. I do this on WebAPI2 in several ASP.Net projects - YMMV.

(Another thing that gets tricky is if you want your authentication mechanism to be by a Bearer token in the request header - that's pretty much impossible unless you download the javascript via ajax, and then add it to the document ... or put the token in the querystring - which would be weird as you'd have to render the script tag with the token. This really works best with cookie-based authentication. )

  1. Load your JS file(s) into a static variable(s) on the API controller
  2. Make sure Attribute Routing is turned on for WebAPI (https://learn.microsoft.com/en-us/aspnet/web-api/overview/web-api-routing-and-actions/attribute-routing-in-web-api-2)
  3. Create an endpoint for your javascript file(s) with a route like:
[Route("api/system/GlobalConstants.js")]
public HttpResponseMessage GlobalConstantJS()
{
    var resp = new HttpResponseMessage(HttpStatusCode.OK)
    {
        Content = new StringContent(MY_STATIC_STRING_WITH_THE_JS_TEXT)
    };
    return resp;
}
  1. Make sure your API controller is secured with the Authorize attribute :)
  2. Use a plain-old regular script element, pointing to the route:
 <script src="~/api/system/GlobalConstants.js" type="text/javascript"></script>

...obviously this has the additional advantage of being able to serve dynamically generated javascript files - if you so choose.

C.List
  • 657
  • 8
  • 16
-2

If you can use jQuery, there is a $.getScript ajax function. http://api.jquery.com/jquery.getscript/

It is an asynchronous call to the server to load a javascript file. But on the server side, if the user is not currently authenticated by the server, return null.

$.getScript('url', function(data) {
        // check if data is null, if yes, means the user needs to be authenticated still
    });
Andrew
  • 18,680
  • 13
  • 103
  • 118
  • If you make the authentication checks on the client side, there's no guarantee that smart users / hackers won't (very easily) override your checks. – H.Wolper May 27 '14 at 11:03
  • I agree. I am not looking for a client side solution. It must be something from the server side. –  May 27 '14 at 14:24
  • You do the get request, but only return the script if the user is logged in on the server side, otherwise return false or nothing. – Andrew May 27 '14 at 20:33
  • @Andrew - I'm sorry but I don't really see how your solution answers my question at all :-( I am looking for a server side solution. –  May 28 '14 at 13:31
  • Andrew, this does not accomplish what you want at all. You're doing it on the client side. The user would be able to bypass what you're saying by using their browser's debugging tools or simply navigating to the javascript file. – mason May 28 '14 at 16:23
  • I never said authenticate on the client side in the answer, of course authenticate server side. Your asp.net would check if authenticated, and if so, send back a javascript file? Put the javascript in a protected directory, now they can't navigate to it. – Andrew May 28 '14 at 16:26