You're trying to setup / use Service Provider (SP) Initiated SSO. In this case Salesforce is the SP and you've configured an external IdP to provide authentication.
SP Initiated Login works on Salesforce with My Domain. Additionally you will need to set up Salesforce for federated authentication on your IdP, by (at least in case of ADFS) importing the metadata which you export from the SSO Settings Screen in Salesforce.
You will need to set up My Domain, where you register a custom domain for your org, and there is a setting in My Domain where you choose the authentication provider as the IdP rather than the Salesforce login page. The very descriptive "My SAML IDP" option refers to the settings you configured in Security Controls->Single Sign-On Settings.
You then need to refer to your org by the My Domain URL, at which point Salesforce reads this configuration and redirects to the IdP for authentication, passing through a SAML Request. (i.e. login with the custom My Domain URL eg https://ralph-dev-ed.my.salesforce.com
, so Salesforce knows that it needs to delegate authentication to your IdP). If you wanted to by pass the auto-redirect for users who aren't setup for federated authentication you can append /?login
to your My Domain URL to override the SAML redirect (e.g https://ralph-dev-ed.my.salesforce.com/?login
)
Once you've entered your credentials on the IdP login page, it posts a SAML Assertion to the Salesforce Assertion Consumer Service URL, which identifies the User either by UserName or Federation Id, based on what you've set up in your SSO Settings and lets you in.
Lastly, there is also a Summer 13 Known Issue which is preventing SP Initiated login from working on upgraded sandboxes, owing to a mismatch in the Assertion Consumer Service URL in the SAML Request that is sent to the IdP.
Also worth mentioning that Summer 13 brings support for multiple IdP's.
Found a solution to this. Modify the createUser() method in the Auth Provider registration handler class to query for the user using the email address passed in the authentication (or any other query you want to use)
if(!canCreateUser(data)) {
// If the user has a Federation ID or username match, return that user
// otherwise fail if can't create a new user
if ([select count() from User WHERE FederationIdentifier = :data.email
OR Username = :data.email] == 0) {
//Returning null or throwing an exception fails the SSO flow
return null;
} else {
return [SELECT ID FROM User WHERE FederationIdentifier = :data.email
OR Username = :data.email LIMIT 1];
}
}
Best Answer
I got this figured out.
Regarding Ref. 1: https://help.salesforce.com/apex/HTViewSolution?id=000198728&language=en_US
The tutorial suggested that we choose "Portal" instead of "Standard" for login option. But this is wrong! (Confirmed by Salesforce Engineer) Instead we need to leave it as "Standard" and pass the attributes specified in the tutorial and everything should work.
Here are some points to consider for JIT Provisioning SSO for Community User.
Do not pass Federation ID (Contact.FederationID, User.FederationID) in the attribute statement. Passing Federation ID only on the SAML assertion subject is suffice.
Do not pass Organization ID and Portal ID in the attribute statement.
Recipient URL must be what specified by Salesforce under Single Sign-On settings.
Issuer in Salesforce and on the Server must match.