0

We are using angular for front-end and Salesforce is being used for maintaining database. REST APIs have been written on Salesforce to communicate and fetch data to front-end. A custom profile has been created with limited access for End users. SSO OAth settings are also being used in Salesforce. This results in exposing queries on browser console. We are using Custom Settings to store some data and this Custom Setting (Visibility- Protected) is being used in the Rest API.

We have a field (INFO_API_header_key__c) in this Custom Setting (List) which though not included in front-end query but gets accessible if we edit the query and add this field's API name through query call on postman (A direct query is not being made on Custom Setting but they are being as headers which are coming in front-end response). This exposes the stored data.

Since there is no option to set Field-level Security in Custom Settings, can you please help me with a sample code to hide this field's data through Apex code.

My requirement is this field's data should not be accessible on front-end (or postman) in query calls and for external users ,and this field should only be accessible in SalesForce API only through the field names.

REST API-

@RestResource(urlMapping='/v1/getreceiptInfo/*')
global with sharing class REST_GetDocInfo {

@HttpPost
global static postJson doPOST(Details customer) {

RestRequest req = RestContext.request;
RestResponse res = RestContext.response;
postJson response = new postJson();

validateInput(customer, response);

if(response.status != 'Failure') { 
if(isAuthorizedUser(customer.Id)) {
    response.rawRecord.addAll(getResponseModelList(customer, response));
    if(response.status != 'Failure') { 
    response.status = 'Success';
    response.errorCode.add('000');
    response.message.add('Operation successful');
    }
} else {
    response.status = 'Failure';
    response.errorCode.add('003');
    response.message.add('You are not allowed to view the information');
    }      
}

return response;
 }

//this class has the response data fields 
global class postJson {
public List<ResponseModel> rawRecord;
public String status;
public String [] message;
public String [] errorCode;
public Boolean leadcustomer;

public postJson(){
rawRecord = new List<ResponseModel>();
message = new List<String>();
errorCode = new List<String>();
}
}

//this is custom response data model 
global class ResponseModel {
public String receiptId;
public String customerName;
public String customerNumber;
public String receiptType;
public String valReceipt ;
public String receiptName;
public String leadcustomer;
public Decimal isReceiptListAvailable;
public String recOrderNumber;


public ResponseModel(String receiptId, String customerName, String 
customerNumber, String receiptType, 
String valReceipt , String receiptName, String leadcustomer, Decimal 
isReceiptListAvailable, String recOrderNumber){
this.receiptId = receiptId;
this.customerName = customerName;
this.customerNumber = customerNumber;
this.receiptType = receiptType;
this.valReceipt  = valReceipt ;
this.receiptName = receiptName;
this.leadcustomer = leadcustomer;
this.isReceiptListAvailable = isReceiptListAvailable;
this.recOrderNumber = recOrderNumber;
}

    public ResponseModel(){}
 }

 //call to server and return info as string
 private static String getInfo(String receipt , postJson response){ 
    String valReceipt ;

    JSONToApex jsonRequest = new JSONToApex();
    jsonRequest.receiptUrl = receipt ; 


    Http http = new Http();
    HttpRequest req = new HttpRequest();
    Custom_Settings__c settings = Custom_Settings__c.getValues('App');
    String reqBody= JSON.serialize(jsonRequest);  
    req.setEndPoint(settings.RECEIPT_URL__c);
    req.setMethod('POST');
    req.setHeader('content-type','application/json');
    req.setHeader('x-api-key', settings.INFO_API_header_key__c);
    req.setBody(reqBody);

    try {
    HTTPResponse res = http.send(req);
    valReceipt  = res.getBody();
    } catch(Exception e) {
    valReceipt  = 'blank';
    response.status = 'Failure';
    response.errorCode.add('007');
    response.message.add('Not able to get receipt. ' + e);
    } 
    return valReceipt ;
    }
 }
2
  • 1
    Have you looked at using Named Credentials instead of custom settings? From a brief look at your code, it seems like they could be made to work. And they've not available to query, they just get substituted into callouts by the system.
    – Aidan
    Jun 19, 2018 at 11:56
  • Thanks for the suggestion @Aidan . For Named credentials, is this what you mean- { req.setEndPoint(settings.RECEIPT_URL__c); req.setMethod('POST');}. We have already added that in our code. If this is not what you meant, could you please help me with a sample code. Thanks Jun 20, 2018 at 8:28

1 Answer 1

0

Moved from a comment to an answer as I think it probably will answer your problem and it gives me more space.

Named Credentials are a special object for storing credentials securely. You can set it up per-user or have one shared login for all users. The important thing is that you don't have access to the credentials directly via Apex or any query. When you use named credentials, you create an HttpRequest and configure it to use the named credential that you need. You never read the username/password in your code, it's filled in by SF in the background. The example from the docs is this:

HttpRequest req = new HttpRequest();
req.setEndpoint('callout:MyCredential/some_path');
req.setMethod('GET');
Http http = new Http();
HTTPResponse res = http.send(req);
System.debug(res.getBody());

And that's it. If you configure the named credential to generate an authentication header, it will automatically add a standard Basic access authentication header and you never need to handle the secret.

If you need something different, you can configure your Named Credential to allow merging in request headers and then set them like this:

req.setHeader('X-Username', '{!$MyCredential.UserName}');

You must log in to answer this question.

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