• Rohit Radhakrishnan
  • NEWBIE
  • 15 Points
  • Member since 2015

  • Chatter
    Feed
  • 0
    Best Answers
  • 0
    Likes Received
  • 0
    Likes Given
  • 2
    Questions
  • 20
    Replies
What exactly does the statement mean? - Each SOQL query can have up to 4 joins across external objects and other types of objects.
I have 2 (A__x and B__x) external objects that are related to each other and one is a parent to a Case object.
Case has the External Lookup field a__c that has lookup to A__x
A__x has indirect lookup field b__c that has lookup to B__x
When I do {SELECT CaseNumber, a__c, A__r.b__c, a__r.b__r.Id FROM Case], i dont get the details from a__r.b__r.Id. However a callout id iniated as per the logs. Is this a limitation?
 
Hi All,
 
Can someone help me with the below issue on sfdx?
 
I'm running the below command:
sfdx force:data:record:create -t -s TraceFlag -v "DebugLevelId=7dl3Y000000XirWQAS StartDate=2020-06-05 ExpirationDate=2020-06-06 LogType=USER_DEBUG TracedEntityId=0054H000005sUT7" -u salesforce.admin@rorcom.com.customer
 
I get an error : ERROR running force:data:record:create: insufficient access rights on cross-reference id: 7dl3Y000000XirW
 
I am trying to insert a traceflag record for a user record and referring the Debug Level as "SFDC_DevConsole "which has the id "7dl3Y000000XirWQAS"
 
The user salesforce.admin@rorcom.com.customer is having a system administrator profile and system admin is added as a profile in a connected app that has "Admin approved user may self Authorize" option set. I have logged into the org using a JWT token running the "sfdx force:auth:jwt:grant" command and login was successful with the message: "Successfully authorized salesforce.admin@rorcom.com.customer with org ID 00Dxxxxxxxxxxxx".
 
Regards,
Rohit
Hi All,
 
Can someone help me with the below issue on sfdx?
 
I'm running the below command:
sfdx force:data:record:create -t -s TraceFlag -v "DebugLevelId=7dl3Y000000XirWQAS StartDate=2020-06-05 ExpirationDate=2020-06-06 LogType=USER_DEBUG TracedEntityId=0054H000005sUT7" -u salesforce.admin@rorcom.com.customer
 
I get an error : ERROR running force:data:record:create: insufficient access rights on cross-reference id: 7dl3Y000000XirW
 
I am trying to insert a traceflag record for a user record and referring the Debug Level as "SFDC_DevConsole "which has the id "7dl3Y000000XirWQAS"
 
The user salesforce.admin@rorcom.com.customer is having a system administrator profile and system admin is added as a profile in a connected app that has "Admin approved user may self Authorize" option set. I have logged into the org using a JWT token running the "sfdx force:auth:jwt:grant" command and login was successful with the message: "Successfully authorized salesforce.admin@rorcom.com.customer with org ID 00Dxxxxxxxxxxxx".
 
Regards,
Rohit
Hello guys,
 
i am looking for the best way to handle validation rules in apex triggers. Sometimes i want to execute some dml actions after the record is validated. 

Is it possible to query all my validation rules and extract the error condition ? i don't want to translate my validation rules into apex and i am pretty sure, that there is better way to do that.  

Another option is to translate all my validation rules into apex methodes to receive a boolean. So it would be possible to use them in classes and triggers.

I hope you will understand my concers and i am appreciate your help ! 
sfdx force:auth:jwt:grant --instanceurl is failing to authenticate with sfdx and sandbox autheication.
SFDX Authentication is working fine for Scratch Org and DevHub Org but failing with Sanbox
Hi All,

I am getting the below error when I am trying to run a build in Azure Devops for a Salesforce deployment. 

Does any one know how to specify ANT_OPTS in Azure Devops to avoid this error ?

Any other tips or workaround is also appreciated.


BUILD FAILED
/home/vsts/work/1/s/build/build.xml:32: java.lang.OutOfMemoryError: Java heap space
    at java.util.Arrays.copyOf(Arrays.java:3236)
    at java.io.ByteArrayOutputStream.grow(ByteArrayOutputStream.java:118)
    at java.io.ByteArrayOutputStream.ensureCapacity(ByteArrayOutputStream.java:93)
    at java.io.ByteArrayOutputStream.write(ByteArrayOutputStream.java:153)
    at sun.net.www.http.PosterOutputStream.write(PosterOutputStream.java:78)
    at java.util.zip.DeflaterOutputStream.deflate(DeflaterOutputStream.java:253)
    at java.util.zip.DeflaterOutputStream.write(DeflaterOutputStream.java:211)
    at java.util.zip.GZIPOutputStream.write(GZIPOutputStream.java:145)
    at sun.nio.cs.StreamEncoder.writeBytes(StreamEncoder.java:221)
    at sun.nio.cs.StreamEncoder.implWrite(StreamEncoder.java:282)
    at sun.nio.cs.StreamEncoder.write(StreamEncoder.java:125)
    at sun.nio.cs.StreamEncoder.write(StreamEncoder.java:135)
    at java.io.OutputStreamWriter.write(OutputStreamWriter.java:220)
    at java.io.Writer.write(Writer.java:157)
    at com.sforce.ws.parser.MXSerializer.writeElementContent(MXSerializer.java:1005)
    at com.sforce.ws.parser.MXSerializer.text(MXSerializer.java:802)
    at com.sforce.ws.parser.XmlOutputStream.writeText(XmlOutputStream.java:103)
    at com.sforce.ws.bind.TypeMapper.writeSimpleType(TypeMapper.java:306)
    at com.sforce.ws.bind.TypeMapper.writeSingleObject(TypeMapper.java:397)
    at com.sforce.ws.bind.TypeMapper.writeObject(TypeMapper.java:369)
    at com.sforce.soap.metadata.Deploy_element.writeFieldZipFile(Deploy_element.java:51)
    at com.sforce.soap.metadata.Deploy_element.writeFields1(Deploy_element.java:129)
    at com.sforce.soap.metadata.Deploy_element.writeFields(Deploy_element.java:97)
    at com.sforce.soap.metadata.Deploy_element.write(Deploy_element.java:90)
    at com.sforce.ws.transport.SoapConnection.writeBody(SoapConnection.java:366)
    at com.sforce.ws.transport.SoapConnection.sendRequest(SoapConnection.java:337)
    at com.sforce.ws.transport.SoapConnection.send(SoapConnection.java:96)
    at com.sforce.soap.metadata.MetadataConnection.deploy(MetadataConnection.java:351)
    at com.salesforce.ant.DeployTask.submitMessage(DeployTask.java:326)
    at com.salesforce.ant.SFDCMDAPIAntTaskRunner.runTask(SFDCMDAPIAntTaskRunner.java:29)
    at com.salesforce.ant.DeployTask.execute(DeployTask.java:63)
    at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:293)
Total time: 28 seconds
The process '/usr/bin/ant' failed with exit code 1
##[error]Error: The process '/usr/bin/ant' failed with exit code 1

Thanks
Natraj
Hello All,
I'm extremely new to lightning components and trying to replace some of our custom javascript buttons with lightning compatible options.  One button takes ownership of a lead.  I found a post that does something similar for cases and tried to modify it for my purpose: https://learnownlightning.blogspot.com/2018/01/change-owner-update-record-using.html

It seems to be doing the record update based on apex code, but it launches a quickaction screen with a cancel button that doens't go away.  I've seen it posted that you can use 
$A.get("e.force:closeQuickAction").fire();
It is not working for me.  I'm not sure if I'm not puting that code in the right place but I'm hoping someone can help me figure out a way to click the quick action button, have the lead change ownership, and that's it.

Here is my code so far:
Component:
<aura:component implements="force:lightningQuickAction,force:hasRecordId" controller="LightningComponent_MoveToMarketing" access="global" >
<aura:handler name="init" value="{!this}" action="{!c.doInit}"/>    
</aura:component>
Controller:
({
 doInit : function(component, event, helper) {
        var leadId = component.get("v.recordId");
        var action = component.get("c.changeOwnerMethod");
        action.setParams({
            leadId : leadId
        });
        action.setCallback(this, function(response) {
            if(response.getState() === "SUCCESS") {
                console.log("Lead Owner Changed To Current login User");
             var rec = response.getReturnValue();
             console.log(rec.OwnerId);
            }
        });
        $A.enqueueAction(action);
$A.get("e.force:closeQuickAction").fire();
        $A.get('e.force:refreshView').fire();
 }
})

Apex Class:
public class LightningComponent_MoveToMarketing {

    @AuraEnabled
    public static Lead changeOwnerMethod(Id leadId) {
        if(leadId != null) {
            Lead l = [SELECT OwnerId FROM Lead WHERE Id = :leadId];
         l.OwnerId = UserInfo.getUserId();
//update case Ownerid with loggedin userid.
            update l;
            return l;
        }
        return null;
    }

}

Any ideas?
 
Does anybody know how to pass variable values to ANT task in Azure Devops?
When look into my task logs, I can see the Pipeline variables been passed, but looks like it's trying to overwrite them with the values I manually entered in the build.properties file.

How to I dynamically pass the value of my Pipeline variables into the build.properties file?
  • August 26, 2019
  • Like
  • 0
I built a custom class and method to return the aggregate data to plot a chart using LWC.  For the purpose of example, I hardcode the AccountId for now.
public with sharing class lwcLifetimeSpendingController {
    @AuraEnabled (cacheable=true)
    public static List<AggregateResult> getAccountLifetimeSpending(){
        return [SELECT SUM(Service_Amount__c) Service, SUM(Subscription_Booking__c) Subscription  FROM Opportunity WHERE accountid = '0018000001G9dZUAAZ' and isclosed=true and iswon=true];
    }
}

Here's my JS file.  How do I retrieve the aggregate values from the custom apex controller and use in the JS?  I tried getSObjectValue, but that did not work as it worked only with field data from the return Object.
import { LightningElement,track,wire } from 'lwc';
import { getSObjectValue } from '@salesforce/apex';
import { loadScript } from 'lightning/platformResourceLoader';
import chartjs from '@salesforce/resourceUrl/chart';
import getAccountLifetimeSpending from '@salesforce/apex/lwcLifetimeSpendingController.getAccountLifetimeSpending';

const generateRandomNumber = () => {
    return Math.round(Math.random() * 100);
};

export default class LifetimeSpending extends LightningElement {    
    @wire(getAccountLifetimeSpending) lifetimeAggregateResult;
    @track error;
    
     //getSObjectValue does not work in this scenario
} //end export

Here's the sample of the HTML file
<template>
    <lightning-card title="Lifetime Spending" icon-name="custom:custom19">
        <div class="slds-m-around_medium">
            <canvas class="donut" lwc:dom="manual"></canvas>
        </div>
        <template if:true={error}>
            <c-error-panel errors={error}></c-error-panel>
        </template>    
    </lightning-card>
</template>


 

Is it possible to run Azure DevOps pipelines using Salesforce DX? Presumably the sfdx cli needs to be installed, but unsure of a starting point.

I've seen a video leveraging ANT scripts, but nothing so far with sfdx.

Greetings Expert,

We are trying to Setup CI-CD  for our Org. However, while sfdx force:auth:jwt:grant on Jenkins, we are gettig the below error. Same command is working fine from local of 2 - 3 people. Jenkins is installed on UNIX based system:

+ sfdx force:auth:jwt:grant --clientid XXXXX --username XXXXX --jwtkeyfile XXXXX --setdefaultdevhubusername --instanceurl https://test.salesforce.com

ERROR: Command failed with response. - (secret-tool:20489): GLib-GObject-CRITICAL **: g_object_unref: assertion 'G_IS_OBJECT (object)' failed secret-tool: Cannot autolaunch D-Bus without X11 $DISPLAY

Section from Jenkinsfile:

if (isUnix()) {
sh '''
export SFDX_USE_GENERIC_KEYCHAIN=true
echo Above Set Value: $SFDX_USE_GENERIC_KEYCHAIN
sfdx force:org:list
echo Shell is: $SHELL
which secret-tool
which sfdx
force:auth:jwt:grant --clientid XXXXX --username XXXXX --jwtkeyfile XXXXX --setdefaultdevhubusername --instanceurl https://test.salesforce.com '''
}

Any setting which we ccould apply on Jenkins server to resolve the Issue ?... Appreciate your assistance with this.

Hey guys,

i am not familar with javascript, but i really like how the chart.js libary looks. To get started i want to create some cool Salesforce Dashboards with chart.js. I have already create a visualforce Page to show a simple bar chart. Now, i am looking for a way to get the controller variable to the javascript function : 
http://www.chartjs.org/docs/latest/

This is the javascript Code: 
var ctx = document.getElementById("myChart").getContext('2d');
var myChart = new Chart(ctx, {
    type: 'bar',
    data: {
        labels: ["M1", "M2", "M3", "M4", "M5", "M6"],
        datasets: [{
            label: '# of Votes',
            data: [12, 19, 3, 5, 2, 3],   
            backgroundColor: [
                'rgba(255, 99, 132, 0.2)',
                'rgba(54, 162, 235, 0.2)',
                'rgba(255, 206, 86, 0.2)',
                'rgba(75, 192, 192, 0.2)',
                'rgba(153, 102, 255, 0.2)',
                'rgba(255, 159, 64, 0.2)'
            ],
            borderColor: [
                'rgba(255,99,132,1)',
                'rgba(54, 162, 235, 1)',
                'rgba(255, 206, 86, 1)',
                'rgba(75, 192, 192, 1)',
                'rgba(153, 102, 255, 1)',
                'rgba(255, 159, 64, 1)'
            ],
            borderWidth: 1
        }]
    },
    options: {
        scales: {
            yAxes: [{
                ticks: {
                    beginAtZero:true
                }
            }]
        }
    }
});
</script>
How can i change the label and dataset with controller variables ? My idea is to create a simple list and transform the list to string. Does this work ? 

Thanks for help guys. I cant find any help for chart.js and visualforce...

Greetings,

Marry





 
I have 2 lightning components:
The first one is a table which has 4 columns and we can add or delete rows. 
The second one is a report which displays data from one of the coloumns.
How do I achieve this? Do I need to fire an event on the save method?

Here's my first component:
<aura:component implements="force:appHostable,flexipage:availableForAllPageTypes,flexipage:availableForRecordHome,force:hasRecordId,forceCommunity:availableForAllPageTypes,force:lightningQuickAction" access="global" controller="LC57_AiPotenitalRevenueClass">
    
    <aura:attribute name="showHidePlayer" type="boolean" default="false" description="To Toggle the table" /> 
    <aura:attribute name="qualificationList" type="APR_AccountPotentialRevenue__c[]" description="To hold the data list" />
    <aura:attribute name="editMode" type="Boolean"  description="To enable Edit Mode"/>
    <aura:attribute name="lockQualificationItem" type="Boolean" description="To toggle the delete and edit Button" default="false"/>
    <aura:attribute name="recordId" type="String" description="Fetch the Current page Id" />
    <aura:attribute name="scope" type="String" description="Selected scope value"/>
    <aura:attribute name="fieldLabelsMap" type="Object" description="Keeps labels of column headers"/>
    <aura:attribute name="service" type="APR_AccountPotentialRevenue__c" default="{'sobjectType': 'APR_AccountPotentialRevenue__c',
                                                                                  'Service__c': '',                                                                  
                                                                                  }"/>
    <aura:attribute name="Brandlist" type="String[]" description="Display User Brand value"/>
    <aura:attribute name="newCriterion" type="APR_AccountPotentialRevenue__c" description="New criterion definition attribute"/>
    <!--<aura:registerEvent name="navigate" type="c:loadChart"/>-->
    <!-- HELPER ATTRIBUTES -->
    <aura:attribute name="reInitialize" type="Boolean" description="Helper to reinitialize lookup component" default="false"/>
    
    <!-- HANDLERS -->
    <aura:handler name="init" value="{!this}" action="{!c.doInit}"/>  
    
    <div class="slds-page-header">
        <div onclick="{!c.toggle}">         
            <aura:if isTrue="{!v.showHidePlayer == False}">
                <lightning:icon iconName="utility:right" size="small" />
            </aura:if>
            <aura:if isTrue="{!v.showHidePlayer}">
                <lightning:icon iconName="utility:down" size="small" />  
            </aura:if>            
        </div> 
        <div  class="slds-text-heading--label align">
            Dépense client
        </div> 
        
    </div>
    
    
    
    
    <div aura:id="text">
        
        <div class="slds-scrollable">
            <table class="slds-table slds-table_bordered table-condensed slds-table_cell-buffer"> 
                <thead >
                    <tr class="slds-text-title_caps">
                        <th class="thead"  scope="col">
                            <div class="slds-truncate">{!v.fieldLabelsMap.Brand__c}</div>
                        </th>
                        <th class="thead"  scope="col">
                            <div class="slds-truncate" title="Competitor Name">{!v.fieldLabelsMap.Service__c}</div>
                        </th>
                        <th class="thead"  scope="col">
                            <div class="slds-truncate" title="Competitor Name">{!v.fieldLabelsMap.Turnover__c}</div>
                        </th>
                        <th class="thead" scope="col">
                            <div class="slds-truncate" title="Action">{!v.fieldLabelsMap.Comments__c}</div>
                        </th>
                        <th class="thead" scope="col">
                            <div class="slds-truncate" title="Action">{!$Label.c.PIS_Modified_by_Date}</div>
                        </th>
                    </tr>
                </thead> 
                <tbody>
                    <tr> 
                        <td>
                            <ui:inputSelect disabled="true" class="slds-select" aura:id="brand" >
                                <aura:iteration items="{!v.Brandlist}" var="brand">
                                    <ui:inputSelectOption value="{!v.newCriterion.Chosen_Brand__c}" text="{!brand}" label="{!brand}"/>
                                </aura:iteration>
                            </ui:inputSelect>
                        </td>
                        <td>
                            <ui:inputselect class="slds-input" aura:id="ChooseBrand"  value="{!v.newCriterion.Service__c}"  required="true"/> 
                        </td>
                        <td>
                            <ui:inputText class="slds-input" value="{!v.newCriterion.Turnover__c}"  />
                        </td>
                        <td>
                            <ui:inputText class="slds-input slds-cell-wrap" value="{!v.newCriterion.Comments__c}"/>
                        </td>
                        <td></td>
                        <td></td>
                        <td></td>
                        <td>
                            
                            <button type="button" class="slds-button slds-button--icon-border-filled"
                                    onclick="{!c.save}" >
                                <lightning:icon iconName="utility:check" size="small" class="fillGreenIcon"/>
                            </button>
                            <button type="button" class="slds-button slds-button--icon-border-filled"
                                    onclick="{!c.cancel}">
                                <lightning:icon iconName="utility:undo" size="small" class="fillGreenIcon"/>
                            </button>
                            
                        </td>
                    </tr>
                    
                    <aura:if isTrue="{!v.qualificationList.length > 0}">
                        <aura:iteration aura:id="trial" items="{!v.qualificationList}" var="item" indexVar="i">
                            <tr id="{!i}" data-index="{!i}">
                                
                                <td class="slds-cell-wrap">
                                    <div>
                                        <ui:outputRichText class="slds-input"  value="{!item.profileofInterestRecord.Brand_Logo__c}"/>  
                                    </div>    
                                </td>     
                                <td class="slds-cell-wrap">
                                    <ui:OutputText class="slds-input"  value="{!item.profileofInterestRecord.Service__c}"/>  
                                </td> 
                                <td class="slds-cell-wrap">
                                    <ui:outputText class="slds-input" aura:id="levels" value="{!item.profileofInterestRecord.Turnover__c  }" />
                                </td>
                                <td class="slds-cell-wrap">
                                    <ui:outputText class="slds-input" aura:id="levels" value="{!item.profileofInterestRecord.Comments__c  }" />
                                </td>
                                <td  colspan="2">
                                    <div>
                                        <lightning:icon iconName="action:add_contact" size="xx-small" alternativeText="Indicates approval"/>                                           
                                        <ui:outputText aura:id="levels" value="{!item.profileofInterestRecord.LastModifiedBy.Name}"/>
                                        <ui:OutputDate aura:id="levels" value="{!item.profileofInterestRecord.LastModifiedDate }"/>                                           
                                    </div>
                                    
                                </td>   
                                <td>
                                </td>
                                <td>
                                    <button aura:id="editButton" type="button"
                                            class="slds-button slds-button--icon-border-filled"
                                            onclick="{!c.editCriterion}"
                                            >
                                        <lightning:icon iconName="utility:edit" size="small" class="fillGreenIcon"/>
                                    </button>
                                    <button aura:id="deleteButton" type="button"
                                            class="slds-button slds-button--icon-border-filled" 
                                            onclick="{!c.deleteCriterion}" >
                                        <lightning:icon iconName="utility:delete" size="small" class="fillRedIcon"/>
                                    </button>
                                </td> 
                                
                            </tr>
                       </aura:iteration>    
                    </aura:if> 
                </tbody>
            </table>   
        </div>      
        
    </div>       
    
</aura:component>

And the second component is:
<aura:component controller="LC58_AiIndicatorsClass" implements="flexipage:availableForAllPageTypes,flexipage:availableForRecordHome,force:hasRecordId,forceCommunity:availableForAllPageTypes" access="global" >
    <ltng:require scripts="{!$Resource.ChartJS}" afterScriptsLoaded="{!c.scriptsLoaded}"/>
    <aura:attribute name="revenue" type="double"/>
    <aura:handler name="init" value="{!this}" action="{!c.doInit}"/>
    <aura:attribute name="clist" type="List" access="GLOBAL"/> 
    <div class="icon-style slds-align--absolute-center">
        <lightning:formattedNumber value="{!v.revenue}" style="currency" currencyCode="USD"/>    
    </div>
    <div class="icon-style1">
        <canvas id="myChart" height="200"></canvas>
    </div>   
</aura:component>

 
I am attempting to complete the aforementioned trailhead step on a Windows 10 machine. When I attempt to test the setup via sfdx force:auth:jwt:grant, I get the following error:

This org appears to have a problem with its OAuth configuration. Reason: invalid_grant - user hasn't approved this consumer

When it gives the error, SFDX provides a list of possible issues to check for. I have done so repeatedly. I have gone through the Trailhead step backwards and forwards. Every other part seems to work just fine. This part does not. Unfortuntely the Google results haven't really been all that helpful, so now I turn to you oh great and powerful forum. What do you say?
This is an error under "Create a Self-Signed SSL Certificate and Private Key
Creating"

On Step 2: 
openssl genrsa -des3 -passout pass:x -out server.pass.key 2048
I get the error of "You must type in 4 to 1023 characters" and even if I change that, the generated server.pass.key i still empty so when I run Step 3
 
openssl rsa -passin pass:x -in server.pass.key -out server.key

I get the error of 
 
unable to load Private Key
139667048820672:error:0906D06C:PEM routines:PEM_read_bio:no start line:crypto/pem/pem_lib.c:691:Expecting: ANY PRIVATE KEY

I'm using arch linux if that helps? Has anyone encountered this issue? As far as I can tell this is a new module since CI was announced not too long ago
I noticed that there is no link in this Trailhead for OpenSSL for Windows.  It simpy says "Windows complete package.exe installer" with no link. What's the suggestion or recommendation for those of us on Windows?

Thank you.
Hi,

I am at the step Create a custom classifier/Set up authorization/Generate a JWT token.
When I run the script jwt.sh I get a response:
             Your access token response:
              {"message":"Invalid JWT token"}

I am on win10 64bit but don't have the anniversary update so I don't have bash coming with win10.
I have bash came with git.
As I don't have a valid JWT token I can not continue to "Step 1: Create the Dataset".

Please help.


Here is a more detailed output and my changes to the jwt.sh script:

Script output (with my password changed)


-------------------------------------------------------------------------------------------

$ ./jwt.sh ./00D0Y0000008amn.jks lajos.kelemen@accenture.com 3600 https://api.metamind.io
Enter destination keystore password:  my_pass
Enter source keystore password:  my_pass
Existing entry alias lkelemen_sf_devcert exists, overwrite? [no]:  yes
Entry for alias lkelemen_sf_devcert successfully imported.
Import command completed:  1 entries successfully imported, 0 entries failed or cancelled
[Storing privateKey.p12]
MAC verified OK

Generated Assertion:

eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJsYWpvcy5rZWxlbWVuQGFjY2VudHVyZS5jb20iLCJzdWIiOiJsYWpvcy5rZWxlbWVuQGFjY2VudHVyZS5jb20iLCJhdWQiOiJodHRwczovL2FwaS5tZXRhbWluZC5pby92MS9vYXV0aDIvdG9rZW4iLCJleHAiOjE0NzYwODAzMTksImlhdCI6MTQ3NjA3NjcxOX0.EcvaPYv3bfA_HNsa_5tNFz6iajvprCee-kNfdSNMPHpgeMgWU3Z0LFt8AojJLNYZIzNydNarDtUbDkqhdpB_c2Ahi2xUhiy_ATnWaUWNrykROsv7dVu_l8smIb9s08N4mcllsDorNWcM9XWmVDlVgq4oegaeQhq2yCOuxn3jAb5IRlurXjSY125FTJs_3oE06vkZYieg6kxQYoeZiWvGfwhdgEB-szutrrXFgUEVKa5U_qj5HFQYlHV7yAcbRTxCc5vOwaAv7qCrjdFCfsmWXPlk-65DSoAFUXK12j6HbB-hHRimNrf-4lLz0mxMmDNC5HuLMHG8BOZMp6PDc19QBg

Your access token response:

{"message":"Invalid JWT token"}

-------------------------------------------------------------------------------------------

my script changes:

openssl pkcs12 -in privateKey.p12 -nocerts -nodes -out private_key
 
changed to (added -passin pass at the end)

openssl pkcs12 -in privateKey.p12 -nocerts -nodes -out private_key -passin pass:my_pass

-------------------------------------------------------------------------------------------
curl -H "Content-type: application/x-www-form-urlencoded" -X POST "$4/v1/oauth2/token" -d \
"grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&assertion=$jwt3.$jwt5" ; echo

changed to (added -k parameter to accept self signed certs?)

curl -k -H "Content-type: application/x-www-form-urlencoded" -X POST "$4/v1/oauth2/token" -d \
"grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&assertion=$jwt3.$jwt5" ; echo


 
HI All,

I have a Requirment Integration salesforce with Microsoft Azure Any Ideas appreciated.

Thanks,
Hareesh

Issue with SalesForce Cert.
---------------------------

The Salesforce cert is dumped below with linenumbers in text using
"openssl x509 -text -noout | nl" for convenience.

Line 38-41 show the Authority Key Identifier - this is used to identify
the public key used to sign this cert (which in practice disambiguates two
potential issuing certificates with the same subject id, but different
keys.)

This can be done in two separate ways

(a) using a "keyid" to specify the key itself, matching a "subject
key" in the issuer's cert

(b) using a serial number and issuer name.

(Note in the second case, that's the issuer's issuer, not the subject's
issuer, and for a self-signed cert, the subject, issuer, and issuer's
issuer are all the same cert.)

Lines 38-41 therefore give two distinct ways to locate the issuing
certificate. It's either

(a) one with subject key Id
A6:E0:FA:0A:4B:47:F5:E0:7F:69:BA:E3:62:5E:D7:17:FB:B4:D5:59

(b) one with serial:01:3E:54:E9:2C:EE:00:00:00:00:5A:A5:E1:D7
and issuer /CN=BT Consumer Complaints/OU=00DW0000003idkb/
O=Salesforce.com/L=San Francisco/ST=CA/C=USA

Look at the serial number of the subject cert:
01:3e:54:e9:2c:ca:00:00:00:00:5a:a5:e1:d7

This is actually _not_ the same as the subject key Id in the subject cert
(the 6th octet differs - "CA" vs "EE"), so by that definition, the key
used to sign this certificate is not the same as the subject's own key,
certificate, and it is not a self-signed cert. This issue causes the
OpenSSL stack to fail, and reasonably so.

It's done this since 2006, at least: If another product is using OpenSSL,
and is _not_ failing this verification of such a problematic salesforce
cert, then it may not be verifying peer certificates properly at all
(eg, by installing a handler with SSL_CTX_set_cert_verify_callback() that
does not properly verify the cert chain, or calling SSL_CTX_set_verify()
with SSL_VERIFY_NONE)

Cert follows:

1 Certificate:
2 Data&colon;
3 Version: 3 (0x2)
4 Serial Number:
5 01:3e:54:e9:2c:ca:00:00:00:00:5a:a5:e1:d7
6 Signature Algorithm: sha1WithRSAEncryption
7 Issuer: CN=BT Consumer Complaints, OU=00DW0000003idkb, O=Salesforce.com, L=San Francisco, ST=CA, C=USA
8 Validity
9 Not Before: Apr 29 08:29:27 2013 GMT
10 Not After : Apr 29 08:29:27 2015 GMT
11 Subject: CN=BT Consumer Complaints, OU=00DW0000003idkb, O=Salesforce.com, L=San Francisco, ST=CA, C=USA
12 Subject Public Key Info:
13 Public Key Algorithm: rsaEncryption
14 Public-Key: (2048 bit)
15 Modulus:
16 00:aa:9f:24:20:28:ef:a5:b0:2b:18:df:69:cf:51:
17 f6:bc:5a:83:44:1d:9a:4a:50:95:c3:8a:21:c1:6f:
18 a0:f6:ae:13:d9:0a:d2:72:22:0c:f3:95:84:af:05:
19 cb:ce:42:b4:52:48:1e:fa:ae:14:a0:b8:7a:31:d3:
20 de:d5:c0:66:9e:2d:d4:74:32:ad:35:91:cf:6d:30:
21 8d:7c:1c:48:8e:af:a3:46:7d:2e:e2:c8:4d:0e:c7:
22 bb:64:54:0c:6f:8e:f0:c5:be:3d:17:67:b2:45:b0:
23 45:57:d8:36:e7:87:0d:1e:5e:71:c0:d0:f7:6f:91:
24 90:13:ef:71:34:bd:73:82:49:86:bb:8c:fe:72:8c:
25 2a:26:67:1d:c3:16:e4:d9:0a:9d:d0:58:55:6e:78:
26 1d:48:6b:3a:f2:00:76:a5:86:6e:f3:64:c5:8a:05:
27 08:c6:5f:3d:dc:07:72:9c:82:72:bd:2f:5d:69:ca:
28 d3:82:f1:7a:43:4a:c4:2d:3d:cf:5e:6b:c7:07:0a:
29 5d:5d:86:41:28:cf:b9:15:2f:2f:78:0f:58:85:01:
30 80:69:54:37:32:2e:86:cf:53:d8:63:42:f7:cf:0e:
31 53:c6:14:d0:be:98:36:bc:2d:f8:80:35:fb:0c:ab:
32 b7:b8:44:44:fb:51:8c:d1:ef:b3:5a:03:c0:a4:af:
33 98:df
34 Exponent: 65537 (0x10001)
35 X509v3 extensions:
36 X509v3 Subject Key Identifier:
37 A6:E0:FA:0A:4B:47:F5:E0:7F:69:BA:E3:62:5E:D7:17:FB:B4:D5:59
38 X509v3 Authority Key Identifier:
39 keyid:A6:E0:FA:0A:4B:47:F5:E0:7F:69:BA:E3:62:5E:D7:17:FB:B4:D5:59
40 DirName:/CN=BT Consumer Complaints/OU=00DW0000003idkb/O=Salesforce.com/L=San Francisco/ST=CA/C=USA
41 serial:01:3E:54:E9:2C:EE:00:00:00:00:5A:A5:E1:D7

42 X509v3 Basic Constraints: critical
43 CA:TRUE
44 Signature Algorithm: sha1WithRSAEncryption
45 92:9b:4e:88:f9:af:1f:d7:ef:e8:dc:d3:21:d0:16:4f:dc:e3:
46 2b:51:08:9f:f1:79:65:7c:39:16:42:32:13:78:ec:2e:da:c4:
47 b1:21:9e:f3:74:11:1e:d9:57:9b:d4:73:16:92:c3:49:e9:79:
48 11:ee:99:b9:71:f9:7c:92:e2:c7:35:65:b4:dc:32:cd:f8:3a:
49 c9:9b:90:d2:e0:7c:f5:ca:d7:28:57:d6:39:2b:4c:f2:4a:fe:
50 53:b6:49:f4:71:34:54:35:c1:5b:fc:d3:c5:4d:cb:7c:46:c1:
51 5a:68:e1:b4:c2:97:98:45:7e:54:b0:6d:40:c1:67:1a:8d:7a:
52 db:cf:64:7a:ba:f6:9e:e9:06:c4:83:03:84:ea:ed:77:99:b9:
53 16:67:92:a7:f9:bf:0f:b2:a9:b7:26:b3:3e:a1:15:f4:84:eb:
54 8a:04:2f:6f:85:d3:4e:a6:ff:fe:7a:cd:8b:13:0e:7a:36:04:
55 4d:34:77:49:68:f6:95:ea:77:ec:43:37:ab:05:ae:c9:16:c0:
56 51:8e:f4:f1:84:81:9b:e3:48:7d:97:c3:46:82:7c:e8:5e:9d:
57 34:7b:b9:1b:85:05:68:1b:36:8c:0d:9f:a3:1c:5d:62:d2:d5:
58 ef:35:c6:ce:58:b9:88:7b:42:05:3c:ff:a9:05:bd:e2:8e:78:
59 50:dd:78:1f

  • September 12, 2013
  • Like
  • 0

I have been trying to connect Salesforce and Google API using server to server application.

 

Intent :- To communicate data between Salesforce and Google Spreadsheet which is hosted in Google Sites and using some Google Forms, Google scripts and triggers to update data.

 

So, for doing this I need a server to server application model from Google as it wouldnt require a consent from user while its communicating data. for doing this I need to create a JWT and pass it to Google to get the token and proceed with the next steps.

 

JWT for Google requires a RSA with SHA256 signing of the msg using the private key that google has provided in the certificate when I created the server to server application in Google.

I havent found this info anywhere till now :(

In salesforce, we have a crypto class in which can sign with RSA SHA1 (or) generate digest with SHA256, I tried generating a digest using SHA256 and signing that digest usng RSA and the private key given by google. Even thats not working.

 

Google isnt accepting my assertion values (JWT) and its returning an invalid Grant message.

 

I have seen that Jeff douglas has posted some information about this here :-http://blog.jeffdouglas.com/2010/07/06/using-rsa-sha1-with-salesforce-crypto-class/

But unfortunately he has mentioned about domain model and asking us to upload a certificate to google, which i dont want to do or which is not my scenario.

 

Also Google requires a UT8 base64 URL encoded value at all places as mentioned in this link :-https://developers.google.com/accounts/docs/OAuth2ServiceAccount#libraries But salesforce has a separate URL encoding and a separate base64encoding method available in the EncodingUtil class.

 

I have a C# dotnet application which is generating the same value and its able to hit Google and get the value properly. But uses the certificate file and gets the privatekey directly. I used openssl to retrieve the privatekey from the .p12 certificate file provided by Google and have pasted it in my code. I am sure there is some problem in the signing part, because when I compare the values generated by my .NET application and Salesforce Apex code, its returning correct values, but when it comes to the signature part, the length is also same for the returned data (signature) from both .NET and SF but Google returns an invalid grant while calling from SF but returns a bearer token when I call it from my .NET application.

 

public class TestRestAPICall
{
    public class JWTClaimSet
    {
       public string iss {get;set;}
       public string scope {get;set;}
       public string aud {get;set;}
       public Long exp {get;set;}
       public Long iat {get;set;}
       //public string prn {get;set;}
    }

//@future (callout=true)
public static void LoginToGoogle()
{
    //Set your username and password here        
    String clientId = '851234545868.apps.googleusercontent.com';

    //Construct HTTP request and response
    Http http = new Http();
    HttpRequest req = new HttpRequest();
    HttpResponse res = new HttpResponse();


    String JWTHeader =  '{"typ":"JWT","alg":"RS256"}';
    //String Base64EncodedJWTHeader = 'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9'; //To encode later using code

    //Taken from .net application
// Since the information is going to be same, I have encoded it already in .NET and using it here
    String Base64EncodedJWTHeader = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9';
// Salesforce returns time in milliseconds, so we are dividing it by 1000 to set the seconds value instead of milliseconds value
    Long expires_at = math.roundToLong(DateTime.now().addMinutes(40).getTime() / 1000);
    Long issued_at = math.roundToLong(DateTime.now().addSeconds(-2).getTime() / 1000);
    //Long issued_at = 1372276504;
    //Long Expires_at = 1372279804;

    JWTClaimSet JWT = new JWTClaimSet();
    //JWT.prn = username;
    JWT.iss = '851234545868@developer.gserviceaccount.com';
    JWT.scope = 'https://www.googleapis.com/auth/drive.file';
    JWT.aud = 'https://accounts.google.com/o/oauth2/token';
    JWT.iat = issued_at;
    JWT.exp = expires_at;

    String strJWTJSON = JSON.Serialize(JWT);
    system.debug('Unencoded claimset::'+strJWTJSON);


    Blob ClaimsetBlob = Blob.valueOf(strJWTJSON);
    String Base64EncodedClaimset = EncodingUtil.base64Encode(ClaimsetBlob);
    //Base64EncodedClaimset = PerformPostBase64Encode(Base64EncodedClaimset);
    system.debug('Base64 Encoded Claimset::'+Base64EncodedClaimset);

    // constructing the base64 encoded string to sign it
    string Base64EncodedString = Base64EncodedJWTHeader + '.' + Base64EncodedClaimset;


    // Steps to sign the base64Encoded string
    String algorithmName = 'RSA';
    String key = 'MIICXAIBAAKBgQCi16h+5TeQU5Fo0DlR6+YmrzYXZ7DLxz+dBEnB8Hj0gznqlz8p7nQ7I4AV/SfiJQ6JbU16sKS5IW7Hob5ieW1DfwxYZeCSBPbEkt7eASrI8xqGU5RVewaQivY3vO+avgSSUT+ZU243XsDvZJQlkE3e46FhBvFedDQvuk2iEfgdxQIDAQABAoGAFaO882f4c0h3qUsKYvWLNxbPhFq2Js5KiM4aEximqi+KEb+ZmDPk5Dr6eXGTzDyKav7IbgZtTWDA/OxkhWeHelsMB9LqBq50L6hLHTK4hHecPrT3oN4GviUXh5y5Vt479A1TopjLKdt7V4AnAs0HEWJzar/euUa+T9eODPWPFP0CQQDWQeK2cqzWSVHUpkufp7a0Sc2RvfcIpOf8kRFBLnKiFGr7BscLz6qsaG1M8TyUNMrCquwLSNSDMvPjl6sCjgRPAkEAwpFx8+lspjN0yV5M5XHPmnoddTHwV/8QHoccMBBq0ZMFs2m1E/rFhwMHRBiFN6flbze8src7YnOmmtYqsGizqwJAfqoEtYel1ikST3zgSEqGIJ9hAEAlwt56pz27zaT/8AHSHQUstzbV14cE1u/muFddZyhU03cC62078djAKIp80QJAKMMT3ofOrVsmYnGRJpibZ7+hoEXgFm9nTx37N86YsmNc1GOW/iKRc2GdChUhA7H3DT/eForwtAWKp/Gqa97jlQJBAKjKOIKvdYS9fTpCzs1nUHg9rvVartRR5xxwLH57bBincuSJSBGjwd1FInAh2tgiUGPWGPsplShP87wao9+n9VQ=';
    Blob privateKey = EncodingUtil.base64Decode(key);

    Blob input = Blob.valueOf(Base64EncodedString);
    //Blob SHA256InputBlob = Crypto.generateDigest('SHA-256',input);

    Blob Blobsign = Crypto.sign(algorithmName, input , privateKey);


    // The following line is just for debugging and viewing the blob data in signature as string and its not used anywhere
    String signature = EncodingUtil.urlEncode(EncodingUtil.convertToHex(Blobsign),'UTF-8');

    system.debug('Unencoded signature ::'+signature);
    String base64EncodedSignature = EncodingUtil.base64Encode(Blobsign); 
    //base64EncodedSignature = PerformPostBase64Encode(base64EncodedSignature);
    system.debug('Base 64 encoded signature ::'+base64EncodedSignature );

    system.debug('Encoded assertion : ' + Base64EncodedString+'.'+base64EncodedSignature);

    string URLEncodedUTF8GrantType = encodingUtil.urlEncode('urn:ietf:params:oauth:grant-type:jwt-bearer','UTF-8');
    string URLEncodedUTF8Assertion = encodingUtil.urlEncode(Base64EncodedString+'.'+base64EncodedSignature,'UTF-8');        

    system.debug('URLEncodedUTF8GrantType : ' + URLEncodedUTF8GrantType);
    system.debug('URLEncodedUTF8Assertion : ' + URLEncodedUTF8Assertion);

    //Making the call out
    req.setEndpoint('https://accounts.google.com/o/oauth2/token');
    req.setMethod('POST');
    //req.setHeader('Content-Length', '-1');
    req.setHeader('Content-Type','application/x-www-form-urlencoded');
    //req.setHeader('grant_type',URLEncodedUTF8GrantType);
    //req.setHeader('assertion',URLEncodedUTF8Assertion);
    req.setBody('grant_type='+URLEncodedUTF8GrantType+'&assertion='+URLEncodedUTF8Assertion);
    res = http.send(req);
    system.debug('Response : '+res.getBody());
}

 public static String PerformPostBase64Encode(String s)
 {
    s = s.Replace('+', '-');
    s = s.Replace('/', '_');
    s = s.Split('=')[0]; // Remove any trailing '='s
    return s;
 }
}

 

 

I have also posted my problem at stackexchange, it would be great if anyone could help me out :-

 

http://salesforce.stackexchange.com/questions/13301/connect-apex-and-google-api-using-jwt-to-retrieve-oauth-2-0-token

Hi,

 

Is there a way to get the namespace prefix of a Salesforce organization using Apex code ?

 

I have developed an AppExchange application. This application need to know the namespace of the Salesforce organization to create a record.

 

Thanks

Viraj

  • June 17, 2010
  • Like
  • 0