Quantcast
Channel: Active questions tagged lightning-experience - Salesforce Stack Exchange
Viewing all articles
Browse latest Browse all 3022

SAML(IDP) Integration - getting access denied in Salesforce

$
0
0

We are trying to implement single sign-on functionality using the SAML 2.0 with HTTP post binding from a lightning community. But after post request we are getting access denied in HTTP callback. We have also validated SAML request body, signature, digest value and other required information which we are sending in post request. All information are correct but we are still getting 302 error message in post request.

Notes:We added SF Signature generation based on the CertificateWe validated the Signature using the SF Signature Validation methodWe properly assign the all required information

Lightning Component:

SamlIdpDemo.cmp

<aura:component implements="force:appHostable,flexipage:availableForAllPageTypes,flexipage:availableForRecordHome,force:hasRecordId,forceCommunity:availableForAllPageTypes,force:lightningQuickAction"                 access="global"                controller="SamlIdpDemoCtrl"><!--attribute--><aura:attribute name='samleResponse' type="String"/><aura:attribute name="showSpinner" type="boolean" default="false"/><!--Handler--><aura:handler name="init" value="{!this}" action="{!c.doInit}"/><!--markup--><p>SAML IDP Demo</p><div class="c-container"><aura:if isTrue="{!v.showSpinner}"><lightning:spinner alternativeText="Loading" variant="inverse" /></aura:if><lightning:layout multipleRows="true"><lightning:layoutItem size="12" padding="around-small"><div class="header-column"><lightning:textarea name="input3" label="SAML Response" value="{!v.samleResponse}" placeholder="type here..."/></div></lightning:layoutItem><lightning:layoutItem size="12" padding="around-small"><div class="header-column"><lightning:button variant="brand" label="Submit" title="Submit" onclick="{! c.handleSubmit }" /></div></lightning:layoutItem></lightning:layout></div></aura:component>

SamlIdpDemoController.js

({    doInit : function(component, event, helper) {        component.set("v.showSpinner", true);        helper.handleDoInit(component);    },    handleSubmit : function(component, event, helper) {        //get Base64 content        var content = component.get("v.samleResponse");        var form = document.createElement("form");        form.setAttribute("method", "post");        form.setAttribute("action", "https://secure3.commonbenefits.com/Exchange/SAML2/Acs");        var hiddenField = document.createElement("input");        hiddenField.setAttribute("type", "hidden");        hiddenField.setAttribute("name", "SAMLResponse");        hiddenField.setAttribute("value", content);        form.appendChild(hiddenField);        document.body.appendChild(form);        //Submit        form.submit();    }})

SamlIdpDemoHelper.js

handleDoInit : function(component) {        var action = component.get("c.getRequestBodyBase64");        action.setCallback(this, function(response) {            var state = response.getState();            if (state === "SUCCESS") {                component.set("v.samleResponse", response.getReturnValue());                component.set("v.showSpinner", false);            }else if (state === "ERROR") {                var errors = response.getError();                console.log("***error***"+errors);                component.set("v.showSpinner", false);            }        });        $A.enqueueAction(action);},

SamlIdpDemoCtrl.cls

public without sharing class SamlIdpDemoCtrl {    @AuraEnabled    public static String getRequestBodyBase64(){        String requestBody = getRequestBody();        system.debug('***requestBody***'+requestBody);        String encodedStr = EncodingUtil.base64Encode(Blob.valueOf(requestBody));        system.debug('***encodedStr***'+encodedStr);        return encodedStr;    }    public static String getRequestBody(){        Datetime currentDateTime = System.now().addDays(-1);//       String issueInstant = currentDateTime.year()+'-'+(currentDateTime.month()<10?'0':'')+currentDateTime.month()+'-'+(currentDateTime.day()<10?'0':'')+currentDateTime.day()+'T'+currentDateTime.time();        currentDateTime = currentDateTime.addDays(7);        String notOnOrAfter = currentDateTime.year()+'-'+(currentDateTime.month()<10?'0':'')+currentDateTime.month()+'-'+(currentDateTime.day()<10?'0':'')+currentDateTime.day()+'T'+currentDateTime.time();        User oUser;        for(User u : [SELECT Id, GroupId__c, SSN__c FROM USER WHERE Id=:UserInfo.getUserId()]){            oUser = u;        }        String responseId = 'id'+generateRandomString(33);        String requestBody = '';        requestBody = '<Response Destination="https://secure3.commonbenefits.com/Exchange/SAML2/Acs" ID="'+responseId+'" Version="2.0"';        requestBody += ' IssueInstant="'+issueInstant+'" xmlns="urn:oasis:names:tc:SAML:2.0:protocol">';        system.debug('***BaseURL***'+URL.getSalesforceBaseUrl().toExternalForm());        requestBody += '<Issuer xmlns="urn:oasis:names:tc:SAML:2.0:assertion">'+URL.getSalesforceBaseUrl().toExternalForm()+'</Issuer>';        requestBody += '<Status>';        requestBody += '<StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success" />';        requestBody += '</Status>';        //Assertion Start from here        String assertionBody = '';        assertionBody += '<saml2:Assertion xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" Version="2.0" ID="_68a60e20-b42a-4345-be2d-eb551e43a3ff" IssueInstant="'+issueInstant+'">';        assertionBody += '<saml2:Issuer>'+URL.getSalesforceBaseUrl().toExternalForm()+'</saml2:Issuer>';        assertionBody += '<saml2:Subject>';        assertionBody += '<saml2:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified">'+UserInfo.getName()+'</saml2:NameID>';        assertionBody += '<saml2:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">';        assertionBody += '<saml2:SubjectConfirmationData NotOnOrAfter="'+notOnOrAfter+'" Recipient="https://secure3.commonbenefits.com/Exchange/SAML2/Acs" />';        assertionBody += '</saml2:SubjectConfirmation>';        assertionBody += '</saml2:Subject>';        system.debug('***Conditions***'+notOnOrAfter);        assertionBody += '<saml2:Conditions NotOnOrAfter="'+notOnOrAfter+'">';        assertionBody += '<saml2:AudienceRestriction>';        assertionBody += '<saml2:Audience>https://secure3.commonbenefits.com/Exchange</saml2:Audience>';        assertionBody += '</saml2:AudienceRestriction>';        assertionBody += '</saml2:Conditions>';        assertionBody += '<saml2:AuthnStatement AuthnInstant="'+issueInstant+'" SessionIndex="42">';        assertionBody += '<saml2:AuthnContext>';        assertionBody += '<saml2:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified</saml2:AuthnContextClassRef>';        assertionBody += '</saml2:AuthnContext>';        assertionBody += '</saml2:AuthnStatement>';        assertionBody += '<saml2:AttributeStatement>';        assertionBody += '<saml2:Attribute Name="http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid">';        assertionBody += '<saml2:AttributeValue>'+oUser.GroupId__c+'</saml2:AttributeValue>';        assertionBody += '</saml2:Attribute>';        assertionBody += '<saml2:Attribute Name="SSN">';        assertionBody += '<saml2:AttributeValue>'+oUser.SSN__c+'</saml2:AttributeValue>';        assertionBody += '</saml2:Attribute>';        assertionBody += '</saml2:AttributeStatement>';        assertionBody += '</saml2:Assertion>';         requestBody += assertionBody;        requestBody += '</Response>';         String signature = generateXMLSignature(requestBody, responseId);        system.debug('***signature***'+signature);        requestBody = requestBody.replace('</Issuer><Status>', '</Issuer>'+signature+'<Status>');        return requestBody;    }     public static String generateXMLSignature(String docBodyString, String responseId){        Blob bodyDigest = Crypto.generateDigest('SHA256',Blob.valueOf(docBodyString));        String referenceString = '';        referenceString += '';        referenceString += '<Reference URI="#'+responseId+'">';        referenceString += '<Transforms>';        referenceString += '<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />';        referenceString += '<Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />';        referenceString += '</Transforms>';        referenceString += '<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" />';        referenceString += '<DigestValue>'+EncodingUtil.base64Encode(bodyDigest)+'</DigestValue>';        referenceString += '</Reference>';               String signedInfoString = '';        signedInfoString += '<SignedInfo>';        signedInfoString += '<CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />';        signedInfoString += '<SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" />';        signedInfoString += referenceString;        signedInfoString += '</SignedInfo>';        String algorithmName = 'RSA-SHA256';        String certificateDevName = 'SelfSignedCert_16Feb2021_172200';        //Blob siBlob = Blob.valueOf(signedInfoString);        Blob siBlob = Blob.valueOf(docBodyString);        Blob signatureValue = Crypto.signWithCertificate(algorithmName, siBlob, certificateDevName);        String signatureValueString = EncodingUtil.base64Encode(signatureValue);       String signatureString = '';       signatureString += '<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">';       signatureString += signedInfoString;        signatureString += '<SignatureValue xmlns="http://www.w3.org/2000/09/xmldsig#">'+signatureValueString+'</SignatureValue>';       signatureString += '<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">';       signatureString += '<X509Data xmlns="http://www.w3.org/2000/09/xmldsig#">';       signatureString += '<X509Certificate xmlns="http://www.w3.org/2000/09/xmldsig#">********</X509Certificate>';       signatureString += '</X509Data>';       signatureString += '</KeyInfo>';       signatureString += '</Signature>';        return signatureString;    }       public static String generateRandomString(Integer len) {        final String chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz';        String randStr = '';        while (randStr.length() < len) {            Integer idx = Math.mod(Math.abs(Crypto.getRandomInteger()), chars.length());            randStr += chars.substring(idx, idx+1);        }        return randStr;     }}

Thanks,


Viewing all articles
Browse latest Browse all 3022

Latest Images

Trending Articles



Latest Images

<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>