OAuthSwift: Error in signature calculation
I ccompared with that web site : http://oauth.googlecode.com/svn/code/javascript/example/signature.html
the signature calculated in OAuthSwiftClient, authorizationHeaderForMethod give wrong value. this imply that on some web site, upload fail. here is something I did, which works.
hope this help. Olivier
// convert a Dictionary, in array of string, with escaped string
func getEscapedArrayParam(parameters: Dictionary<String, AnyObject>) -> [String] {
// escape all oauth parameter
var encodedParam = [String]()
for(k, v) in parameters {
let str = k + "=" + (v as! String)
let escapedStr = str.stringByAddingPercentEncodingWithAllowedCharacters(.URLHostAllowedCharacterSet())
encodedParam.append(escapedStr!)
}
// sort the result
encodedParam.sortInPlace{ $0 < $1 }
return encodedParam
}
// do almost like stringByAddingPercentEncodingWithAllowedCharacters, but take in account more character to be changed in %xyz
//!*'();:@&=+$,/?%#[]
func escapeString(str: String) -> String {
let encoding: NSStringEncoding = NSUTF8StringEncoding
// !*'();:@&=+$,/?%#[]
let charactersToBeEscaped = ":/?&=;+!@#$()',*" as CFStringRef
let charactersToLeaveUnescaped = "[]." as CFStringRef
let raw: NSString = str
let result = CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, raw, charactersToLeaveUnescaped, charactersToBeEscaped, CFStringConvertNSStringEncodingToEncoding(encoding))
return result as String
}
public func encodeParameters(method: String, url: NSURL, parameters: Dictionary<String, AnyObject>, credential: OAuthSwiftCredential) -> String {
// algorithm used : https://dev.twitter.com/oauth/overview/creating-signatures
// will add the oauth_signature parameter
//define the oauth parameters
var authorizationParameters = Dictionary<String, AnyObject>()
authorizationParameters["oauth_version"] = OAuth.version
authorizationParameters["oauth_consumer_key"] = credential.consumer_key
authorizationParameters["oauth_timestamp"] = String(Int64(NSDate().timeIntervalSince1970))
authorizationParameters["oauth_nonce"] = (NSUUID().UUIDString as NSString).substringToIndex(8)
authorizationParameters["oauth_signature_method"] = OAuth.signatureMethod
// add token is it exist
if (credential.oauth_token != ""){
authorizationParameters["oauth_token"] = credential.oauth_token
}
// add additionnal oauth (optionnal) parameters if not already existing
// example, oauth_callback, defined when requesting the token
for (key, value) in parameters {
if key.hasPrefix("oauth_") {
authorizationParameters.updateValue(value, forKey: key)
}
}
// escape all oauth parameter
let encodedParam = getEscapedArrayParam(authorizationParameters)
// convert it into a string, each param separated by &
var outputStr:String = ""
for v in encodedParam {
outputStr += v + "&"
}
// remove last "&"
outputStr.removeAtIndex(outputStr.endIndex.predecessor())
// percent encode the oauth sorted, appened, parameters
let percentOutput = self.escapeString(outputStr)
// build the signature base string
let urlPercented = self.escapeString(String(url)) // String(url).stringByAddingPercentEncodingWithAllowedCharacters(.URLHostAllowedCharacterSet())
var signBaseString:String = method + "&" + urlPercented
signBaseString += "&" + percentOutput
// build the signin key
let signingKey = self.escapeString( credential.consumer_secret) + "&" + self.escapeString(credential.oauth_token_secret)
// Build the signature
let sha1 = HMAC.sha1(key: signingKey.dataUsingEncoding(NSUTF8StringEncoding)!, message: signBaseString.dataUsingEncoding(NSUTF8StringEncoding)!)!
let oauth_signature = sha1.base64EncodedStringWithOptions([])
authorizationParameters.updateValue(self.escapeString( oauth_signature) , forKey: "oauth_signature")
// add the signature to the parameters
//encodedParam.append("oauth_signature=" + oauth_signature )
//encodedParam.sortInPlace{ $0 < $1 } // not sure it is useful r not
// create an array, with escape before =
var headerComponents = [String]()
for (key, value) in authorizationParameters {
headerComponents.append("\(key)=\"\(value)\"")
}
let finalUrl:String = "OAuth " + headerComponents.joinWithSeparator(", ")
return finalUrl
}
About this issue
- Original URL
- State: closed
- Created 9 years ago
- Comments: 28 (15 by maintainers)
Commits related to this issue
- #214 changed expected signature in unit test for now - see #115 for the related discussion — committed to FGoessler/OAuthSwift by deleted user 8 years ago
thanks you for your work on this
I keep this issue open to discuss about signature for the moment
And maybe when I have time make some tests on other services or just execute basic tests