Salesforce Login : Access Salesforce without Access Codes

This is quick little post on how to create a force.com site/page to access Salesforce even if you don't have the access codes and to some extent to create your own custom login screen. Generally helpful when same login is shared by multiple user.

There are already apps like Trapdoor for mac that lets you do the same, but this one just an cloud version of the same and of course you can build one for yourself!

What you need to make this work ?

  • Username and Password
  • The security token

How this works ?

  • The username  & password entered are used to make a SOAP call to Salesforce using the partner Endpoint
  • The response is parsed to retrieve the SessionId and Salesforce Server URL
  • Using the ServerURL and SessionId the user is redirected to "frontdoor.jsp" page of Salesforce which lets user log into Salesforce using session Id.

This page can be hosted in any org and not necessarily in the org you are trying to log in

Code 

Page

The Page uses Visualstrap to create a custom login screen. Same can be installed from here . And you can always copy the page code to create your own custom login screen for salesforce :)

<apex:page controller="SalesforceLogin_Con" showHeader="false" docType="html-5.0">
    <style>  
     body{  
         font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;  
         background: #344A5F;
         
     }    
     
     .logo{
         text-align:center;
         height:44px;
         width:44px;
         margin: auto;
         background-color: #2A94D6;
         padding-top:8px;
         border-radius:8px;
         font-size:200%;
         color:white;
         display:inline-block;
         font-weight:bold;
     }
     
     .logoTxt{
         margin-left:10px;
         font-weight:bold;
         color:#8199af;
         display:inline-block;
     }
     
     .spcl{
         color:#1abc9c !important;
         padding-bottom:-20px;
         margin-bottom:0px !important;
     }
     
     label{
         font-size:130%;
     }
     
     .msgIcon{display:none}
     .messageText h4{display:none}
   </style>
   
    <vs:importvisualstrap />
    <apex:form >
        <vs:visualstrapblock >
            <c:navbar brand="Blogforce9" logo="http://blogforce9dev-developer-edition.ap1.force.com/resource/1385742741000/BlogForce9__BlogForce9WhiteLogo" inverse="true" type="fixed-top">
            <a href="http://blogforce9.blogspot.in/" target="_blank" class="btn btn-primary btn-danger"><vs:glyph icon="home"/> Home</a>
        </c:navbar>
           <div class="container">
                <apex:outputPanel layout="block" styleClass="row">
                    <div class="col-md-6 col-md-offset-3">
                        <div class="jumbotron spcl">
                           <vs:panel >
                               <div style="margin-bottom:10px">
                                   <div class="logo">S</div>
                                   
                                   <div class="logoTxt">
                                       <div style="font-size:150%;">Salesforce Login</div>
                                       <small style="font-weight:normal">Login to Salesforce using Security token to avoid Access Code emails</small>
                                   </div>
                               </div>
                           </vs:panel>
                            <vs:panel >
                                <apex:pageMessages ></apex:pageMessages>
                                <vs:formblock alignment="horizontal" style="margin-top:5px;padding:10px">
                                    <vs:formgroup >
                                        <apex:outputLabel >Username</apex:outputLabel>
                                        <apex:inputText value="{!Username}" styleClass="form-control" required="true"/>
                                    </vs:formgroup> 
                                    <vs:formgroup >
                                        <apex:outputLabel >Password + Security Token</apex:outputLabel>
                                        <apex:inputSecret value="{!Password}" styleClass="form-control" required="true"/>
                                    </vs:formgroup>
                                    <vs:formgroup >
                                        <apex:outputLabel >Domain</apex:outputLabel>
                                        <apex:selectList value="{!domain}" styleClass="form-control" size="1">
                                            <apex:selectOption itemValue="login" itemLabel="login"></apex:selectOption>
                                            <apex:selectOption itemValue="test" itemLabel="test"></apex:selectOption>
                                        </apex:selectList>                                        
                                    </vs:formgroup>
                                    <vs:formgroup >
                                        <apex:commandButton value="Login" action="{!doLogin}" styleClass="btn btn-success btn-md pull-right" style="width:200px"/>
                                    </vs:formgroup>
                                    <small class="text-info">*Passwords are not saved by this page</small>
                                </vs:formblock>
                            </vs:panel>                            
                        </div>
                    </div>
                </apex:outputPanel>
            </div>
            
            <c:navbar brand="Blogforce9" inverse="true" type="fixed-bottom" layout="none" >              
                <div class="text-muted" style="margin:10px;font-size:130%;text-align:Center" layout="block">  
                    Site built with  <a href="http://blogforce9dev-developer-edition.ap1.force.com/ProjectDetail?id=a0290000009MI61" target="_blank" class="btn btn-sm btn-danger"><vs:glyph icon="heart"/> VisualStrap</a> 
                </div>  
            </c:navbar>
        </vs:visualstrapblock>
    </apex:form>
</apex:page>

Controller

public class SalesforceLogin_Con {
    
    public String username{get;set;}
    public String password{get;set;}
    public String domain{get;set;}

    public Pagereference doLogin(){
        Pagereference loginReference;
        try{
            
            String loginRes = sendLoginRequest(username,password,domain);
            if(!String.isBlank(loginRes) && !loginRes.containsIgnoreCase('INVALID_LOGIN')){
                Dom.Document loginDoc = new Dom.Document();
                loginDoc.load(loginRes);
                Dom.XmlNode resultElmt = loginDoc.getRootElement()
                  .getChildElement('Body','http://schemas.xmlsoap.org/soap/envelope/')
                  .getChildElement('loginResponse','urn:partner.soap.sforce.com')
                  .getChildElement('result','urn:partner.soap.sforce.com');
                /*Extract the session Id and Server url*/
                String serverurl = resultElmt.getChildElement('serverUrl','urn:partner.soap.sforce.com').getText().split('/services')[0];
                String sessionId = resultElmt.getChildElement('sessionId','urn:partner.soap.sforce.com').getText();
                /*Use frontdoor.jsp to login to salesforce*/
                loginReference =  new Pagereference(serverurl+'/secur/frontdoor.jsp?sid='+sessionId);
            }
            else{
                Apexpages.addMessage(new ApexPages.Message(ApexPages.Severity.ERROR,'Please check your Username and Password.'));
            }
       }
       catch(Exception ex){
            Apexpages.addMessages(ex);
       }
        
        return loginReference;
    }
    
    /*Method to send login request using using SOAP*/
    private static String sendLoginRequest(String un,String pw,String domain){
        HttpRequest request = new HttpRequest();
        request.setEndpoint('https://' + domain + '.salesforce.com/services/Soap/u/30.0');
        request.setMethod('POST');
        request.setHeader('Content-Type', 'text/xml;charset=UTF-8');
        request.setHeader('SOAPAction', '""');
        request.setBody('<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/"><Header/><Body><login xmlns="urn:partner.soap.sforce.com"><username>' + un + '</username><password>' + pw + '</password></login></Body></Envelope>');
        Http h = new Http();
        HttpResponse res = h.send(request);
        return res.getBody();
    } 
}
This Code can further be Reused for
  • Generate SessionId to Call Salesforce REST Endpoints
  • Salesforce to Salesforce custom Integration
  • This page can be hosted in Force.com site as a Custom/Branded Salesforce Login

5 comments:

  1. This comment has been removed by the author.

    ReplyDelete
    Replies
    1. As you can see in the error message you need to create a remote site setting for login . Just follow the path in the error and create one, it should be fine

      Delete
  2. Good work Avinava. Is there any session timeout for frontdoor.jsp approach. Suppose i just want the user to login and do some other stuff, not necessarily take him to setup menu page, then after how long i'd need to ask the user to login again. Also why don't you write a post for social sign on as well. You are doing great.

    ReplyDelete
  3. Good work Avinava. Is there any session timeout for frontdoor.jsp approach. Suppose i just want the user to login and do some other stuff, not necessarily take him to setup menu page, then after how long i'd need to ask the user to login again. Also why don't you write a post for social sign on as well. You are doing great.

    ReplyDelete
  4. Hi, how to write a test class for this class , please post test class

    ReplyDelete