Problem
Your app contains a significant action, like signing a document or escalating an issue, that requires you make certain the currently logged in user is in fact who they say they are.
Solution
Prompt the user to re-enter their password and verify password via a callout to the web service API.
Notes
- You'll need to create a remote site setting for the login URL. If you're org is on na1, then you'll need the following URL as a remote site setting: https://www.salesforce.com
- Below code uses web service API so it's as if the user is logging into Data Loader or IDE. Accordingly, if tokens are required, users will need to append their token to password.
Code
Here is the code for a simple Visualforce page that prompts a user to enter password and then prints a message stating the password was correct or incorrect. Use this code as a template.
Visualforce Page
<apex:page controller="VerifyPassword">
<apex:sectionHeader title="Verify Password"/>
<apex:pageMessages />
<apex:form >
<apex:pageBlock title="" mode="view">
<apex:pageBlockButtons >
<apex:commandButton value="Verify" action="{!doVerify}"/>
</apex:pageBlockButtons>
<apex:pageBlockSection title="My Content Section" columns="1">
<apex:pageBlockSectionItem >
<apex:outputLabel value="Username" for="username"/>
<apex:outputText value="{!username}" id="username"/>
</apex:pageBlockSectionItem>
<apex:pageBlockSectionItem >
<apex:outputLabel value="Password" for="password"/>
<apex:inputSecret value="{!password}" id="password"/>
</apex:pageBlockSectionItem>
</apex:pageBlockSection>
</apex:pageBlock>
</apex:form>
</apex:page>
Controller
Here's the corresponding controller code:
/*
======================================================================
NOTES:
You'll need to create a remote site setting for the login url. If you're org is on na1, then you'll need the following URL as a remote site setting: https://www.salesforce.com
======================================================================
*/
public class VerifyPassword {
public final String LOGIN_DOMAIN = 'test'; //other options: test, prerellogin.pre
public String username {get{ return UserInfo.getUsername(); }}
public transient String password {get;set;}
public PageReference doVerify(){
HttpRequest request = new HttpRequest();
request.setEndpoint('https://' + LOGIN_DOMAIN + '.salesforce.com/services/Soap/u/22.0');
request.setMethod('POST');
request.setHeader('Content-Type', 'text/xml;charset=UTF-8');
request.setHeader('SOAPAction', '""');
request.setBody(buildSoapLogin(username,password));
//basically if there is a loginResponse element, then login succeeded; else there
// would be soap fault element after body
final Boolean verified = (new Http()).send(request).getBodyDocument().getRootElement()
.getChildElement('Body','http://schemas.xmlsoap.org/soap/envelope/')
.getChildElement('loginResponse','urn:partner.soap.sforce.com') != null;
if(verified) ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.CONFIRM, 'Correct password!'));
else ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.ERROR, 'Incorrect password!'));
return null;
}
public static String buildSoapLogin(String username, String password){
XmlStreamWriter w = new XmlStreamWriter();
w.writeStartElement('', 'login', 'urn:partner.soap.sforce.com');
w.writeNamespace('', 'urn:partner.soap.sforce.com');
w.writeStartElement('', 'username', 'urn:partner.soap.sforce.com');
w.writeCharacters(username);
w.writeEndElement();
w.writeStartElement('', 'password', 'urn:partner.soap.sforce.com');
w.writeCharacters(password);
w.writeEndElement();
w.writeEndElement();
String xmlOutput =
'<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/"><Body>'
+ w.getXmlString()
+ '</Body></Envelope>';
w.close();
return xmlOutput;
}
}
Recipe Activity - Please Log in to write a comment
Thanks
Works for me
Hi, Amn att, please set the "remote site url" as "https://test.salesforce.com", and that will be OK, please have a try. Hope that will be a little help to you~~
Hi Richard,
I am getting error as below... I dont understand what is test?
System.CalloutException: Unauthorized endpoint, please check Setup->Security->Remote site settings. endpoint = https://test.salesforce.com/services/Soap/u/22.0
Class.VerifyPassword.doVerify: line 37, column 47 External entry pointAnd unable to log in via data loader... pls help!!!
Pat_Patterson, API call endpoint URLs are agnostic of My Domain so test/prod/prerel etc should work.
Hi Richard - nice recipe! Just one nit - on line 9 of the controller, the default LOGIN_DOMAIN should probably be 'login', since you mention 'test' as another option. Also, if you have configured 'My Domain', 'customername.my' is another possibility for LOGIN_DOMAIN.