mirror of
https://github.com/OAuthSwift/OAuthSwift.git
synced 2026-04-26 20:55:57 +03:00
[GH-ISSUE #115] Error in signature calculation #68
Labels
No labels
bug
cocoapod
duplicate
enhancement
feature-request
help wanted
help wanted
invalid
pull-request
question
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
starred/OAuthSwift#68
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @olivier38070 on GitHub (Sep 29, 2015).
Original GitHub issue: https://github.com/OAuthSwift/OAuthSwift/issues/115
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
@phimage commented on GitHub (Sep 29, 2015):
make a fork, a branch and commit your code into, then it's easy to make a diff online
here it's difficult to see what you have done and where
@perfectflowltd commented on GitHub (Oct 9, 2015):
I'm seeing this issue too. olivier38070 fix didn't work for me
@phimage commented on GitHub (Nov 11, 2015):
@App8ite if you try olivier fix, could you commit into your fork? (into a branch)
maybe also #80
@olivier38070 commented on GitHub (Nov 11, 2015):
sorry to have been lazy. I should have committed my stuff, and forgot it
(too overloaded in my job)
I will try to do it soon, I have to get my source back.
2015-11-11 10:01 GMT+01:00 Phi Mage notifications@github.com:
@pculligan commented on GitHub (Nov 13, 2015):
Is there a test case that can demonstrate what's wrong? I am curious if #141 fixed this. There have been some changes in this area and I'd like to know if it's still open. If you can describe the case, I'll test.
@phimage commented on GitHub (Nov 26, 2015):
added unit test about signature
4ec66e4fd1(based on google unit test)to fix potential issues or label this issue as bug, I need an oauth data set (URL,parameters,consumer key,consumer secret,token,token secret,timestamp,nonce)
@ohcrfpv commented on GitHub (Dec 13, 2015):
When I done a POST to twitter api, it responded a message 'Could not authenticate you.'. The same issue?
@phimage commented on GitHub (Dec 13, 2015):
@fewspider thank you to look for a potential identical issue, but for this issue I am waiting for a sample code with problem (api, version, parameters, etc...) from @olivier38070
And I keep open to maybe study the code...
Some signature problem has been fixed last month
You can open a new issue with the version used of OAuthSwift, the code, parameters, etc.. and I will test
@ohcrfpv commented on GitHub (Dec 13, 2015):
@phimage ok,wait a minute
@ohcrfpv commented on GitHub (Dec 13, 2015):
@phimage done
@olivier38070 commented on GitHub (Dec 14, 2015):
Hi,
sorry, I was too busy by my job.
now, I updated the code, and it seems that it has evolve a lot.
I Will have difficulties to commit anything, as my code also is a fork from
an old version, with some modification to work.
what do you suggest I do ?
I could try to get the latest version, remove all my code in my application
and check what if it is working...
(I remind that on my side, I could login on smugmug, but I couldn't
send/upload any images)
here is what gave me trouble :
the signature calculation gave me error, in smugmug, when trying to do
upload.
the code bellow (Part A) is replacing this :
public func signatureForMethod(method: OAuthSwiftHTTPRequest.Method,
url: NSURL, parameters: Dictionary<String, AnyObject>) -> String {
}
located in OauthSwiftCredential.swift
Also, I had trouble with the encoding of the request, when sending datas :
Part A :
// 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
}
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
}
Dictionary<String, AnyObject>, credential: OAuthSwiftCredential) -> String {
https://dev.twitter.com/oauth/overview/creating-signatures
// will add the oauth_signature parameter
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)
}
}
String(url).stringByAddingPercentEncodingWithAllowedCharacters(.URLHostAllowedCharacterSet())
var signBaseString:String = method + "&" + urlPercented
signBaseString += "&" + percentOutput
"&" + self.escapeString(credential.oauth_token_secret)
signingKey.dataUsingEncoding(NSUTF8StringEncoding)!, message:
signBaseString.dataUsingEncoding(NSUTF8StringEncoding)!)!
let oauth_signature = sha1.base64EncodedStringWithOptions([])
authorizationParameters.updateValue(self.escapeString(
oauth_signature) , forKey: "oauth_signature")
headerComponents.joinWithSeparator(",") //
headerComponents.joinWithSeparator(", ")
return finalUrl
}
PArt B:
public func makeRequest(urlString: String, method:
OAuthSwiftHTTPRequest.Method, parameters: [String: AnyObject] = [:],
headers: [String:String]? = nil) -> OAuthSwiftHTTPRequest? {
if let url = NSURL(string: urlString) {
let request = OAuthSwiftHTTPRequest(URL: url, method: method,
parameters: parameters)
if self.credential.oauth2 {
request.headers = ["Authorization": "Bearer
(self.credential.oauth_token)"]
} else {
//let str = ["Authorization": self.encodeParameters(method,
url: url, parameters: parameters, credential: self.credential)]
//request.headers == str
// var str = ["Authorization":
OAuthSwiftClient.authorizationHeaderForMethod(method, url: url, parameters:
parameters, credential: self.credential)]
var str2 = ["Authorization": self.encodeParameters(method,
url: url, parameters: parameters, credential: self.credential)]
request.headers = str2
}
request.successHandler = success
request.failureHandler = failure
request.dataEncoding = dataEncoding
request.encodeParameters = true
"(image)".dataUsingEncoding(NSUTF8StringEncoding)
request.contentType = "image/jpeg" //type
request.start()
in OAuthSwift.swift
in makeRequest (it is now setupRequestForOAuth) :
key)
}
"Content-Type")
//request.setValue(body!.length.description,
forHTTPHeaderField: "Content-Length")
request.HTTPBody = body!
} else {
which replace this :
if let b = body {
request.HTTPBody = b
} else {
the other part of the code are different, but I believe that it is refactor
on your side, as I don't rememmber having updated so much that part.
smugmug need some parameter in the header, even for the upload, if I
remember well what was wrong.
Hope this help.
Olivier
2015-12-13 17:37 GMT+01:00 You shall not pass notifications@github.com:
@phimage commented on GitHub (Dec 14, 2015):
@olivier38070 If you make a fork with your code, and say the provider(smugmug) and the method(post)
This is enough for me, no need to try to pull request, yes there is too many change
@olivier38070 commented on GitHub (Dec 14, 2015):
ok, I tried to commit and push, but I have an error with githib.
I don't see what I can do, as other githib are working fine
"You may not have permission to access OAuthSwift. Check Preferences to
make sure you’re still logged in."
2015-12-14 9:54 GMT+01:00 You shall not pass notifications@github.com:
@phimage commented on GitHub (Dec 14, 2015):
@olivier38070 are you trying to commit to this repo OAuthSwift/OAuthSwift, not your fork maybe?
I think you must not have the repo with last commit, go to the commit where you begin
for instance start with
github.com/olivier38070/OAuthSwift@c6cea89e66and make a branch, commit into this oneOr if you have a local repo with git and your code, remove your OAuthSwift, create an empty one with same name and push you repo into by adding(or checking if alread added) as remote origin
@olivier38070 commented on GitHub (Dec 14, 2015):
I tried using sourcetree (which I know) instead of github desktop tool
provided by github....
seems to work.
2015-12-14 12:05 GMT+01:00 You shall not pass notifications@github.com:
@dbmrq commented on GitHub (Mar 5, 2016):
I was having some trouble with the Goodreads api and #168 didn't fix it, but this did. Is anything still missing for it to be merged? Maybe I could help.
@phimage commented on GitHub (Mar 5, 2016):
@danielbmarques if I understand just adding bracket ( PR #168 for issue #174) do not fix your issues with Goodreads.
You take some code from oliver? you can make a PR if you can, I will read it for sure (here I ask to make a clean one, by merging code from OAuthSwift master)
@dbmrq commented on GitHub (Mar 5, 2016):
Well, it seems I spoke too soon, this didn't actually fix my problem after all.
What I did was to replace my
urlEncodedStringWithEncodingwith the one in #165. Before I did that the POST request I was trying to make never worked. After I changed the code for Olivier's the request worked and I made my comment here, but now I found out it only works some of the time. Which is very weird… the string that gets signed is exactly the same except for thenonceand thetimestampparameters. Yet it works some of the time, and some of the time it doesn't.The problem doesn't seem to be with Goodreads either, since the call works in their app (I think they use some objective C library).
I'll keep working on this and make a PR if I can fix it.
@phimage, if you have any ideas about how to debug this, I'm kind of clueless right now, and I don't know much about OAuth.
One thing that I noticed and might be worth mentioning is that the
urlEncodedStringWithEncoding()gets called multiple times on the same strings. It gets called, for instance, for each parameter in theurlEncodedQueryStringWithEncodingfunction, and then those same parameters are passed to that function again when they're part of the whole url.Edit: I checked the code with the link Olivier mentioned in his first post and after #165 it looks perfect… but I just tested other calls with and without brackets and all my calls that contain brackets in the parameters fail, while the rest of them works.
Edit 2: I think what I said about
urlEncodedStringWithEncoding()being called twice might be on the right track… This patch is what makes Goodreads calls with brackets work on Android. It seems they added a way to encode the parameters only sometimes, if I understood correctly.Thanks for the help and for the great work here.
@cschulte22 commented on GitHub (Mar 7, 2016):
I've had similar problems with the signatures not matching. In my case I'm using this on an iPhone app to connect to my own rails application. From what I can tell I've found two separate issues.
The first problem I had was when sent a parameter in a
POSTorPATCHbody that had a newline character\n. I was getting an incorrect signature and the request would fail. #165 fixed that problem for me.The second problem is when sending a request with square brackets
[]. Those requests were always generating bad signatures for me. #168 did not fix that issue for me, and also still included the problem with the newline characters.Since I have control over both ends of the API, I ended up just going with #165 and not sending any parameters with square brackets. Square bracket parameters in rails are pretty much everywhere, so I'm not entirely happy with that solution, but it let me get something out the door for now.
For what it's worth, I did try checking things with the nouncer signature calculator, but I ended up getting 3 different signatures - one from that, one from this OAuthSwift code, and a third from my rails app using the simple_oauth gem. At that point I figured it wasn't worth trying to track down the proper fix since I had no idea who was wrong. Although I'd be inclined to believe that the rails gem is properly handling square brackets, since they're everywhere in rails and someone else would have discovered that issue over there by now.
Anyway, seems to me like the right way to proceed here would be to merge #165 and then see about a separate fix for #174 based off that.
@dbmrq commented on GitHub (Mar 8, 2016):
Ok, I fixed other problems in my code and now it works with both #165 and #168.
It seems to me like the main difference between those two is that in #165 some of the excluded characters aren't mentioned explicitly: they're taken from
URLQueryAllowedCharacterSet.In both cases it's not clear what the allowed characters are. #165 uses
URLQueryAllowedCharacterSet, whose contents aren't immediately clear, and #168 (as the original code) uses aninvertedSet, which makes clear what characters are excluded, but not which characters are allowed.The OAuth 1.0 specification, on the other hand, is very clear about what is allowed:
So I think it would be a lot better to explicitly state the allowed characters.
I modified my code to do just that:
Since the OAuth specification is so clear, I think this is pretty safe to do, and it works perfectly for me.
@phimage, should I make a PR with that change?
@cschulte22 commented on GitHub (Mar 8, 2016):
@danielbmarques I rebuilt my app using your changes - the newline problem didn't happen but I still had issues with the square brackets. That leads me to believe that the problem is most likely on my end, not in this OAuthSwift code.
I'm in favor of your solution though since it matches the spec. I'll post back here if I ever track down the issue on my end.
@phimage commented on GitHub (Mar 8, 2016):
@danielbmarques thanks you to point out the info from RFC
I have just a doubt because one day I make a comment about information from RFC and the difference in OAuthSwift implemention. (Maybe two method must be created, one for the signature, one other to encode elsewhere, and maybe that"s why there is double encoding sometimes...)
I will look into PR and issues for this comment
@dbmrq commented on GitHub (Mar 9, 2016):
@phimage, oh, it seems you're right. That info is actually from the OAuth 1.0 specification (from what I understand it's a little more strict than RFC3986), and it refers to both the signature base string and the encoding of parameters for the header.
It does add a caveat, though:
I think that only applies for a request's HTTPBody, right? From what I saw in the code the parameters are added to the body in the
setupRequestForOAuth()method of theOAuthSwiftHTTPRequestclass, so we'd have to add a different method just for the encoding of the parameters that go in the body.If that's the case, this is already broken with the current code, though. The spaces sent in the body, for instance, are currently encoded as "%20", not as "+".
So my code wouldn't really change anything about that and it would be safe to change it already.
From what I gather the code that goes in the body must be encoded differently, but at least for me it doesn't matter much: I'm using it as it is, with the spaces encoded incorrectly, but everything is working fine, even when I send spaces inside a parameter's value.
As for the double encoding, I looked into it further and I think that's actually right: http://stackoverflow.com/a/3292691/3539651
Anyway, let me know if/when you want me to make a PR for the changes in the
urlEncodedStringWithEncoding()method… and I can also help writing a different one for the encoding of the body if you decide that's the way to go.@cschulte22, from what I gathered from the Goodreads forums there are a lot of problems with the encoding of brackets in many different clients. Besides that, according to them servers aren't always consistent in the way they decode the brackets, and what works for one may not work for another.
I think it would be a good idea to try debugging your calls in another client, like Chrome's Postman extension, and if your requests work from there your problem is likely somewhere else on your code. If you can't get it to work in other clients, maybe your server decodes things differently… you could try it with the brackets encoded just once (as I said, they're encoded twice in the signature base string), I don't know.
Whether it's with #165, #168 or with my fix, I am now getting proper signatures that match the link Olivier mentioned in the original post, and my calls also match the ones made by the Postman extension and by Paw, a REST client for Mac.
Good luck. :)
@phimage commented on GitHub (Mar 9, 2016):
@danielbmarques you can make a PR at anytime
ps: For Goodreads if a solution is found an option could be added
@dbmrq commented on GitHub (Mar 9, 2016):
@phimage Done. :) #201
I'll add a Goodreads example to the demo when I have the time.
@phimage commented on GitHub (Mar 9, 2016):
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
@cschulte22 commented on GitHub (Mar 15, 2016):
Alright, finally tracked my issue down to code on my server. Thanks @danielbmarques for the recommendations on Postman and Paw. Turns out that OAuthSwift was generating proper signatures for me.
The problem on my server was that I was generating my signature using the parsed parameter hash (i.e.
conversation[subject]=somethingwas turning into{conversation: {subject: 'something'}}). When I updated my server to use the decoded raw post data instead of the parameter hash it fixed the incorrect signatures.@s-aska commented on GitHub (Mar 17, 2016):
This correspondence is correct.
\nis not be escaped is a problem, request in most of the service will fail.I am using the
c163d1d205in their apps.Most of the Library of the various language is compliant to RFC3986.
Perl https://metacpan.org/source/ETHER/URI-1.71/lib/URI/Escape.pm#L157
Ruby 2.2~ http://docs.ruby-lang.org/en/2.2.0/URI.html
python 3.3~ https://docs.python.org/3.3/library/urllib.parse.html
PHP http://rawurlencode.onlinephpfunctions.com/