+ Start a Discussion
Nayana Pawar 5Nayana Pawar 5 

Using OAuth 1.0 encoded requests for external web service calls Error: signature_invalid


down votefavorite

Please help me.

I have a salesforce requirement that necessitates a callout from Apex to an external web service that receives signed OAuth responses.

I am getting oAuth_token successfully. But after that when I am trying to get data using that oAuth_token I am getting error 'signature_invalid'.

Check getAccData method from code as below.

        global class OAuthToken
        {
            private OAuthService__c service;
            private String token;
            private String tokenSecret;
            private Boolean isAccess = false;
            private String verifier;
            private String nonce;
            private String timestamp;
            private String signature;
            private String consumerKey;
            private String consumerSecret;    
            private Map<String,String> parameters = new Map<String,String>();    
            public String message { get; set; }
            public String callbackUrl {get; set; }
            public void setConsumerKey(String value) { consumerKey = value; }
            public void setConsumerSecret(String value) { consumerSecret = value; }
            
            public String newAuthorization(String serviceName)
            {        
                service = [SELECT request_token_url__c, access_token_url__c, consumer_key__c,consumer_secret__c, authorization_url__c,
                                  (select token__c, secret__c, isAccess__c FROM tokens__r WHERE owner__c=:UserInfo.getUserId() ) 
                                  FROM OAuthService__c WHERE name = :serviceName];
                                  
                if(service==null)
                 {
                    System.debug('Couldn\'t find Oauth Service '+serviceName);
                    message = 'Service '+serviceName+' was not found in the local configuration';
                    return null;
                 }
                
                 if(callbackUrl==null) 
                 { 
                    if(ApexPages.currentPage()==null || ApexPages.currentPage().getHeaders().get('Host')==null) {
                        message = 'No callback page was set and it couldn\'t be generated from Apex context';
                        System.debug(message);
                        return null;
                    }
            
                    callbackUrl = EncodingUtil.urlEncode('https://'+ApexPages.currentPage().getHeaders().get('Host')+
                                                         Page.CompleteAuth.getUrl(),'UTF-8');
                 }
                 
                Http h = new Http();
                HttpRequest req = new HttpRequest();
                req.setMethod('POST');
                req.setEndpoint('https://www.gliffy.com/api/1.0/accounts/5023581/users/nileshbhd5@gmail.com/oauth_token.xml?action=create&description=createuser');//service.request_token_url__c        
                req.setTimeout(12000);
                System.debug('Request body set to: '+req.getBody());
                consumerKey = service.consumer_key__c;
                consumerSecret = service.consumer_secret__c;
                sign(req);
                HttpResponse res = null;        
                res = h.send(req);    
                String XMLString = res.getBody();
                parseXML(XMLString); 
                
                System.debug('Response from request token request: ('+res.getStatusCode()+')'+res.getBody());
                if(res.getStatusCode()>299) {
                    message = 'Failed getting a request token. HTTP Code = '+res.getStatusCode()+
                              '. Message: '+res.getStatus()+'. Response Body: '+res.getBody();
                    return null;
                }
                String resParams = serviceName == 'test1234' ?'oauth_token=token&oauth_token_secret=token_secret' : res.getBody();
                Map<String,String> rp = getUrlParams(resParams);
                OAuth_Token__c t = new OAuth_Token__c();
                t.owner__c = UserInfo.getUserId();
                t.OAuth_Service__c = service.id;
                t.token__c = token;
                t.secret__c = tokenSecret;
                t.isAccess__c = false;
                delete service.tokens__r;
                insert t;

                System.debug('Got request token: '+t.token__c+'('+rp.get('oauth_token')+')');
                
                if(service.authorization_url__c.contains('?')) {
                string getAccountURL = 'https://www.gliffy.com/api/1.0/accounts/5023581/users.xml?action=get'+'&oauth_token='+token;
                    return getAccountURL;
                } else {
                    return service.authorization_url__c+'?oauth_token='+EncodingUtil.urlDecode(t.token__c,'UTF-8')+'&oauth_consumer_key='+service.consumer_key__c;
                }
            }
            
            
             public String getAccData(String authUrlName)
             {
               service = [SELECT request_token_url__c, access_token_url__c, consumer_key__c,consumer_secret__c, authorization_url__c,
                                  (select token__c, secret__c, isAccess__c FROM tokens__r WHERE owner__c=:UserInfo.getUserId() ) 
                                  FROM OAuthService__c WHERE name = :'Gliffy'];
              if(service==null)
                 {
                    System.debug('Couldn\'t find Oauth Service '+'Gliffy');
                    message = 'Service '+'Gliffy'+' was not found in the local configuration';
                    return null;
                 }
                 
               if(callbackUrl==null) 
                 { 
                    if(ApexPages.currentPage()==null || ApexPages.currentPage().getHeaders().get('Host')==null) {
                        message = 'No callback page was set and it couldn\'t be generated from Apex context';
                        System.debug(message);
                        return null;
                    }
            
                    callbackUrl = EncodingUtil.urlEncode('https://'+ApexPages.currentPage().getHeaders().get('Host')+
                                                         Page.CompleteAuth.getUrl(),'UTF-8');
                 }
                                  
                Http h = new Http();
                HttpRequest req = new HttpRequest();
                req.setMethod('POST');
                req.setEndpoint(authUrlName);
                req.setTimeout(12000);
                consumerKey = service.consumer_key__c;
                consumerSecret = service.consumer_secret__c;
                sign(req);
                HttpResponse res = null;
                res = h.send(req);
                String XMLString = res.getBody();
                system.debug('Accountdata String:'+XMLString );
                return XMLString;
             }
            
            private void refreshParameters() 
            {
                parameters.clear();
                parameters.put('oauth_consumer_key',consumerKey);
                if(token!=null) {
                    parameters.put('oauth_token',token);
                }
                if(verifier!=null) {
                    parameters.put('oauth_verifier',verifier);
                }
                parameters.put('oauth_signature_method','HMAC-SHA1');
                parameters.put('oauth_timestamp',timestamp);
                parameters.put('oauth_nonce',nonce);
                parameters.put('oauth_callback',callbackUrl);
            }
            
            public void sign(HttpRequest req) 
            {
                
                nonce = String.valueOf(Crypto.getRandomLong());
                timestamp = String.valueOf(DateTime.now().getTime()/1000);
                refreshParameters();        
                String s = createBaseString(parameters, req);        
                      
                Blob sig = Crypto.generateMac('HmacSHA1', Blob.valueOf(s), 
                               Blob.valueOf(consumerSecret+'&'+
                                            (tokenSecret!=null ? tokenSecret : '')));
                signature = EncodingUtil.urlEncode(EncodingUtil.base64encode(sig), 'UTF-8');
                System.debug('Signature: '+signature);
                
                String header = 'OAuth ';
                for (String key : parameters.keySet()) {
                    header = header + key + '="'+parameters.get(key)+'", ';
                }
                header = header + 'oauth_signature="'+signature+'"';
                System.debug('Authorization: '+header);
                req.setHeader('Authorization',header);
            }
          
          private String createBaseString(Map<String,String> oauthParams,HttpRequest req) 
            {
                Map<String,String> p = oauthParams.clone();
                if(req.getMethod().equalsIgnoreCase('post') && req.getBody()!=null && 
                   req.getHeader('Content-Type')=='application/x-www-form-urlencoded')
                   {
                    p.putAll(getUrlParams(req.getBody()));
                }
                String host = req.getEndpoint();
                Integer n = host.indexOf('?');
                if(n>-1) {
                    p.putAll(getUrlParams(host.substring(n+1)));
                    host = host.substring(0,n);
                }
                List<String> keys = new List<String>();
                keys.addAll(p.keySet());
                keys.sort();
                String s = keys.get(0)+'='+p.get(keys.get(0));
                for(Integer i=1;i<keys.size();i++) {
                    s = s + '&' + keys.get(i)+'='+p.get(keys.get(i));
                }

                return req.getMethod().toUpperCase()+ '&' + 
                    EncodingUtil.urlEncode(host, 'UTF-8') + '&' +
                    EncodingUtil.urlEncode(s, 'UTF-8');
            }
          
          private Map<String,String> getUrlParams(String value) 
            {
                Map<String,String> res = new Map<String,String>();
                if(value==null || value=='')
                {
                    return res;
                }
                for(String s : value.split('&')) 
                {
                    System.debug('getUrlParams: '+s);
                    List<String> kv = s.split('=');
                    if(kv.size()>1) {              
                      String encName = EncodingUtil.urlEncode(EncodingUtil.urlDecode(kv[0], 'UTF-8'), 'UTF-8').replace('+','%20');
                      String encValue = EncodingUtil.urlEncode(EncodingUtil.urlDecode(kv[1], 'UTF-8'), 'UTF-8').replace('+','%20');
                      System.debug('getUrlParams:  -> '+encName+','+encValue);
                      res.put(encName,encValue);
                    }
                }
                return res;
            }
          
        }