0

//This class provides logic for inbound just-in-time provisioning of single sign-on users in your Salesforce organization. //This is the second version which differs from the original in that it works with social login instead of former identity verification method.

I am trying to update existing code that will make the already existing user to active if the status is inactive when the user tries to log in but the logic does nothing. It says Unable to verify your identity.

global class JustInTime_v2_Handler implements Auth.SamlJitHandler {

    private class JitException extends Exception{}
    private String federationIdentifier;
    private String defaultUserNameSuffix;
    private String loginPath;
    private String loginViaAccount;
    private String pId;
    private String errorMsg;
    private Id userProfileId;


    private User setupNewUser(Contact c, String possibleNewUserName, Id userProfileId, 
                              String umichEmail, String friendAccountEmail){        

        User newUser = new User();        
            newUser.Username = possibleNewUserName;
            newUser.Reset_Password_On_Create__c = true;
            newUser.FederationIdentifier = federationIdentifier;
            newUser.FirstName = c.FirstName;
            newUser.LastName = c.LastName;

        if( friendAccountEmail != null ) { 
            newUser.Email = friendAccountEmail ; 
        }            
        else if( umichEmail != null ) { 
            newUser.Email = umichEmail; 
        }   

        if( c.MailingPostalCode != '' && c.MailingPostalCode != null ) {
            newUser.PostalCode = c.MailingPostalCode ; 
        }            

        if( c.MailingCountry != '' && c.MailingCountry != null ) {
            newUser.Country = c.MailingCountry ; 
        }   

        Integer i = Integer.valueof(Math.random() * 1000000);
        String randomInt1 = '99';
        if( String.valueof(i).length() >= 2 ){
            randomInt1 = String.valueof(i).substring(0,2); 
        }              

        String firstNameSubstring =  (c.FirstName + c.FirstName + c.FirstName).substring(0,4); // triple up in case length is too short
        String lastNameSubstring = (c.LastName + c.LastName + c.FirstName).substring(0,4);  // triple up in case length is too short
        newUser.CommunityNickname = lastNameSubstring + firstNameSubstring + randomInt1;  

        User currentUser = [SELECT LocaleSidKey, LanguageLocaleKey, TimeZoneSidKey, EmailEncodingKey FROM User WHERE Id=:UserInfo.getUserId()];  // per Andre: it is okay to set time zone as anything since Fonteva will handle time zone in the portal.  language can be default english.
        newUser.LocaleSidKey = currentUser.LocaleSidKey;
        newUser.LanguageLocaleKey = currentUser.LanguageLocaleKey;

        String alias = '';
        String randomInt2 = String.valueof(i).substring(0,1);

        if(c.FirstName == null) {
            alias = randomInt2 + c.LastName + 'abc';
        } else {
            alias = randomInt2 + newUser.LastName + newUser.FirstName ;
        }

        if(alias.length() >= 5) {
            alias = alias.substring(0, 5);
        }

        newUser.Alias = alias;
        newUser.TimeZoneSidKey = currentUser.TimeZoneSidKey; 
        newUser.EmailEncodingKey = currentUser.EmailEncodingKey;

        /*
         * If you are updating Contact or Account object fields, you cannot update the following User fields at the same time.
         * If your identity provider sends these User fields as attributes along with Contact 
         * or Account fields, you must modify the logic in this class to update either these 
         * User fields or the Contact and Account fields.
         */

        newUser.isActive = true;
        newUser.contactId = c.id;
        newUser.profileId = userProfileId;

     return newUser;   
    }

    private User handleJit( boolean fromCreateMethod, String ProfileName,  Map<String, String> attributes) {  

        User u2Return;


        if( fromCreateMethod) {


            // GET PROFILE ID
            List<Profile> profile = [Select Id From Profile Where Name =:ProfileName limit 1];        
            if( profile.isEmpty() ){ 
                throw new JitException ('Unable to create a user account.  The profile ' + ProfileName + ' cannot be found.');   
            }    
            userProfileId = profile[0].id;        

            // FIND EXISTING CONTACTS 
            Contact c = getMatchingContact();  

            if( c != null ) {

                String umichEmail = (c.AAUMCustom__UMich_Email__c != null? c.AAUMCustom__UMich_Email__c : c.OrderApi__Preferred_Email__c) ;
                String friendAccountEmail = c.AAUM_Friend_Account_ID__c;

                String newUserName = buildNewUserName(umichEmail, friendAccountEmail);

                // FIND ANY EXISTING PORTAL USER RECORD FOR THE CONTACT.  
                List<User> uList = [ Select id, userName, Profile.Name, ProfileId, FederationIdentifier, isActive, ContactId 
                                     From User Where  ContactId =: c.id ]; 

                // if no existing duplicate user record found
                if ( uList.isEmpty() ){
                    u2Return = setupNewUser ( c, newUserName, userProfileId, umichEmail, friendAccountEmail);
                    updateContact(c);
                } 
                  else{
                  if(uList[0].isActive==true){
                  throw new JitException('Unable to create a user account.  One already exists, but it may need to be re-configured');

                  }

                  }             


                }                                        
            }        



     return u2Return;   
    }

    private void handleuser(boolean create, user u, Map<String, String> attributes){
        if(!create){
            if (attributes.containsKey('User.IsActive')) {
            String IsActiveVal = attributes.get('User.IsActive');
                If(IsActiveVal=='false'){
                    u.IsActive=true;
                 update u;
                }
           }

            }
                }




    private Contact getMatchingContact(){
        Contact theContact;
        List<Contact> matchingContacts = [Select Id,AAUMCustom__Ext_Alumni_ID__c,AAUMCustom__UMich_Email__c,LastName,FirstName,Name,
                                          MailingPostalCode, MailingCountry,AAUM_Friend_Account_ID__c,OrderApi__Preferred_Email__c
                                          From Contact Where AAUMCustom__Ext_Alumni_ID__c =: federationIdentifier And AAUMCustom__Ext_Alumni_ID__c != null ];

        if(  matchingContacts.isEmpty() ){
            throw new JitException ('Unable to create a user account for you.  Reason: No Contact Record is found matching your Alumni/Member ID');
        }
        else if( matchingContacts.size() > 1 ){
            throw new JitException ('Unable to create a user account. Reason: Multiple Contact Records found matching your Alumni/Member ID. Further verification steps needed.');
        }
        else {
            theContact = matchingContacts[0];           
        }       
    return theContact;
    } 

    private String getUserNameSuffix(){    
        String orgId = UserInfo.getOrganizationId();
        if( orgId.startswith('00D630000009Dob') ){ return '.uat';
        }else if ( orgId.startswith('00D1a000000KDXx' )) {  return '';  // prod                   
        }else if ( orgId.startswith('00D630000009GiM' )) {  return '.devPartial';
        }else if ( orgId.startswith('00Dg0000006HjcC' )) {  return '.QA';
        }else if ( orgId.startswith('00D0q0000000NVf' )) {  return '.uat';
        }else return '.otherSandbox';            
    }

    private void updateContact(Contact c){

    }

    private String buildNewUserName(String umichEmail,String friendAccountEmail){
        defaultUserNameSuffix = getUserNameSuffix();
        String newUserName = '';

        if( friendAccountEmail != null && friendAccountEmail.length() > 0 ){
            newUserName = friendAccountEmail + '.asfportal' + defaultUserNameSuffix;            
        }        
        else if( umichEmail != null && umichEmail.length() > 0 ){     
            newUserName = umichEmail + '.asfportal' + defaultUserNameSuffix; 
        }
        else{
            throw new JitException('Unable to create a user account.  System cannot find a valid email address on your Contact record');
        }   
        system.debug(logginglevel.error,'username: ' + newUserName);
    return newUserName;    
    }

    global User createUser(Id samlSsoProviderId, Id communityId, Id portalId,
                           String federationIdentifier, Map<String, String> attributes, String assertion) {
        User u ; 
        parseInfo('CreateUser', communityId, portalId, federationIdentifier, attributes );
        if( pId != null ){            
            u = handleJit(true, 'Fonteva Customer Community User', attributes);                    
        }else {
            throw new JitException('The login link that routed you here is for staff members with an active Account.  It doesn\'t look like you have an active Staff Account.');
        }

    return u;
    }

    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];
        handleuser(false,u,attributes); 

        } 

   private void parseInfo(String methodCalled,Id communityId, Id portalId,String federationIdentifier,Map<String,String> attributes){
       pId = (communityId != null? communityId : portalId);
       this.federationIdentifier = federationIdentifier;
       loginPath = 'Social';

       Map<String,JIT_Attributes_Mappings__c> allSettings = JIT_Attributes_Mappings__c.getAll();
       String ShibbolethTypeKey = (allSettings.get('ShibbolethType') != null? allSettings.get('ShibbolethType').Raw_Attribute_Name__c : 'None');
       String SocialEmailKey = (allSettings.get('SocialEmail') != null? allSettings.get('SocialEmail').Raw_Attribute_Name__c : 'None');
       String UmichAccountKey = (allSettings.get('UmichAccount') != null? allSettings.get('UmichAccount').Raw_Attribute_Name__c : 'None');

       for( String key : attributes.keyset() ){
           System.debug(logginglevel.error,'Key: ' + key + ' - value: ' + attributes.get(key));
           if( key == ShibbolethTypeKey ){
               loginPath = 'Shibboleth';
           }

           if( key == UmichAccountKey ){
               loginViaAccount = attributes.get(key);
           }
       }

       String outputMsg = 'Method Called: ' + methodCalled + '\n';
              outputMsg += 'federationIdentifier: ' + federationIdentifier + '\n';
              outputMsg += 'pId : ' + pId + '\n';
              outputMsg += 'loginPath : ' + loginPath + '\n';
              outputMsg += 'loginViaAccount : ' + loginViaAccount + '\n';

       System.debug(logginglevel.error,'outputMsg : ' + outputMsg );        

   }  

}**
**
  • In your 'setupNewUser' method, you instantiate a User, but I don't see you ever insert them from there or where you call it. I didn't see anywhere you were calling the method that updates a user either. – HungryBeagle Oct 12 '18 at 16:19
0

What you have done is correct. If there is a matching user record with federation identifier as same as SAML claim, updateUser is called. In there, if the user record is inactive, you can make it active and update. That should enable the user to login seamlessly. I have successfully verified that.

What i'm thinking is, since you do a validation before updating inside handleUser() method, it may not getting update. Please double check the conditions and actual values by running a debug.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.