10

Setup:

  1. Force.com site page
  2. Guest Users
  3. VF with Lightning Out
  4. Lightning component to subscribe to Push Topic

Problem Guest User does not have a session ID so no way to set it here:

$.cometd.init({
     url: '/cometd/39.0',
     requestHeaders: {Authorization: 'OAuth ' + sid},
     appendMessageTypeToURL: false
}); 

Is there a way to use Named Credentials in a Lightning Component?

I tried (did not think it would work but thought I would try):

$.cometd.init({
     url: 'callout:Prod/cometd/39.0',
     requestHeaders: {Authorization: 'OAuth {!$Credential.OAuthToken}'},
     appendMessageTypeToURL: false
}); 

but it did not work and since I cannot get a session ID from Guest User I am stuck with how to subscribe to the push topic.

I also tried to create an HTTPRequest in apex and use the {!$Credential.OAuthToken} and then debug it but as expected it is not merged until sent

I also do not see a way to get a valid sessionId / auth_token in Apex using a named credential.

so the Questions

  1. Is there a way to use a named credential in a Lightning Component
  2. If no to #1 is there a way to get the valid OAuth token in apex using a given named credential

Additional Question

When testing and hardcoding the sessionID of full user I can get cometd to connect to /cometd/39.0 but when attempting to connect to another org using a session Id from that org it will not connect and I am using a URL like https://xxx/my/salesforce.com/cometd/39.0. Is it not possible to connect to cometd of another org? (assume session ID is valid)

Just bumping to top after falling beneath the fold over the weekend

  • I was thinking about such a scenario in the context of platform events and listening to them in lightning. My approach - yet untested - have a VF page connect to comet/listen to streaming api, wrap it into a cmp - use postMessage to inform cmp about push updates. cmp can then issue an application event. – Christian Szandor Knapp Jun 9 '17 at 21:27
  • Yup. But I am trying to subscribe to another SF push topic and need the names credential for the oAuth. Even if I had that I can't seem to connect to the other instance using comtd and a hardcoded session Id though – Eric Jun 9 '17 at 21:29
  • Your stuff is running on Instance A. You want to listen to Push Topics from Instance B, right? Thinking loud here since all untested: Maybe have a cmp on instance B that surfaces via lightning out in instance A? Knot them together with the approach above. – Christian Szandor Knapp Jun 10 '17 at 10:48
  • 1
    @ChristianSzandorKnapp - That could work in my situation, that for the thought. However, I would liKe to solve the original question as well as connecting to Streaming API from another instance. My gut is that it is simply not possible at this moment given the lack of answers :). – Eric Jun 10 '17 at 16:50
4
+100

I have done something similar to make a call to the Salesforce Rest API from lightning (well technically Apex). The session that lightning produces is an isolated session that can't be used anywhere else. It is specific to lightning only.

In my use case, I needed to get some information about a list view that wasn't exposed in describe calls or querying the list view object. So I created a Connected App + Auth Provider + Named Credential. When I created the connected app I set it up for OAuth and used my admin account to sign in. So basically it is a single account integration of sorts.

In my Apex Controller for my lightning component, I used the named credential and it does work. I have it running in a production environment right now.

Here is a sample of my Apex Controller that uses the named credential:

public static final string ENDPOINT_TEMPLATE = 'callout:Lightning_API/services/data/v39.0/sobjects/{0}/listviews/{1}/describe';

@AuraEnabled
public static SummaryResponse getListViewSummary(string sobjectType, string[] viewNames) {
    SummaryResponse response = new SummaryResponse();

    string endpointTemplate = '';

    List<ListView> views = queryListViews(sobjectType, viewNames);
    for (ListView view : views) {
        string endpoint = String.format(ENDPOINT_TEMPLATE, new string[]{sobjectType, view.Id});

        HttpRequest calloutRequest = new HttpRequest();
        calloutRequest.setEndpoint(endpoint);
        calloutRequest.setHeader('Content-Type', 'application/json');
        calloutRequest.setMethod('GET');

        HttpResponse calloutResponse = new Http().send(calloutRequest);

        string jsonResponse = calloutResponse.getBody();
        if (jsonResponse.startsWith('{')) {
            ListViewInfo viewInfo = (ListViewInfo) JSON.deserialize(jsonResponse, ListViewInfo.class);
            if (viewInfo != null) {
                viewInfo.viewId = view.Id;
                viewInfo.name = view.Name;
                viewInfo.total = 0;
                viewInfo.totalFormatted = '0';

                if (String.isNotBlank(viewInfo.query)) {
                    viewInfo.total = Database.countQuery(viewInfo.getAggregateQuery());
                    viewInfo.totalFormatted = viewInfo.total.format() + (viewInfo.total == 5000 ? '+' : '');
                }

                response.views.add(viewInfo);
            }
        }
    }

    return response;
}

If this is indeed what you are trying to do let me know any specific questions you might have on setting this up. It took some trial and error on my part to get everything configured.

I also can't say that this is the best or most definitive way to accomplish this as lightning continues to be a moving target but at least at this moment in time this is what I did to the things that I needed to.

  • Yea I do the same thing. Comtd however requires JavaScript and an live page. Appreciate the answer, it will help someone but does not solve the purpose of the question. – Eric Jun 9 '17 at 3:16

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.