Nerd @ Work

When Salesforce is life!

[Salesforce / Heroku] Salesforce as Identity Provider and Heroku as Service Provider

One year from my last SSO blog post (Implementing Delegated SSO) I’m still here playing with Single Sign On, this time using SAML 2.0.

For a quick overview of the how SAML works, read SAML FEDERATION FOR DUMMIES and SAML for dummies.

We have 3 actors:

  • Client: this is your browser
  • Service Provider: this is the remote Site where you need to access your private data/services without having to log in in this portal (this is Heroku in our demo implementation)
  • Identity provider: this is the server that hosts your authentication details, which authenticates your private sessions on the Service Provider (this is Salesforce)

These actors speak to eachother to allow the client to be authenticated both in the Service Provider and the Identity Provider.

The aim of this article is to configure Salesforce as an Identity Provider using a NodeJS app hosted on Heroku as Service Provier.

Let’s say we have a Customer Community and every user should access a remote Service Provider without the need to log in again.

First let’s configure a new Community

From Setup > All Communities click on New Community, select the Salesforce Tabs + Visualforce template, select a name:

Click on the Administration tab and then to Members. Leave the System Administrator and add a customer community profile:

Click on Branding to change header image and color theme.

Click on Login & Registration to change header logo of login page and other login/logout settings.

You have setup a new community:

Setup Salesforce as Identity Provider

The next step is to setup Salesforce as Identity Provider.

Enable My Domain from Setup > Domain Managerment > My Domain.

Remember that once the My Domain subdomain is setup you cannot change it anymore.

By deploying the domain you enable it for all your ORG’s users:

  • Users will be able to login from https://yourdomain.my.salesforce.com/login
  • if you don’t change the base settings, users will still be able lo login through https:/login.salesforce.com
  • Integrations will continue to work without any problem

You can even change login brand:

Now go to Setup > Security Controls > Identity Provider click Enable Identity Provider.

Single Sign On is almost here!

For every community and the base Salesforce Identity you are provided with the SAML descriptor to configure Single Sign On on the remote Service Provider.

There is one more step to properly configure the authentication channel.

Create a connected app

From Setup > Create > Apps click on New button of the Connected Apps section.

Fill in the mandatory fields:

  • Connected App Name: name of your app
  • API Name: dev name of the app (cannot be changed once set)
  • Enable SAML: true
  • Entity Id: this is the unique identifier of your Service Provider. This field is unique across Connected Apps (any other connected app should have a different value)
  • ACS URL: this is the callback URL on your Service Provider (we’ll be configuring the app in the next chapter)
  • Subject Type: set to User ID (your user will be identified by its Salesforce ID)
  • Name ID Format: this is the format of the unique id (urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified)
  • Issuer: leave the default value

Another cool feature is the Custom Connected App Handler: you can specify an Apex class which is called when the authentication is done.

The class must extend the Auth.ConnectedAppPlugin class:

global class SamlConnectedAppPlugin extends Auth.ConnectedAppPlugin{

    global override boolean authorize(Id userId, Id connectedAppId, boolean isAdminApproved) {
        User u = [select id, First_SAML_Login__c from User where id =: userId].get(0);
        if(u.First_SAML_Login__c == null){
            u.First_SAML_Login__c = System.now();
            try{
                update u;
            }catch(exception e){
                System.debug('Exception:' + e.getMessage());
            }
        }
        return true;
    }


    global override Map customAttributes(Id userId, Map formulaDefinedAttributes) {  
        User u = [select id, Name, CommunityNickname from User where id =: userId];
        formulaDefinedAttributes.put('nickname',u.CommunityNickname);
        formulaDefinedAttributes.put('fullname',u.Name);
        return formulaDefinedAttributes;
    }
}

Where:

  • authorize(): authorized user based on custom login (e.g. you can query for a given User’s field)
  • customAttributes(): allow to specify a set of custom attributes to be sent to the Service Provider. In this example the send the user’s full name and nickname
  • refresh(): (not implemented here) is called upon token refresh (OAuth 2.0)

Configure the Service Provier

The service provider is the external App that provides a service which can be accessed only if the user if authenticated.

It will be using Salesforce as the Identity Provider (don’t you say??).

To simulate the Service Provider, here is a NodeJS app hosted on Heroku:



By clicking the Heroku Button you are redirected to the Heroku app creation:

In the Config Variables lays down the magic:

  • SAML_ENTRYPOINT: set with the value of the node md:SingleSignOnService Binding=”urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect” of the SAML descriptor for the community
  • SAML_ISSUER: set with the name you have setup in the Entity Id of your connected app
  • SAML_CERT: copy the whole certificate string in the node ds:X509Certificate of the SAML descriptor of your community
  • SAML_IDENTIFIER_FORMAT: leave with the default value urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified
  • APP_NAME: set a cool name for your service provider
  • SF_HOME: this is the base URL for your community

Then click the Deploy For Free button and wait for the magic to take place!

Your Heroku app is up and running at https://heroku_app_name.herokuapp.com

Link the Service Provider in your community

Let’s add a simple link to the community sidebar.

Click to Setup > Customize > Home > Custom links:

Create a new Home Page Component:

And add it to a new Home Page Layout tailored to your community:

Let’s test it out!

[Salesforce] The Sobject Crusade: AccountFeed

Back to the Sobject Crusade list.

Source: AccountFeed

This represents a single feed item on the Account record detail page (chatter feed).

It tracks different kind of feeds:

ActivityEvent—indirectly generated event when a user or the API adds a Task associated with a feed-enabled parent record (excluding email tasks on cases). Also occurs when a user or the API adds or updates a Task or Event associated with a case record (excluding email and call logging).

For a recurring Task with CaseFeed disabled, one event is generated for the series only. For a recurring Task with CaseFeed enabled, events are generated for the series and each occurrence.

  • AdvancedTextPost: created when a user posts a group announcement
  • ApprovalPost: generated when a user submits an approval
  • CanvasPost: a post made by a canvas app posts on a feed
  • CollaborationGroupCreated: generated when a user creates a public group
  • ContentPost: a post with an attached file
  • CreatedRecordEvent: generated when a user creates a record from the publisher
  • DashboardComponentAlert: generated when a dashboard metric or gauge exceeds a user-defined threshold
  • DashboardComponentSnapshot: created when a user posts a dashboard snapshot on a feed
  • LinkPost: a post with an attached URL
  • PollPost: a poll posted on a feed
  • ProfileSkillPost: generated when a skill is added to a user’s Chatter profile
  • QuestionPost: generated when a user posts a question
  • ReplyPost: generated when Chatter Answers posts a reply
  • RypplePost: generated when a user creates a Thanks badge in Work.com
  • TextPost: a direct text entry on a feed
  • TrackedChange: a change or group of changes to a tracked field
  • UserStatus: automatically generated when a user adds a post. Deprecated

To enable chatter feed tracking, go to Setup > Chatter > Feed Tracking and select the Account object and the fields you want to track.

Let’s take this account:

We have an AccountFeed of type TrackedChange and another one of type TextPost.

By querying for AccountFeed:

Note that the query includes the subquery (SELECT Id, FieldName, NewValue FROM FeedTrackedChanges), that returns, only for the TrackedChange record:

[
    {
        "Id":"0D624000009RROlCAO",
        "FieldName":"Account.Phone",
        "NewValue":"(650) 450-8812"
    },{
        "Id":"0D624000009RROmCAO",
        "FieldName":"Account.Fax",
        "NewValue":"(650) 450-8822"
    }
]

which tracks the fields change that originated the AccountFeed record.

N.B. Note we could have used the FeedItem object as well:

SELECT id, Type, Title, Body, Visibility, likecount, NetworkScope, (Select Id, FieldName, NewValue From FeedTrackedChanges) from Feeditem where ParentId='00124000003vaBu' 

[Salesforce] The Sobject Crusade

Design by Davide D’Annibale
In the past months I hit the severe wall of ignorance at least twice (with all my face), so I decided to start a personal crusade to cover all Salesforce Standard Objects, using the SOAP API Developer’s Guide and its list of Standard Objects.

To support this research, I start by reading the standard guide of an object and then making all actions to use that object in order to query for its records.

Sometimes an object is simple and well known that is quite useless to explore it (I said quite, because sometimes you find unknown features even with the objects you use daily); on the other hand some objects are cool because to use them you have to make configurations and write code and do stuff you haven’t never done, some other times you simply cannot do anything because the object is deprecated (and you are not that old to have a Developer ORG with that feature activated…my first API level is 15 BTW).

Moreover Salesforce Platform releases are not done yet, so I expect the number of objects will increse release after release.

As of Spring ’16 the number of objects is 546: this means that if I post an Object daily (weekends included), I’ll finish the research in the next 2 years….definitely too much!

That’s the reason I’ll try to post group of objects daily or so (ok, this is not a job, so maybe I shouldn’t promise something that I cannot keep, I still have a life…) instead of only one: on the blog sidebar you’ll always see a link of the last objects added.

If you want to partecipate in the crusade you are welcome!

The following list will be updated every time an object is added.

Legend:

[NA] – Un-activable (the feature is an old feature that cannot be activated on recent Dev Orgs)
[SR] – Salesforce.com Support Required (the feature needs Salesforce.com support activation)
[SRP] – Salesforce.com Support Required (Partially) (a part of the feature needs Salesforce.com support activation)

Page 21 of 27

Powered by WordPress & Theme by Anders Norén