How to secure my Web API - MVC4 with Android/iOS a

2020-05-29 12:06发布

I've been reading quite a few questions here on SO about securing web api's using api keys, tokens, hmac ect and haven't found the answer I am looking for.

I'm working on a MVC4 web application project with internet and intranet sites, web api and Android/iOS applications.

The Web API is to be used by my applications and nobody else as it will be accessing sensitive data.

What would be the best way of securing this api so only my apps can use it? Something that seems like such a simple request is extremely difficult to get started on.

I've looked at the post here on SO using HMAC and a few others but none of them sounded like they would fit here, more than likely I am just missing something.

Is HMAC the way to go or would client certificates be more appropriate for this situation?

Should I use SSL and some sort of API key?

I know the question is a bit vague, I've been staring at it for over an hour trying to figure out how to word what I am thinking so I figured I would just post it and update if needed... :(

I would be more than happy to provide more details upon request.

4条回答
虎瘦雄心在
2楼-- · 2020-05-29 12:34

In a general case for a high traffic app, all the above answer have a flaw that many attackers can easily exploit: With a jail broken iPhone, you can break SSL - not to your server, but when they have your app on their phone, they can at least analyse the packages you send.

The best way to avoid that (in my opinion) is using 'on time passwords' - real on time passwords.

How can you generate these one time passwords?

A1. Get a device_identifier for each device (this could also just be any random number, but you should avoid collisions with other devices' identifiers)

A2. Have an api_key, that you will use for hashing

Now if you want to send a package to your api, you do the following:

B1. Construct your normal package, here is the example of some json payload:

var payload = {"hello":"world"}

B2. Hash your var hashed_payload = hash(payload) using your favourite hashing function

B3. Generate the one time password for this package:

var otp = hash(salt & hashed_payload & device_token & api_key)

Now you have everything you need, to send to the server:

In the headers, you need to send the otp,salt and device_token as well!

On the server, you will do the same steps marked as B1-3 and compare your hashing result with the one provided by the client. After that you have to make sure that you 'ban' this salt for this device_token in order to avoid replay attacks.

This method still has one flaw but requires much more work from attackers: They can find your api_key in you compiled code.

查看更多
Emotional °昔
3楼-- · 2020-05-29 12:37

I'm working on a similar project where I assign unique API keys to each user or client application accessing my API. I'm not a security expert, but I'd recommend that you use SSL and generate unique API keys for both your Android and iOS applications. With SSL, data being transmitted to your API will be encrypted and protected.

查看更多
Animai°情兽
4楼-- · 2020-05-29 12:42

You can use FormsAuthentication. Encrypt the ticket and ensure machineKey is the same in both the config files. See this and this. This will allow the same user credentials to be shared between web app and api. ASP.NET FAM module will establish the identity in this case.

For api key, look at hawk scheme. It uses shared symmetric key. However, Hawk is feature-complete and until it reaches version 1.0 it is likely to change. Nonetheless, it will give you a good idea of implementing HMAC-based security. I have a .NET implementation here for Hawk. And there is one from Pablo as well. In this case, you will need to write a message handler to establish the identity for the consuming application.

查看更多
我命由我不由天
5楼-- · 2020-05-29 12:43

Generate a key for each of your apps and have them pass the key in each request as a token. Your server can then verify the key and authenticate the request.

Take a look at the Basic Authentication module from the ASP.NET site. The sample uses 'basic' as the authorization scheme but you can change it use 'token' instead.

private static void OnApplicationAuthenticateRequest(object sender, EventArgs e)
    {
        var request = HttpContext.Current.Request;
        var authHeader = request.Headers["Authorization"];
        if (authHeader != null)
        {
            var authHeaderVal = AuthenticationHeaderValue.Parse(authHeader);

            // RFC 2617 sec 1.2, "scheme" name is case-insensitive
            if (authHeaderVal.Scheme.Equals("token",
                    StringComparison.OrdinalIgnoreCase) &&
                authHeaderVal.Parameter != null)
            {
                AuthenticateUser(authHeaderVal.Parameter);
            }
        }
    }

Once you have the Basic Auth module in place you can simply decorate any actions or controllers with the Authorize attribute and it will forward the request to the Basic Auth handlers.

namespace webapi.Controllers
{
     [Authorize]
     public class SensitiveDataController : ApiController
     {
       ...
     }
}

As far as over the wire you MUST use SSL when using basic authentication as your key will be transmitted in plain text.

查看更多
登录 后发表回答