[GH-ISSUE #140] OAuth1 exchange fails due token secret being URL encoded. #85

Closed
opened 2026-03-03 16:45:33 +03:00 by kerem · 0 comments
Owner

Originally created by @pculligan on GitHub (Nov 9, 2015).
Original GitHub issue: https://github.com/OAuthSwift/OAuthSwift/issues/140

In using the OAuth1 provider via the OAuthSwiftDemo the initial token request works, but once the credential's oauth_token_secret is assigned, all signatures fail.

Step 1: Request token

POST /platform/oauth/request_token HTTP/1.1
Authorization: OAuth realm="", oauth_callback="oauth-swift%3A%2F%2Foauth-callback%2Fjdcloud", oauth_consumer_key="johndeere-3WuO2CyXvjOAvq5HyQ4C657B", oauth_nonce="1446926761", oauth_signature="ej%2FrsK%2BYoKzQJr8vXqRLc3X81I0%3D", oauth_signature_method="HMAC-SHA1", oauth_timestamp="492373033280972651", oauth_version="1.0"

Note that there is no token at this stage, so the signature is fine, and we get a token and secret back.

HTTP/1.1 200 OK
oauth_token=cb88aa77-6e26-499a-806a-52590d57785b&oauth_token_secret=Q3StNc9bb4n4AF%2FvyiIeiRjwmjqsaBxWWF73wUpqxjjYADLuXRsPrE2sgqLedQmdABSjL9SqDGKEwrc5ZXdow1LiNk7kWQ8K2OY6xp2bRJI%3D&oauth_callback_confirmed=true

When we try to authorize during step 2 however, I get a 401, constantly. After tracing, I found that in the OAuth1Swift.swift file the method takes the callback URL directly.

// 1. Request token
public func postOAuthRequestTokenWithCallbackURL(callbackURL: NSURL, success: TokenSuccessHandler, failure: FailureHandler?) {

...

}

// 3. Get Access token
func postOAuthAccessTokenWithRequestToken(success: TokenSuccessHandler, failure: FailureHandler?) {

...

}

Within the method, the QueryString is parsed by the parametersFromQueryString method into parameters.

    func parametersFromQueryString() -> Dictionary<String, String> {
        var parameters = Dictionary<String, String>()

        let scanner = NSScanner(string: self)

        var key: NSString?
        var value: NSString?

        while !scanner.atEnd {
            key = nil
            scanner.scanUpToString("=", intoString: &key)
            scanner.scanString("=", intoString: nil)

            value = nil
            scanner.scanUpToString("&", intoString: &value)
            scanner.scanString("&", intoString: nil)

            if (key != nil && value != nil) {
                parameters.updateValue(value! as String, forKey: key! as String)
            }
        }

        return parameters
    }

However these are used directly, never decoded in either the postOAuthRequestTokenWithCallbackURL or postOAuthAccessTokenWithRequestToken methods.

            self.client.credential.oauth_token = parameters["oauth_token"]!
            self.client.credential.oauth_token_secret = parameters["oauth_token_secret"]!

I have a local edit that tests out and will submit a PR shortly.

            if let oauthToken=parameters["oauth_token"] {
                self.client.credential.oauth_token = oauthToken.stringByRemovingPercentEncoding!
            }
            if let oauthTokenSecret=parameters["oauth_token_secret"] {
                self.client.credential.oauth_token_secret = oauthTokenSecret.stringByRemovingPercentEncoding!
            }

Originally created by @pculligan on GitHub (Nov 9, 2015). Original GitHub issue: https://github.com/OAuthSwift/OAuthSwift/issues/140 In using the OAuth1 provider via the OAuthSwiftDemo the initial token request works, but once the credential's `oauth_token_secret` is assigned, all signatures fail. Step 1: Request token ``` POST /platform/oauth/request_token HTTP/1.1 Authorization: OAuth realm="", oauth_callback="oauth-swift%3A%2F%2Foauth-callback%2Fjdcloud", oauth_consumer_key="johndeere-3WuO2CyXvjOAvq5HyQ4C657B", oauth_nonce="1446926761", oauth_signature="ej%2FrsK%2BYoKzQJr8vXqRLc3X81I0%3D", oauth_signature_method="HMAC-SHA1", oauth_timestamp="492373033280972651", oauth_version="1.0" ``` Note that there is no token at this stage, so the signature is fine, and we get a token and secret back. ``` HTTP/1.1 200 OK oauth_token=cb88aa77-6e26-499a-806a-52590d57785b&oauth_token_secret=Q3StNc9bb4n4AF%2FvyiIeiRjwmjqsaBxWWF73wUpqxjjYADLuXRsPrE2sgqLedQmdABSjL9SqDGKEwrc5ZXdow1LiNk7kWQ8K2OY6xp2bRJI%3D&oauth_callback_confirmed=true ``` When we try to authorize during step 2 however, I get a 401, constantly. After tracing, I found that in the OAuth1Swift.swift file the method takes the callback URL directly. ``` Swift // 1. Request token public func postOAuthRequestTokenWithCallbackURL(callbackURL: NSURL, success: TokenSuccessHandler, failure: FailureHandler?) { ... } // 3. Get Access token func postOAuthAccessTokenWithRequestToken(success: TokenSuccessHandler, failure: FailureHandler?) { ... } ``` Within the method, the QueryString is parsed by the `parametersFromQueryString` method into `parameters`. ``` func parametersFromQueryString() -> Dictionary<String, String> { var parameters = Dictionary<String, String>() let scanner = NSScanner(string: self) var key: NSString? var value: NSString? while !scanner.atEnd { key = nil scanner.scanUpToString("=", intoString: &key) scanner.scanString("=", intoString: nil) value = nil scanner.scanUpToString("&", intoString: &value) scanner.scanString("&", intoString: nil) if (key != nil && value != nil) { parameters.updateValue(value! as String, forKey: key! as String) } } return parameters } ``` However these are used directly, never decoded in either the `postOAuthRequestTokenWithCallbackURL` or `postOAuthAccessTokenWithRequestToken` methods. ``` self.client.credential.oauth_token = parameters["oauth_token"]! self.client.credential.oauth_token_secret = parameters["oauth_token_secret"]! ``` I have a local edit that tests out and will submit a PR shortly. ``` if let oauthToken=parameters["oauth_token"] { self.client.credential.oauth_token = oauthToken.stringByRemovingPercentEncoding! } if let oauthTokenSecret=parameters["oauth_token_secret"] { self.client.credential.oauth_token_secret = oauthTokenSecret.stringByRemovingPercentEncoding! } ```
kerem 2026-03-03 16:45:33 +03:00
  • closed this issue
  • added the
    bug
    label
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/OAuthSwift#85
No description provided.