1

I have a .Net Core REST API. and a native mobile app (also a SPA).

I don't have any individual user authentication for my application. It's like a free service.

But I want to make sure that the service can be accessed only if the end-users are trying to access it from the native mobile app or the SPA. if the paste the GET/POST link on a browser, it should not be accessible.

Is it possible?

(If not a completely secure solution? at least a simple solution (where the system cannot be easily cracked)? BTW currently using a simple API-Key)

Vishnu
  • 1,757
  • 2
  • 11
  • 19
  • API key bound to an IP or website (like Google does it)? – VDWWD Sep 01 '20 at 15:17
  • Continue using the API key, over SSL to your API? Disregard any calls that don't provide the key? – Louis van Tonder Sep 01 '20 at 15:18
  • @VDWWD I'm just using a GUID – Vishnu Sep 01 '20 at 15:24
  • 1
    @LouisvanTonder "Disregard any calls that don't provide the key" -> anyone can reverse engineer my native app/SPA to get the API key no? – Vishnu Sep 01 '20 at 15:26
  • Sure, if they reverse engineer it, they will see your key. As well as all your other "secrets" ? That is a problem of reverse engineering, not API keys... (in my opinion) – Louis van Tonder Sep 01 '20 at 15:52
  • What you're asking for is not possible. You can implement some "security by obscurity" (i.e. API keys in this case) that prevents misuse of your API in cases the motivation for misuse is low. But highly motivated attackers can always get around it (reverse engineering APP and SPA to get key, using a proxy to intercept legitimate HTTPS traffic to see the traffic). The closest you might get to what you want is rate limiting the requests to your API (e.g. only allow a max number of requests per IP within a time interval). – Christian Sep 02 '20 at 07:39
  • If all you had was a native iOS app, you could use Apple's DeviceCheck API. No Google provided option for Android that doesn't require authenticating with a Google account though. And obviously nothing for SPA. – Christian Sep 02 '20 at 07:47

3 Answers3

0

Who is in the request and What is doing the request?

I don't have any individual user authentication for my application. It's like a free service.

User authentication only identifies who is in the request being made to the API server, not what is doing it.

This is a misconception that usually I find among developers of any seniority, thus I will recommend you to read this section from the article I wrote with the title Why Does Your Mobile App Need An Api Key?. The section explains in detail the difference between who and what is accessing your API server, but I will extract here the main takes from it:

The what is the thing making the request to the API server. Is it really a genuine instance of your mobile app, or is it a bot, an automated script or an attacker manually poking around your API server with a tool like Postman?

The who is the user of the mobile app that we can authenticate, authorize and identify in several ways, like using OpenID Connect or OAUTH2 flows.

In resume you need to think about the who as the user your API server will be able to Authenticate and Authorize access to the data, and to think about the what as the software making that request in behalf of the user.

Is it Possible?

But I want to make sure that the service can be accessed only if the end-users are trying to access it from the native mobile app or the SPA. if the paste the GET/POST link on a browser, it should not be accessible.

Is it possible?

"Yes" and "No"... Well I don't like to categorical use any of these affirmations, because in software is always more like it depends!, thus I surround them in quotes ;)

Yes for Mobile Apps

For a mobile app you can use the Mobile App Attestation concept to give an high degree of confidence that what is making the request is indeed the original and untampered version of your mobile app, and to learn more about it I recommend you to read this answer I gave to the question How to secure an API REST for mobile app?, specially the sections Securing the API Server and A Possible Better Solution.

No for Web Apps

For a web app all an attacker needs to do is to hit F12 to inspect the web page and view all the source code on it, therefore no direct solution here to tackle the issue of knowing with an high degree of confidence what is doing the request, but you can make the attacker life harder. I recommend you to read my answer to the question Secure api data from calls out of the app, specially the section dedicated to Defending the API Server.

Do you want to go the extra mile?

In any response to a security question I always like to reference the excellent work from the OWASP foundation.

For APIS

OWASP API Security Top 10

The OWASP API Security Project seeks to provide value to software developers and security assessors by underscoring the potential risks in insecure APIs, and illustrating how these risks may be mitigated. In order to facilitate this goal, the OWASP API Security Project will create and maintain a Top 10 API Security Risks document, as well as a documentation portal for best practices when creating or assessing APIs.

For Mobile Apps

OWASP Mobile Security Project - Top 10 risks

The OWASP Mobile Security Project is a centralized resource intended to give developers and security teams the resources they need to build and maintain secure mobile applications. Through the project, our goal is to classify mobile security risks and provide developmental controls to reduce their impact or likelihood of exploitation.

OWASP - Mobile Security Testing Guide:

The Mobile Security Testing Guide (MSTG) is a comprehensive manual for mobile app security development, testing and reverse engineering.

For Web Apps

The Web Security Testing Guide:

The OWASP Web Security Testing Guide includes a "best practice" penetration testing framework which users can implement in their own organizations and a "low level" penetration testing guide that describes techniques for testing most common web application and web service security issues.

Exadra37
  • 11,244
  • 3
  • 43
  • 57
0

For my APIs I just made a generic authentication check. I append a pre-set username/password into my request header and then check it against a setting in my API. I only really care about the password but I use the username to identify the source. I created a base controller that all my API controllers inherit from so I can authorize all requests. (logging is optional)

 public abstract class BaseController : ApiController
    {
        protected static readonly Logger _logger = LogManager.GetCurrentClassLogger();

        protected bool IsAuthorized()
        {
            try
            {
                _logger.Debug("Checking credentials");
                var (Username, Password) = Security.ParseCredentials(HttpContext.Current.Request);
                if (Password != AppConfig.Instance.Settings["Password"])
                {
                    _logger.Error($"Calling application ({Username}) was not authorized.");
                    return false;
                }
                else
                {
                    _logger.Debug($"Calling application {Username} successfully authenticated.");
                    return true;
                }
            }
            catch (Exception ex)
            {
                _logger.Error(ex, "An error occured checking authentication");
                return false;
            }
           
        }
    }

Then in my code that calls the API I encode a username password into the authorization property.

var client = new HttpClient
{
    BaseAddress = new Uri(ConfigurationManager.AppSettings["ReportApiUri"])
};
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Authorization =
       new AuthenticationHeaderValue("Basic",
       Convert.ToBase64String(Encoding.UTF8.GetBytes(
           $"SourceApplication:{ConfigurationManager.AppSettings["ApiPassword"]}"
           )
       ));

If you're calling from a SPA you could pre-encrypt the values and pass them in. I'm able to pass this using Postman so there has to be a way to pass it using any client I would think.

PS - The AppConfig object in my base controller is just a class I wrote to retrieve settings, you can use configuration manager or even hard-code it.. I mean, I don't recommend hard-coding it long-term but just to test it out.

Zoey
  • 226
  • 2
  • 13
0

here's a link to another stack overflow question(the question is answered) in which someone tries to get a clients IP.

Yovel
  • 93
  • 7