0

For example, if a local server outputs a JSON with sensitive information, and I can access it through my local network, can I access this data using a lightning component?

  • You cannot access a local server unless it's exposed over the internet. – Jayant Das May 15 '19 at 17:45
  • 2
    @JayantDas but is that true for Javascript (which is run in the user's browser)? I'd imagine that making an AJAX request via Javascript would have that request originate from the user's LAN rather than Salesforce's network. If that's true, then the question is whether or not you can feed the view/controller/whatever data from Javascript variables instead of through something like an @auraenabled. – Derek F May 15 '19 at 18:14
  • @DerekF that’s exactly the case, Derek. – Renato Oliveira May 15 '19 at 18:15
  • @DerekF hadn't thought it that way. But I would think that running a JS (in user's browser locally) vs. being able to access a resource locally are still different? I am just not sure if that's possible either. I am now curious too. Wouldn't that be a sort of XSS vulnerability? – Jayant Das May 15 '19 at 18:17
  • 2
    @JayantDas If the resource is available through a local (or on-LAN) webserver that a user can access via their browser, then Javascript should be able to do the same. Salesforce's CORS settings help prevent XSS issues. Even though you're making the request from a local browser, the origin of the request (in the http headers) is still Salesforce. That makes accessing a local resource a cross-origin request, and you'd need to specifically whitelist the local domain. – Derek F May 15 '19 at 18:55
2

After a good deal of experimentation (I used this to gain my first practical bit of experience with LWC), the answer is yes.

Requirements

There are some requirements that need to be met:

  • The local server needs to set, at the very least, the Access-Control-Allow-Origin header in the response to either the wildcard * (not recommended), or the domain of your salesforce org (e.g. https:\\derekF.lightning.force.com)
    • This is for CORS
  • The local server needs to be able to provide the resource via https
    • You don't need a trusted cert for this
  • You need to add the local server's domain to your Salesforce CSP Trusted Sites
  • The localhost domain can't be used for this, and the ".dev" tld is problematic (in Vivaldi/Chrome at least)

Local server setup (so you can replicate this)

  • I installed XAMPP (doing this on win 10), and used "C:\xampp" as the install directory.
  • I added a folder, jsonTest to the default directory that xampp serves out of, C:\xampp\htdocs
  • In C:\xampp\htdocs\jsonTest, I created a file getjson.php
  • In the apache extra config file httpd-vhosts.conf (C:\xampp\apache\conf\extra\httpd-vhosts.conf), I added a VirtualHost container with ServerName local.devlp
    • This isn't a domain I own, and the tld probably isn't valid either, but it works for proof of concept
  • In the system's hosts file (C:\Windows\System32\drivers\etc\hosts), I pointed the loopback address (127.0.0.1) to local.devlp

Proof of Concept

getjson.php

<?php
$testArray = [
    "key1" => "value1",
    "foo" => "bar"
];

header('Access-Control-Allow-Origin: ' . '*'); // this really should be something like 'https://mydomain.lightning.force.com'

print(json_encode($testArray));

Lightning Web Component (externalDataTest)

externalDataTest.html

<template>
    <lightning-input label="URL" value={resourceURL} onblur={changeHandler}></lightning-input>
    <lightning-card title="Response">
        <p class="slds-p-horizontal_medium">From: {resourceURL}</p>
        <p class="slds-p-horizontal_medium">{responseData}</p>
    </lightning-card>
</template>

externalDataTest.js

import { LightningElement, track, wire } from 'lwc';

export default class ExternalDataTest extends LightningElement {
    @track resourceURL;
    @track responseData;

    changeHandler(evt) {
        this.resourceURL = evt.target.value;

        // A plain ol' AJAX request, no fancy frameworks
        var httpRequest = new XMLHttpRequest();

        // Async and Javascript scoping is a bit weird if you're not used to it
        // The anonymous function for onreadystatechange has access to local variables, but
        //   we can't reach responseData without some extra help (or, at least,
        //   I don't know how to do that).
        // Inside the anonymous function for onreadystatechange, this = httpRequest
        // So, to access responseData (which is normally done via this.responseData)
        //   we need to store the value of "this" in a local var
        var that = this;
        httpRequest.onreadystatechange = function(){
            if(this.readyState === 4){
                that.responseData = this.response;
            }
        }

        // You could point this request to a static URL, if you're a COWARD (or if
        //   the url really is static, I guess)
        httpRequest.open('GET', this.resourceURL);
        httpRequest.send();
    }
}

Result

Result of the local data test, still image

Once you get the data into a javascript variable, the sky's the limit as to what you could do. One particular extension of this that I think would be interesting would be to pass data from a local/LAN/Intranet source back into Apex to create/update some records.

  • That's great! Thank you for taking your time to provide the answer with an example. That surely will help lots of people besides me. :) – Renato Oliveira May 16 '19 at 18:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.