2

In the past i implemented following example http://developer.force.com/cookbook/recipe/verifying-password

in order to login a user via API:

I've exactly same code and it worked for 1year. Now it s not working anymore, response call is:

HttpResponse[Status=Server Error, StatusCode=500]

I m wondering if something (endpoint, request format) has changed with Winter 15 release. Do you know something about?

  • All soap faults are sent with a 500 status code (as per the SOAP 1.1 spec). you'll want to grab the body and see what the soap fault says. It could be an IP range change that means you need to also send the api security token – superfell Oct 22 '14 at 21:03
  • Thanks Superfell, I ve added my ip to the trusted but no luck. Do i need to check some other thing? – MarcoDev Oct 22 '14 at 21:14
  • 1
    You need to look at the response body of your request it'll tell you whats wrong. – superfell Oct 22 '14 at 21:40
2

I suspect the issue is around the security token and the Trusted IP Ranges in the Network Access Security Controls.

Something to check, look for failed logins under Administration Setup > Manage Users > Login History. If you see the Status message "Failed: API security token required" then the requesting Salesforce IP address isn't trusted.

If the IP address that the login request is coming from isn't trusted Salesforce will reject it unless you append the security token on the end of the password.

So your options are:

  1. Modify the Visualforce page to prompt the user to append their security token. You can't get this in Apex code. It is emailed to the user using the Reset my Security Token link.
  2. Add the requesting Salesforce servers IP address to the Trusted IP addresses under Administration Setup > Securtiy Controls > Network Access: Trusted IP Ranges. You could also check Salesforce IP Address to whitelist

This isn't so applicable anymore, but does provide a sample working version from anonymous apex

It would appear that the sample code isn't building a valid SOAP POST request for the partner API. In particular, it is missing the body element. I modified the way the XML is created and got it working.

The request body should look something like:

<?xml version="1.0" encoding="utf-8"?>
<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<env:Header />
<env:Body>
<login xmlns="urn:partner.soap.sforce.com">
<username>username@example.com</username>
<password>UserPasswordqFOSeCuRiTyTokEn9v6DeJysC</password>
</login>
</env:Body>
</env:Envelope>

Here is the hastily modified login Soap message. Note the additional XML declaration and Body plus Header elements in the xmlOutput.

String LOGIN_DOMAIN = 'login'; //other options: test, prerellogin.pre
String username = UserInfo.getUsername();
String password = 'password'; // + security token

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 = 
      '<?xml version="1.0" encoding="utf-8"?>\n'
      + '<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/">'
      + '<Header />' 
      + '<Body>' 
      + w.getXmlString() 
      + '</Body>'
      + '</Envelope>';
w.close();

System.debug(xmlOutput);

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(xmlOutput);

//basically if there is a loginResponse element, then login succeeded; else there
//  would be soap fault element after body
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) { System.debug('Correct password!'); }
else { System.debug('Incorrect password!'); 
  • 1
    Look more closely at the sample code, Body is there, an empty Header isn't needed. – superfell Oct 22 '14 at 21:02
  • That s great Daniel! Thanks a lot. There is only one point that isn t clear to me: now you are adding the security token to the password.Is it required?Is there a method in apex to get a token for user?Because in my old code i wasn t using them. – MarcoDev Oct 22 '14 at 21:03
  • @superfell Quite right, I'm not sure where I misplaced it in converting to anonymous apex. – Daniel Ballinger Oct 22 '14 at 21:08
  • @MarcoDev I was wrong about the Body missing in the request. The security token is required when logging in from an untrusted IP address. Check your Network Access settings. If the IP isn't there you will need the security token. – Daniel Ballinger Oct 22 '14 at 21:11
  • I see under my user detail "Failed: API security token required" but i ve added myip address to the trusted. Is there some other security setting to check? – MarcoDev Oct 22 '14 at 21:17

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.