You need to sign in to do that
Don't have an account?
j4jamshaid
Restful Webservice Authetication
HI,
i am acessing an external webservice using apex class. My external webserices is restful webservice and it uses Digest access authentication. I am acessing it in java and its working fine. I need to access it using apex code. Here is my apex code...
HttpRequest req = new HttpRequest();
req.setEndpoint(serviceEndPoint);
req.setMethod('POST');
req.setBody(xmlFeed);
String myDeveloperAPIKey = 'xxxx';
String username = myDeveloperAPIKey + '%xxxxxuserName';
String password = 'xxxPassword';
Blob headerValue = Crypto.generateDigest('MD5', Blob.valueOf('username:password'));
String authorizationHeader = EncodingUtil.convertToHex(headerValue );
req.setHeader('Authorization',authorizationHeader );
req.setHeader('charset', 'UTF-8');
req.setHeader('Content-Type', 'application/atom+xml');
Http http = new Http();
HTTPResponse res = http.send(req);
return 'status=' + res.getStatus();
It is returning Status="unAuthorized", where as userName/Pasword/key are all correct. can anybody figure out whats wrong here? or what is missing?...
i am acessing an external webservice using apex class. My external webserices is restful webservice and it uses Digest access authentication. I am acessing it in java and its working fine. I need to access it using apex code. Here is my apex code...
HttpRequest req = new HttpRequest();
req.setEndpoint(serviceEndPoint);
req.setMethod('POST');
req.setBody(xmlFeed);
String myDeveloperAPIKey = 'xxxx';
String username = myDeveloperAPIKey + '%xxxxxuserName';
String password = 'xxxPassword';
Blob headerValue = Crypto.generateDigest('MD5', Blob.valueOf('username:password'));
String authorizationHeader = EncodingUtil.convertToHex(headerValue );
req.setHeader('Authorization',authorizationHeader );
req.setHeader('charset', 'UTF-8');
req.setHeader('Content-Type', 'application/atom+xml');
Http http = new Http();
HTTPResponse res = http.send(req);
return 'status=' + res.getStatus();
It is returning Status="unAuthorized", where as userName/Pasword/key are all correct. can anybody figure out whats wrong here? or what is missing?...
1- UserName in generateDigest is somthing like this (APIkey % Username). This is the requirement of the my target web service. This is like this....
String myDeveloperAPIKey = 'xxxx';
String username = myDeveloperAPIKey + '%' + 'xxxxxName';
String password = 'xxxPassword';
Blob headerValue = Crypto.generateDigest('MD5', Blob.valueOf('username:password'));
2- There is too little about generateDigest in api docs, Can any one share my a detail article of using this?
3- Can anyone share the sample code that uses generateDigest in its implimentation?
Thanks for replying my friends.
--Jamshaid.
is the string literal username:password, and nothing to do with your variables called username and password.
Thanks for sharing...
1- i have tried it with the real values and making a string literal of them as following, but it is sending me the same error, I guess i am not using the generateDigest correctly....
Blob headerValue = Crypto.generateDigest('MD5', Blob.valueOf('xxxkey%xxxUsername:xxxPassword'));
2- Can you share any code sample that uses this generateDigest?
Thanks again..
--Jamshaid..
http://www.salesforce.com/us/developer/docs/apexcode/index_CSH.htm#apex_classes_restful_crypto.htm
i have seen that example but it is not helping me out. this example uses generteMac and i need to use generateDigest. here is my code.. Lets review it again.
String atom = '<entry> XML FEED </entry>';
String uri = 'http://api./samplexxxx/lists';
String myDeveloperAPIKey = '1232-12321-12312-123-12123213-xxxx';
String username = 'xxxUserName';
String password = 'xxxABC';
String realm='api.realmxxx.com';
HttpRequest req = new HttpRequest();
req.setEndpoint(uri);
req.setMethod('POST');
req.setBody(atom);
Blob headerValue = Crypto.generateDigest('MD5', Blob.valueOf(username+':'+ password));
(I have used these authorizationHeader .. but no one is working.)
String authorizationHeader = 'DIGEST '+EncodingUtil.convertToHex(headerValue );
//String authorizationHeader = 'DIGEST ' + EncodingUtil.base64Encode(headerValue );
//String authorizationHeader ='DIGEST ' + EncodingUtil.urlEncode(EncodingUtil.base64Encode(headerValue), 'UTF-8');
req.setHeader('Authorization',authorizationHeader );
req.setHeader('charset', 'UTF-8');
req.setHeader('Content-Type', 'application/atom+xml');
Http http = new Http();
HTTPResponse res = http.send(req);
status= res.getStatus();
Here it is returns me "UnAuthorized" message... I need to study more about this "Crypto.generateDigest". How it works? What must be the out put? Any Detail documentation of the this Method? Please share.
--Jamshaid..
The idea is that you provide the web service with an encrypted version of a string (I don't know which service you're trying to contact, so I can't tell you what string you need to construct), which you then sign using your Developer key ... (your 'secret').
What Simon is saying is that your code can never work because nowhere in your code do you use your developer key to encrypt your credentials.
-> Blob headerValue = Crypto.generateDigest('MD5', Blob.valueOf(username+':'+ password));
You definately need more than just username and password.
Read this perhaps to see what the concept is all about :
http://en.wikipedia.org/wiki/Cryptographic_hash_function
Bottom line : you need to check the docs of the service you're trying to connect to carefully, and look for the string they want you to sign/send over. It surely must be something more than just your username + password ....
Hope this helps,
David
Edit : I just noticed that you mentioned something about what they want you to send over.
-> myDeveloperAPIKey + '%' + 'xxxxxName'
Perhaps it would work with :
Blob headerValue = Crypto.generateDigest('MD5', Blob.valueOf(myDeveloperAPIKey + '%' + username +':'+ password));
Message Edited by David VP on 10-08-2008 05:39 PM
David, i have it both ways, But it is not working ...
-> Blob headerValue = Crypto.generateDigest('MD5', Blob.valueOf(username+':'+ password));//( where username = (developerKey % UserName))
-> Blob headerValue = Crypto.generateDigest('MD5', Blob.valueOf(developerKey+'%'+username+':'+ password));
My target Restful webservice requires the developerKey +'%' appended by username and password is used as it is. Here is my java code implimentation. It is working fine. It may help to understand.
UsernamePasswordCredentials credentials =
new UsernamePasswordCredentials(DeveloperApiKey()+ "%" + UserName(), Password());
HostConfiguration hostConfiguration = new HostConfiguration();
hostConfiguration.setHost(Constants.CTCT_HOST);
AuthScope authScope = new AuthScope(HOST, PORT,HOST);
AuthPolicy.registerAuthScheme("Digest", DigestScheme.class);
HttpClient httpClient = new HttpClient();
httpClient.setHostConfiguration(hostConfiguration) ;
List<String> list = new ArrayList<String>();
list.add(AuthPolicy.DIGEST);
//authorizationHeader
httpClient.getParams().setParameter(AuthPolicy.AUTH_SCHEME_PRIORITY, list);
httpClient.getState().setCredentials(authScope, credentials);
GetMethod httpGet = new GetMethod(uri);
int status = httpClient.executeMethod(httpGet);
--Jamshiad..
i am implementing RFC 2617. Following is my apex implementation code. When i debug my java code and get the value of Authorization Header it is as following. When i use the same values even nonce and cnonce, in my apex implementation the response value is different. I have tried many combination to generate the same response value using same value in Apex implementation but response value is different. What is missing in my apex implementation?
/**************** Java Code Authorization Header *********
Authorization: Digest username="userA",
realm="abc.com",
nonce="e8cd2bbc2f36e111dbb5679ac1d29412",
uri="http://abc.com/ws/opens",
response="f2ebf049628bf0bba7f4ff078e875c16",
qop=auth, nc=00000001,
cnonce="c1dc11b3c4eec3c1e55b3e41a23da365"
***************************************************************/
/************** Apex Code Implementation **********************/
static String basicAuthCallout(String abc){
try{
String uri = 'http://abc.com/ws/opens';
String myDeveloperAPIKey = 'xyxz-sfssbsd-23423424-xxxx';
String username = 'userA';
String password = 'userA';
String realm='abc.com';
HttpRequest req = new HttpRequest();
String nonce = 'e8cd2bbc2f36e111dbb5679ac1d29412';
String a1 = myDeveloperAPIKey+'%'+username+':'+realm+':'+ password;
String a2 = 'GET:'+ uri;
String HA1= EncodingUtil.convertToHex(Crypto.generateDigest('MD5', Blob.valueOf(a1)));
String HA2 =EncodingUtil.convertToHex(Crypto.generateDigest('MD5', Blob.valueOf(a2)));
//String resString = HA1+':'+nonce+':'+HA2 ;
String resString = HA1+':'+nonce+':00000001:c1dc11b3c4eec3c1e55b3e41a23da365:"auth":'+HA2 ;
//Here cnounce is same as java code value.
String responseDigest = EncodingUtil.convertToHex(Crypto.generateDigest('MD5', Blob.valueOf(resString)));
String authorizationHeader = createAuthorizationHeader(myDeveloperAPIKey +'%'+username,realm, nonce, uri,responseDigest);
req.setEndpoint(uri);
req.setMethod('GET');
req.setHeader('Authorization',authorizationHeader );
req.setHeader('Content-Type', 'application/atom+xml');
Http http = new Http();
HTTPResponse res = http.send(req);
return 'status='+res.getStatus();
}catch(Exception ex){
return 'Exception=' + ex.getMessage();
}
}
/*********************
Other Static methods.
**********************/
// Here cnounce is same as java code value ...
Static String createAuthorizationHeader(String username, String realm, String nonce, String uri,
String responseDigest) {
return 'Digest username="'+ username + '", realm="' + realm + '", nonce="' + nonce +'",uri="'+ uri +'", response="' + responseDigest + '", qop=auth, nc=00000001,cnonce="c1dc11b3c4eec3c1e55b3e41a23da365"';
}
}
You are right, nonce value can't be used again over and over. But point is that using the same old nonce and cnonce values of java code must generate the same response value, that will prove the correct apex code implementation. But using same old nonce and cnonce value in apex implementation, response value is different. it means somthing is worng in above apex implimentation. What it can be ???
Thanks
--Jamshaid.