Apex – How to Log Users Out of the Community Site

apexcommunityexperience-cloudforce.com-sitesvisualforce

I have a requirement to have a visualforce page with login and logout buttons. When a user clicks login they are redirected to the external App through Auth0 to login and if the user is found in registrationhandler they would see the logout button and the content inside the community and if they click on the logout option, they should be logged out and should see the login button again. I have set up the logout URL to the community page in Auth0 tenant settings.

I have a problem with logout in my visualforce page. Despite clicking on the logout I still see the logout button and also the profile is still the logged in profile but not the guest profile from where we actually begin the login from with.

I am using this vf page as a part of the community site to login and logout of the site.

<apex:page docType="html-5.0" showHeader="false" sidebar="false" controller="CommunitiesLoginController">
 <apex:form style="background:#008d58;">
          <div align="Center">
            <apex:commandbutton rendered="{!If($Profile.Id = 'xxxxxxxxxxx', true, false)}" value="Login" action="{!loginUser}" style="height:25px;font-size:1rem;background:#008d58;width:75px;color:white;"/>
            <apex:commandbutton rendered="{!If($Profile.Id = 'xxxxxxxxxxx', false, true)}" value="Logout" action="{!logoutUser}" style="height:25px;font-size:1rem;background:#008d58;width:75px;color:white;"/>
            
          </div>
            <apex:outputText style="font-style:italic" value="{!$Profile.Id}"> </apex:outputText>
       </apex:form>
     <Style>
         body{ background-color:#008d58; }
    </Style>
</apex:page>

Registration Handler :

global class CustomRegistrationHandler  implements Auth.RegistrationHandler{
    global boolean canCreateUser(Auth.UserData data) {
        return false;
    }
    
    global User createUser(Id portalId, Auth.UserData data){
        if(String.isNotBlank(data.email)){ 
            return createOrGetUser(data, false);
        }
        return null;
    }
    
    global void updateUser(Id userId, Id portalId, Auth.UserData data){
        createOrGetUser(data, true);
    }
    
    
    private User createOrGetUser(Auth.UserData data, Boolean isUpdateUser){
        
        List<Contact> contacts = [SELECT Id, valid__Id__c, FirstName, LastName FROM Contact WHERE valid__Id__c = :data.email];
        
        if(!contacts.isEmpty()) {
            List<User> users = [SELECT Id FROM User WHERE Email = :contacts[0].valid__Id__c AND IsActive = TRUE];
            
            if(!users.isEmpty()) {
                return users[0]; 
            } else if(!isUpdateUser) {
                User usr = new User();
                Profile communityProfile = [SELECT Id FROM Profile WHERE Name = :Label.Valid_Community_User];
                usr.username = contacts[0].valid__Id__c;//can add subfix
                usr.email = contacts[0].valid__Id__c;
                usr.firstName = contacts[0].FirstName;
                usr.lastName = contacts[0].LastName;
                
                String alias = contacts[0].valid__Id__c;
                //Alias must be 8 characters or less
                if(alias.length() > 8) {
                    alias = alias.substring(0, 8);
                }
                usr.Alias = alias;
                usr.Languagelocalekey = 'at';
                usr.Localesidkey = 'at';
                usr.EmailEncodingKey = 'UTF-8';
                usr.TimeZoneSidKey = 'America/Los_Angeles';
                usr.ProfileId = communityProfile.Id;
                usr.ContactId = contacts[0].Id;
                return usr;
            }
            return users[0];
        } else {
            
            throw new NotFoundException('You don\'t have the access, please reach out to System Admin.');
        }
    }
    
    public class NotFoundException extends Exception {}

    public PageReference loginUser(){ 
        PageReference redirect = new PageReference(Label.Community_URL);
        redirect.setRedirect(true);
        return redirect;
    }
}

CommunitiesLoginController :

global with sharing class CommunitiesLoginController {

public PageReference loginUser(){ 
        PageReference redirect = new PageReference(Label.Community_URL);
        redirect.setRedirect(true);
        return redirect;
    }
    
    public PageReference logoutUser(){    
        
        PageReference redirect = new PageReference('https://www.myCommunitySite/');
        System.debug('CommunitiesLoginController :: redirect :: ' +redirect);
        redirect.setRedirect(true);
        return redirect;
    }


}

I would still see the profile which is logged in through the Auth0 even after clicking on the logout button on the visualforce page I still see the logout button. I am suspecting that the Auth0 session is not being terminated. I found out on Auth0 documentation that to Log Users Out of Identity Providers I can use https://YOUR_DOMAIN/v2/logout?federated. Can anyone tell me what does it mean by federated here? or guide me on how to log out of Auth 0 ?

I have tried to logout using the Single logout URL provided by Salesforce in the Auth Provider but it is throwing me on to a generic salesforce page but I want the profile to be logged out and to see the login button becuase then the profile would be the guest user profile on my visualforce page.

Best Answer

To logout a user you can write following code.

public pagereference logout(){
       //perform Business logic here
        PageReference pageRef = new PageReference('/default/secur/logout.jsp');
        pageRef.setRedirect(true);
        return pageRef;
    }

Let me know if it works for you.

Related Topic