function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Laurie DrewLaurie Drew 

JIT Provisioning

I am trying to set up JIT provisioning, I have SSO set up and functioning properly, the SAML Assertion I receive from the IDP contains the FederationID in the subject, so I have written the following code to search for a contact that has the FederationID in the subject populated in a custom field Campus_id__c, but when I attempt to log in with a test ID a new user account is not being created, can anyone assist?  I really appreciate any help that can be provided.

My Code:

global class SSOUserHandler implements Auth.SamlJitHandler {
 
    //JIT Handler Exception
    private class JitException extends Exception {}
 
    //Handle User
    private void handleUser(boolean create, User u, Map < String, String > attributes, 
        String federationIdentifier, boolean isStandard) {
        if (create && attributes.containsKey('User.FederationIdentifier')) {
            u.FederationIdentifier = attributes.get('User.FederationIdentifier');
        }
        
        if (attributes.containsKey('User.ProfileId')) {
            String profileId = attributes.get('User.ProfileId');
            Profile p = [SELECT Id FROM Profile WHERE Id =: profileId];
            u.ProfileId = p.Id;
        }
            
        Contact c = [Select ID, Email, FirstName, LastName from Contact where Campus_ID__c =:federationIdentifier];
        if (attributes.containsKey('User.FirstName')) {
            u.FirstName = attributes.get('User.FirstName');
        } else if (create) {
            u.FirstName = c.FirstName;
        }
        if (attributes.containsKey('LastName')) {
            u.FirstName = attributes.get('LastName');
        } else if (create) {
            u.LastName = c.LastName;
        }
        if(attributes.containsKey('User.Email')) {
            u.Email = attributes.get('User.Email');
        } else if (create) {
            u.Email = c.Email;
        }
        if (attributes.containsKey('UserName')) {
            u.UserName = attributes.get('UserName');
        } else if (create) {
            u.UserName = c.Email;
        }
        if (attributes.containsKey('User.CommunityNickname')) {
            u.CommunityNickname = attributes.get('User.CommunityNickname');
        }
        if (attributes.containsKey('User.IsActive')) {
            String IsActiveVal = attributes.get('User.IsActive');
            u.IsActive = '1'.equals(IsActiveVal) || Boolean.valueOf(IsActiveVal);
        }
        String uid = UserInfo.getUserId();
        User currentUser = [SELECT LocaleSidKey, LanguageLocaleKey, TimeZoneSidKey, EmailEncodingKey FROM User WHERE Id =: uid];
        if (attributes.containsKey('User.LocaleSidKey')) {
            u.LocaleSidKey = attributes.get('User.LocaleSidKey');
        } else if (create) {
            u.LocaleSidKey = currentUser.LocaleSidKey;
        }
        if (attributes.containsKey('User.LanguageLocaleKey')) {
            u.LanguageLocaleKey = attributes.get('User.LanguageLocaleKey');
        } else if (create) {
            u.LanguageLocaleKey = currentUser.LanguageLocaleKey;
        }
        if (attributes.containsKey('User.Alias')) {
            u.Alias = attributes.get('User.Alias');
        } else if (create) {
            String alias = '';
            if (u.FirstName == null) {
                alias = u.LastName;
            } else {
                alias = u.FirstName.charAt(0) + u.LastName;
            }
            if (alias.length() > 5) {
                alias = alias.substring(0, 5);
            }
            u.Alias = alias;
        }
        if (attributes.containsKey('User.TimeZoneSidKey')) {
            u.TimeZoneSidKey = attributes.get('User.TimeZoneSidKey');
        } else if (create) {
            u.TimeZoneSidKey = currentUser.TimeZoneSidKey;
        }
        if (attributes.containsKey('User.EmailEncodingKey')) {
            u.EmailEncodingKey = attributes.get('User.EmailEncodingKey');
        } else if (create) {
            u.EmailEncodingKey = currentUser.EmailEncodingKey;
        }
 
        if (!create) {
            update(u);
        } else {
            Insert u;
        }
    }
    
//Handle JIT
    private void handleJit(boolean create, User u, Id samlSsoProviderId, Id communityId, Id portalId, 
        String federationIdentifier, Map < String, String > attributes, String assertion) {
        if (communityId != null || portalId != null) {
            handleUser(create, u, attributes, federationIdentifier, false);
        } else {
            handleUser(create, u, attributes, federationIdentifier, true);
        }
    }
 
    //For New User
    global User createUser(Id samlSsoProviderId, Id communityId, Id portalId, 
        String federationIdentifier, Map < String, String > attributes, String assertion) {
        User u = new User();
        handleJit(true, u, samlSsoProviderId, communityId, portalId, federationIdentifier, attributes, assertion);
        return u;
    }
 
    //For Existing User
    global void updateUser(Id userId, Id samlSsoProviderId, Id communityId, Id portalId,
        String federationIdentifier, Map < String, String > attributes, String assertion) {
        User u = [SELECT Id, FirstName, ContactId FROM User WHERE Id =: userId];
        handleJit(false, u, samlSsoProviderId, communityId, portalId, federationIdentifier, attributes, assertion);
    }
}
Best Answer chosen by Laurie Drew
Laurie DrewLaurie Drew
Hi Gary,

Yes I was able to resolve our issue, here is my updated class:

global class SSOUserHandler implements Auth.SamlJitHandler {
    
    public string result {get; set;}
    public string debug {get; set;}
    public list<string> emails = new list<string>{'llinnemeier@innovateteam.com'};
 
    //JIT Handler Exception
    private class JitException extends Exception {}
 
    //Handle User
    private void handleUser(boolean create, User u, Map < String, String > attributes, 
        String federationIdentifier, boolean isStandard) {
        system.debug('manual class');
        system.debug('federationIdentifier '+federationIdentifier);
        system.debug('user fed id '+attributes.get('User.FederationIdentifier'));
        if (create && attributes.containsKey('User.FederationIdentifier') && attributes.get('User.FederationIdentifier') != null) {
            u.FederationIdentifier = attributes.get('User.FederationIdentifier');
            federationIdentifier = attributes.get('User.FederationIdentifier');
        }
        else {
            u.FederationIdentifier = federationIdentifier;
        }
        Profile p;
        if (attributes.containsKey('User.ProfileId')) {
            String profileId = attributes.get('User.ProfileId');
            if(profileId != null && profileId != '') {
                p = [SELECT Id FROM Profile WHERE Id =: profileId];
            }
            system.debug('profile1: '+p);
        }
        if(p == null) {
            p = [SELECT Id FROM Profile WHERE Name =: 'Support Community Login User'];
        }
        system.debug('profile2: '+p);
        u.ProfileId = p.Id;
        List<Contact> cons = [Select ID, Email, FirstName, LastName from Contact where Campus_ID__c =:federationIdentifier];
        Contact c;
        if(cons != null && cons.size() > 0) {
            c = cons[0];
        }
        if(c != null) {
            u.ContactId = c.Id;
        }
        if (attributes.containsKey('User.FirstName')) {
            u.FirstName = attributes.get('User.FirstName');
        } else if (create && c != null) {
            u.FirstName = c.FirstName;
        }
        if (attributes.containsKey('LastName')) {
            u.FirstName = attributes.get('LastName');
        } else if (create && c != null) {
            u.LastName = c.LastName;
        }
        if(attributes.containsKey('User.Email')) {
            u.Email = attributes.get('User.Email');
        } else if (create && c != null) {
            u.Email = c.Email+'.temp';
        }
        if (attributes.containsKey('UserName')) {
            u.UserName = attributes.get('UserName');
        } else if (create && c != null) {
            u.UserName = c.Email;
        }
        if (attributes.containsKey('User.CommunityNickname')) {
            u.CommunityNickname = attributes.get('User.CommunityNickname');
        }
        if (attributes.containsKey('User.IsActive')) {
            String IsActiveVal = attributes.get('User.IsActive');
            u.IsActive = '1'.equals(IsActiveVal) || Boolean.valueOf(IsActiveVal);
        }
        String uid = UserInfo.getUserId();
        User currentUser = [SELECT LocaleSidKey, LanguageLocaleKey, TimeZoneSidKey, EmailEncodingKey FROM User WHERE Id =: uid];
        if (attributes.containsKey('User.LocaleSidKey')) {
            u.LocaleSidKey = attributes.get('User.LocaleSidKey');
        } else if (create) {
            u.LocaleSidKey = currentUser.LocaleSidKey;
        }
        if (attributes.containsKey('User.LanguageLocaleKey')) {
            u.LanguageLocaleKey = attributes.get('User.LanguageLocaleKey');
        } else if (create) {
            u.LanguageLocaleKey = currentUser.LanguageLocaleKey;
        }
        if (attributes.containsKey('User.Alias')) {
            u.Alias = attributes.get('User.Alias');
        } else if (create) {
            String alias = '';
            if (u.FirstName == null) {
                alias = u.LastName;
            } else {
                alias = u.FirstName.charAt(0) + u.LastName;
            }
            if (alias.length() > 5) {
                alias = alias.substring(0, 5);
            }
            u.Alias = alias;
        }
        if (attributes.containsKey('User.TimeZoneSidKey')) {
            u.TimeZoneSidKey = attributes.get('User.TimeZoneSidKey');
        } else if (create) {
            u.TimeZoneSidKey = currentUser.TimeZoneSidKey;
        }
        if (attributes.containsKey('User.EmailEncodingKey')) {
            u.EmailEncodingKey = attributes.get('User.EmailEncodingKey');
        } else if (create) {
            u.EmailEncodingKey = currentUser.EmailEncodingKey;
        }
 
        try { 
            if (!create) {
                //update(u); //GB 1/10/2019
                } 
            else {
                Insert u;
                }
                system.debug('success ' + u);
                result = 'Success';
                system.debug('result ' + result + ' ' + debug);
        }
        catch(Exception e) {
            result = 'Failure';
            debug += ' User record not inserted';
            system.debug('result ' + result + ' ' + debug + ' ' + e);
            Messaging.SingleEmailMessage email1 = new Messaging.SingleEmailMessage();
            email1.setToAddresses(emails);
            email1.setSubject('Error in JIT Provisioning failed to insert');
            email1.setHtmlBody('Debug: <br/>' + debug + ' <br/> u.federationIdentifier: ' + federationIdentifier + e.getMessage());
            Messaging.sendEmail(new Messaging.Email[]{email1});
        }
    }
    
//Handle JIT
    private void handleJit(boolean create, User u, Id samlSsoProviderId, Id communityId, Id portalId, 
        String federationIdentifier, Map < String, String > attributes, String assertion) {
        if (communityId != null || portalId != null) {
            handleUser(create, u, attributes, federationIdentifier, false);
        } else {
            handleUser(create, u, attributes, federationIdentifier, true);
        }
    }
 
    //For New Users
    global User createUser(Id samlSsoProviderId, Id communityId, Id portalId, 
        String federationIdentifier, Map < String, String > attributes, String assertion) {
        User u = new User();
        handleJit(true, u, samlSsoProviderId, communityId, portalId, federationIdentifier, attributes, assertion);
        return u;
    }
 
    //For Existing Users
    global void updateUser(Id userId, Id samlSsoProviderId, Id communityId, Id portalId,
        String federationIdentifier, Map < String, String > attributes, String assertion) {
        User u = [SELECT Id, FirstName, ContactId FROM User WHERE Id =: userId];
        handleJit(false, u, samlSsoProviderId, communityId, portalId, federationIdentifier, attributes, assertion);
    }
}

All Answers

Gary Singh (BlackBeltHelp)Gary Singh (BlackBeltHelp)
Hi Laurie,

Were you ever able to find a solution regarding JIT, we are also experiancing the same problem. Any pointers would help. 

Thanks,
Gary
Laurie DrewLaurie Drew
Hi Gary,

Yes I was able to resolve our issue, here is my updated class:

global class SSOUserHandler implements Auth.SamlJitHandler {
    
    public string result {get; set;}
    public string debug {get; set;}
    public list<string> emails = new list<string>{'llinnemeier@innovateteam.com'};
 
    //JIT Handler Exception
    private class JitException extends Exception {}
 
    //Handle User
    private void handleUser(boolean create, User u, Map < String, String > attributes, 
        String federationIdentifier, boolean isStandard) {
        system.debug('manual class');
        system.debug('federationIdentifier '+federationIdentifier);
        system.debug('user fed id '+attributes.get('User.FederationIdentifier'));
        if (create && attributes.containsKey('User.FederationIdentifier') && attributes.get('User.FederationIdentifier') != null) {
            u.FederationIdentifier = attributes.get('User.FederationIdentifier');
            federationIdentifier = attributes.get('User.FederationIdentifier');
        }
        else {
            u.FederationIdentifier = federationIdentifier;
        }
        Profile p;
        if (attributes.containsKey('User.ProfileId')) {
            String profileId = attributes.get('User.ProfileId');
            if(profileId != null && profileId != '') {
                p = [SELECT Id FROM Profile WHERE Id =: profileId];
            }
            system.debug('profile1: '+p);
        }
        if(p == null) {
            p = [SELECT Id FROM Profile WHERE Name =: 'Support Community Login User'];
        }
        system.debug('profile2: '+p);
        u.ProfileId = p.Id;
        List<Contact> cons = [Select ID, Email, FirstName, LastName from Contact where Campus_ID__c =:federationIdentifier];
        Contact c;
        if(cons != null && cons.size() > 0) {
            c = cons[0];
        }
        if(c != null) {
            u.ContactId = c.Id;
        }
        if (attributes.containsKey('User.FirstName')) {
            u.FirstName = attributes.get('User.FirstName');
        } else if (create && c != null) {
            u.FirstName = c.FirstName;
        }
        if (attributes.containsKey('LastName')) {
            u.FirstName = attributes.get('LastName');
        } else if (create && c != null) {
            u.LastName = c.LastName;
        }
        if(attributes.containsKey('User.Email')) {
            u.Email = attributes.get('User.Email');
        } else if (create && c != null) {
            u.Email = c.Email+'.temp';
        }
        if (attributes.containsKey('UserName')) {
            u.UserName = attributes.get('UserName');
        } else if (create && c != null) {
            u.UserName = c.Email;
        }
        if (attributes.containsKey('User.CommunityNickname')) {
            u.CommunityNickname = attributes.get('User.CommunityNickname');
        }
        if (attributes.containsKey('User.IsActive')) {
            String IsActiveVal = attributes.get('User.IsActive');
            u.IsActive = '1'.equals(IsActiveVal) || Boolean.valueOf(IsActiveVal);
        }
        String uid = UserInfo.getUserId();
        User currentUser = [SELECT LocaleSidKey, LanguageLocaleKey, TimeZoneSidKey, EmailEncodingKey FROM User WHERE Id =: uid];
        if (attributes.containsKey('User.LocaleSidKey')) {
            u.LocaleSidKey = attributes.get('User.LocaleSidKey');
        } else if (create) {
            u.LocaleSidKey = currentUser.LocaleSidKey;
        }
        if (attributes.containsKey('User.LanguageLocaleKey')) {
            u.LanguageLocaleKey = attributes.get('User.LanguageLocaleKey');
        } else if (create) {
            u.LanguageLocaleKey = currentUser.LanguageLocaleKey;
        }
        if (attributes.containsKey('User.Alias')) {
            u.Alias = attributes.get('User.Alias');
        } else if (create) {
            String alias = '';
            if (u.FirstName == null) {
                alias = u.LastName;
            } else {
                alias = u.FirstName.charAt(0) + u.LastName;
            }
            if (alias.length() > 5) {
                alias = alias.substring(0, 5);
            }
            u.Alias = alias;
        }
        if (attributes.containsKey('User.TimeZoneSidKey')) {
            u.TimeZoneSidKey = attributes.get('User.TimeZoneSidKey');
        } else if (create) {
            u.TimeZoneSidKey = currentUser.TimeZoneSidKey;
        }
        if (attributes.containsKey('User.EmailEncodingKey')) {
            u.EmailEncodingKey = attributes.get('User.EmailEncodingKey');
        } else if (create) {
            u.EmailEncodingKey = currentUser.EmailEncodingKey;
        }
 
        try { 
            if (!create) {
                //update(u); //GB 1/10/2019
                } 
            else {
                Insert u;
                }
                system.debug('success ' + u);
                result = 'Success';
                system.debug('result ' + result + ' ' + debug);
        }
        catch(Exception e) {
            result = 'Failure';
            debug += ' User record not inserted';
            system.debug('result ' + result + ' ' + debug + ' ' + e);
            Messaging.SingleEmailMessage email1 = new Messaging.SingleEmailMessage();
            email1.setToAddresses(emails);
            email1.setSubject('Error in JIT Provisioning failed to insert');
            email1.setHtmlBody('Debug: <br/>' + debug + ' <br/> u.federationIdentifier: ' + federationIdentifier + e.getMessage());
            Messaging.sendEmail(new Messaging.Email[]{email1});
        }
    }
    
//Handle JIT
    private void handleJit(boolean create, User u, Id samlSsoProviderId, Id communityId, Id portalId, 
        String federationIdentifier, Map < String, String > attributes, String assertion) {
        if (communityId != null || portalId != null) {
            handleUser(create, u, attributes, federationIdentifier, false);
        } else {
            handleUser(create, u, attributes, federationIdentifier, true);
        }
    }
 
    //For New Users
    global User createUser(Id samlSsoProviderId, Id communityId, Id portalId, 
        String federationIdentifier, Map < String, String > attributes, String assertion) {
        User u = new User();
        handleJit(true, u, samlSsoProviderId, communityId, portalId, federationIdentifier, attributes, assertion);
        return u;
    }
 
    //For Existing Users
    global void updateUser(Id userId, Id samlSsoProviderId, Id communityId, Id portalId,
        String federationIdentifier, Map < String, String > attributes, String assertion) {
        User u = [SELECT Id, FirstName, ContactId FROM User WHERE Id =: userId];
        handleJit(false, u, samlSsoProviderId, communityId, portalId, federationIdentifier, attributes, assertion);
    }
}
This was selected as the best answer
Gary Singh (BlackBeltHelp)Gary Singh (BlackBeltHelp)
Hi Laurie, 

Thanks a bunch, can you please share the related test class. This is the light in the dark for Adminis like me.

Regards, 
Gary
Laurie DrewLaurie Drew
There is a trailhead module that will help you build your test class:

https://trailhead.salesforce.com/content/learn/modules/unit-testing-on-the-lightning-platform
Gary Singh (BlackBeltHelp)Gary Singh (BlackBeltHelp)
Thank you Laurie.