简体   繁体   中英

Authenticate a site/app to access a Web API Service

Brief question: I've a Web API Service in .NET, and a Site made only with HTML and AngularJS.

How can authorize to my service ONLY my web?


I'm looking for a secure answer to a problem that seems to be common but is not. I read a lot of answers, ideas and every kind of things in the late days, but I couldn't find the solution.

Let's suppose I've a Web Api Service (the lastest one) from MS. So I have to application that need consumes it. Let's define two scenarios.

Scenario 1:

In the same IIS, I've an ASP.NET MVC 3/4 with the particularity that all MVC work is on the client side, made by AngularJS, so the App points directly from JavaScript to the Web Api Service.

Scenario 2:

I've a third party application that points directly to the Web Api Service, and is locate in other network/site/anything but related.

So, my question is:

How can authenticate both systems, in order to the Web Api Service gives access to both system (I don't care if is the same way or not), and not give access for example to a guy with a REST client, and logged to the site with user/pass authorization? I hope these both examples gave the idea of the point what I'm interested.

Please comment below anything you need to improve this question in a better way!

By the way, no, obfuscation can not be used. I thought in something like a refreshing token but I can't figure it.

How I would set up authentication with your Scenario 1 :

I will force the static files to go through the server in order to ensure authentication

Web.config

<compilation>
    <buildProviders>
        <add extension=".html" type="System.Web.Compilation.PageBuildProvider" />
        <add extension=".htm" type="System.Web.Compilation.PageBuildProvider" />
    </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 <authentication> and <authorization> in my web.config like:

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

or

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

Additionally I will set up my login page:

<authentication mode="Forms">
      <forms  path="/" loginUrl="~/login"..

For Scenario 2 :

Probably you will need to enable CORS, if it is the case you will need to:

Set the config option config.EnableCors(); in your Register method; you will also need to enable CORS in your ApiController by using [EnableCors] attribute along with the declaration of the controller, here is an example how I do it:

 [EnableCors(origins: "http://localhost:49595", headers: "*", methods: "*")]
 public class ValuesController : ApiController
 {
 ...

Finally to secure the WebApi we will need to use an attribute [Authorize] in the controllers and most likely you will need to define your custom authentication method to authorize your second callers. You could follow these steps:

Not exactly an answer to the question but what I want to say is too long for a comment, so...

There are various ways to secure a RESTful service , but if you want to restrict access to it you mainly have two approaches:

  • use the service only from an internal network or through a VPN of some sort (ie control the environment over which the service is accessed and allow access only from some specific sources);
  • have the service exposed to the public but then have the application or server drop any requests that don't meet some requirements (ie not authenticated, missing tokens, bad signatures etc).

Depending on what you are doing, none of the above could work.

What you want (as I understand from your question) is to limit the clients accessing your service to just two. Of the top of my head I can only think of HTTPS with mutual authentication . You use client side certificates to authenticate the client. IIS will handle the connection so if your clients make a request without presenting a certificate the request is rejected. Nobody can access your service unless they have a client certificate provided by you.

So it's a matter of issuing one certificate for each client. This works for the third party app but it might be impossible to implement because of the browsers accessing your API directly. This will mean you need to install a certificate for each browser accessing your MVC application or move access to the API on the MVC server side and no longer call it directly from AngularJS. If you can do either of that it's fine, otherwise it's back to the drawing board...

Hope this helps! And if you find a suitable solution please post it as an answer on SO.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM