How do I limit requests to specific domain

I would like to be able to limit certain endpoints to specific domains (our own). Currently I just hide endpoints from metadata, but if someone pokes around it’s easy enough to find. So, what I’m after the the ability to limit certain endpoints without having to login. These endpoints exist for guest users of the system.

The client side is pure angularJS and simply calls our API. Is there a valid secure way to deal with this?

Sounds like you just want to use a Request Filter or Request Filter Attribute to validate the Request.

Here’s an example of a Request Filter Attribute that validates the request against a whitelist of IP’s defined in your registered AppSettings:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = false, AllowMultiple = false)]
public class EnsureValidClientAttribute : RequestFilterAttribute
{
    public override void Execute(IRequest req, IResponse res, object requestDto)
    {
        var allowedIps = new HashSet<string>(HostContext.AppSettings.GetString("AllowedIps").Split(','));
        if (!allowedIps.Contains(req.UserHostAddress))
        {
            res.StatusCode = (int)HttpStatusCode.Forbidden;
            res.StatusDescription = "Thou shall not pass!";
            res.EndRequest();
        }
    }
}

Which you can then annotate on all Services you wish to restrict to a predefined list of IPs:

[EnsureValidClient]
public class MyHiddenServices : Service
{
    //...
}

That looks and sounds pretty simple. I like it. Can I consider this fairly safe, as in difficult for someone to spoof the request ip address?

It’s safe in that Firewalls and a range of Network Security rely on filtering IPs. But in general IP Address Spoofing is possible but then they wouldn’t be able to receive any responses since it wont be routed to them.

ok, so i’ve been able to test in a deployed dev environment but didn’t get the results I expected. Perhaps it’s as simple as I’m using the wrong request property. The request IP is of the user client machine and not the server ip that served up the client pages.

So it’s not the client that we want to limit - but the server that hosts the client.

Yes it’s the IP of the client making the request, why would you validate the Server’s IP that’s hosting the actual Service?

Really have no idea what you mean by this but Enable DebugMode then go to ?debug=requestinfo and have a look at the different values of the incoming request and choose which one you want to validate against.

Sorry, sometimes I’m not good at explaining the issue correctly.

Here’s the background on the problem. Currently we have several api endpoints that the client has to call when a user is not logged in. However, this is not very secure as anyone could call these enpoints if they know them.

What i’m trying to do is figure out how to limit these to only be called from a valid client page that is served up from one of our domains and not just someone running curl on the endpoint or other apps calling the endpoint.

If they’re not logged in, what are you expecting to validate this on? i.e. how are you planning on differentiating an anonymous call from curl vs an anonymous call from an Ajax request from one of your web pages? I mean you can check the HTTP Referer but that can easily be spoofed by curl.

You can do something like generate a token embedded in every page you return that your Ajax client uses when making the request which you validate on the Server by holding the state of generated tokens. But all a HTTP Client would need to do is request a page from your domain, extract out the token and make the same request.

Personally I would design your API’s defensively, knowing that your anonymous API’s can be called by anyone, so don’t give anonymous APIs access you don’t want anonymous clients to be able to call.

Thanks. I’m starting to realize from reading other posts around the web that basically it’s futile without an actual user login. I think the defensive approach is the only way to handle it - which is the way it’s kind of been anyway.

Thanks.