0

I'm trying to expose a method to be accessed through HTTP Post.

@RestResource(urlMapping='/exampleURL')
global with sharing class Listener {
    //Object jsonObj = JSON.deserializeUntyped(RestContext.request.requestBody);

    @HttpPost
    global static void someMethod(String id) {
        System.debug('Got info:' + id);
    }
}

I think everything looks alright with the code, and I can test it within the system and outside of the system properly. It's very simple. However, I am trying to integrate a service that does not allow me to control the headers or body of the request. They only allow me to control the endpoint.

Is there any way I can still create a HTTP api without being able to include the session ID within the headers (no control over headers). Can I somehow integrate required credentials into the endpoint so that Salesforce is happy, or somehow remove credential requirements altogether (of course I would have a way to add them back manually, no naked endpoints).

Code: 401, [ { "message": "Session expired or invalid", "errorCode": "INVALID_SESSION_ID" } ]

I can post the HTTP POST request if you'd like, but I don't see how it will matter. You can assume there are no credentials within it and I cannot put any within it.

1
  • 1
    2 options. 1. Public site with shared class -> you will be able to perform requests GET with some limitations (based on site profile). 2. Custom middleware website. I consider this as easier and more secure since you can filter and log all incoming requests, and direct them to SF
    – kurunve
    Dec 27, 2017 at 14:10

1 Answer 1

3

One method you could try would be to set up a public force.com site, and allow the public user access to your global Apex class.

An alternative to that method is to set up an intermediary web server (either on physical hardware that you/your company/your client has on-premise, or through something like AWS, DigitalOcean, or Heroku). You would point this service to your intermediary server, which would then take care of getting you into Salesforce (generally using one of the OAuth2.0 flows).

The issue with both of those approaches is that because one step in the process is completely unauthenticated, your endpoint is effectively public.

You don't specifically mention the service that you're trying to use here, which makes it harder to give targeted advice. I find it hard to imagine that a service designed to push data to you wouldn't require you to set up some credentials first.

At any rate, if you have control over the endpoint, I would suggest trying to include a "nonce" (number, used once) in the endpoint url.

The URL mapping annotation in Salesforce can include a wildcard. @RestResource(urlMapping='/exampleURL/*') will allow you to include additional data in your endpoint URL. In your POST method, you can extract everything after "/exampleURL/" by using RestContext.request.resourcePath.substringAfter('/exampleURL/')

If you can change the nonce on every request, that would be good. If you can only include a single, static piece of data with each request from your third-party service, I still think this approach is worthwhile. The data included in the URL is effectively a password and, after the first transmission, the data in the URL is effectively public. The data included in the URL can still be used as part of a "defense in depth" strategy, but using it as the only stage in your defense strategy would amount to "security through obscurity" (i.e. I hope nobody else knows or can guess this secret string) which is not good.

1
  • That's unfortunate, but you're right, thank you. Dec 27, 2017 at 14:35

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .