[GH-ISSUE #358] Filter Empty Parameters #226

Closed
opened 2026-03-03 16:46:51 +03:00 by kerem · 6 comments
Owner

Originally created by @rhvall on GitHub (Apr 4, 2017).
Original GitHub issue: https://github.com/OAuthSwift/OAuthSwift/issues/358

Description:

I have been using OAuthSwift to connect to Salesforce; it might be just salesforce, but I am not using a "secret token" to authenticate to the service in the device, but I only have a client ID and renew token. Later, when I want to get a new token, I pass the client ID and the renew token and I get back a new access token from Salesforce.

The problem is, if I don't have a secret token, when I construct a OAuth2Swift object the renew and I have to pass an empty secret, I get a 401 result, however, if I simply comment the code that appends "client_secret" from the list of parameters, I get the expected result (access token).

OAuth Provider (Twitter, Github, ..):

SalesForce

OAuth Version:

  • Version 1
  • Version 2

OS (Please fill the version) :

  • iOS :
  • OSX :
  • TVOS :
  • WatchOS :

Installation method:

  • Carthage
  • CocoaPods
  • Manually

Library version:

  • head
  • v1.0.0
  • v0.6
  • other: (Please fill in the version you are using.)

Xcode version:

  • 8.0 (Swift 3.0)

  • 8.0 (Swift 2.3)

  • 7.3.1

  • other: (Please fill in the version you are using.)

  • objective c

Proposed Solution

Filter empty or null parameters from the list of parameters before initiating the network request. File "OAuth2Swift", Method: "requestOAuthAccessToken"

Code:

let filteredParams = parameters.filter { $1 != nil && String(describing: $1).isEmpty == false }
        
        if self.contentType == "multipart/form-data" {
            // Request new access token by disabling check on current token expiration. This is safe because the implementation wants the user to retrieve a new token.
            return self.client.postMultiPartRequest(accessTokenUrl, method: .POST, parameters: filteredParams, headers: headers, checkTokenExpiration: false, success: successHandler, failure: failure)
        } else {
            // special headers
            var finalHeaders: OAuthSwift.Headers? = nil
            if accessTokenBasicAuthentification {
                
                let authentification = "\(self.consumerKey):\(self.consumerSecret)".data(using: String.Encoding.utf8)
                if let base64Encoded = authentification?.base64EncodedString(options: Data.Base64EncodingOptions(rawValue: 0)) {
                    finalHeaders += ["Authorization": "Basic \(base64Encoded)"] as OAuthSwift.Headers
                }
            }
            
            // Request new access token by disabling check on current token expiration. This is safe because the implementation wants the user to retrieve a new token.
            return self.client.request(accessTokenUrl, method: .POST, parameters: filteredParams, headers: finalHeaders, checkTokenExpiration: false, success: successHandler, failure: failure)
        }

The first line is what makes the magic, avoid any nil or empty description string. After that is just replacing "parameter" with filteredParams in the request methods.

Originally created by @rhvall on GitHub (Apr 4, 2017). Original GitHub issue: https://github.com/OAuthSwift/OAuthSwift/issues/358 ### Description: I have been using OAuthSwift to connect to Salesforce; it might be just salesforce, but I am not using a "secret token" to authenticate to the service in the device, but I only have a client ID and renew token. Later, when I want to get a new token, I pass the client ID and the renew token and I get back a new access token from Salesforce. The problem is, if I don't have a secret token, when I construct a OAuth2Swift object the renew and I have to pass an empty secret, I get a 401 result, however, if I simply comment the code that appends "client_secret" from the list of parameters, I get the expected result (access token). ### OAuth Provider (Twitter, Github, ..): SalesForce ### OAuth Version: - [ ] Version 1 - [X] Version 2 ### OS (Please fill the version) : - [x] iOS : - [ ] OSX : - [ ] TVOS : - [ ] WatchOS : ### Installation method: - [ ] Carthage - [X] CocoaPods - [ ] Manually ### Library version: - [X] head - [ ] v1.0.0 - [ ] v0.6 - [ ] other: (Please fill in the version you are using.) ### Xcode version: - [X] 8.0 (Swift 3.0) - [ ] 8.0 (Swift 2.3) - [ ] 7.3.1 - [ ] other: (Please fill in the version you are using.) - [ ] objective c ### Proposed Solution Filter empty or null parameters from the list of parameters before initiating the network request. File "OAuth2Swift", Method: "requestOAuthAccessToken" Code: ``` let filteredParams = parameters.filter { $1 != nil && String(describing: $1).isEmpty == false } if self.contentType == "multipart/form-data" { // Request new access token by disabling check on current token expiration. This is safe because the implementation wants the user to retrieve a new token. return self.client.postMultiPartRequest(accessTokenUrl, method: .POST, parameters: filteredParams, headers: headers, checkTokenExpiration: false, success: successHandler, failure: failure) } else { // special headers var finalHeaders: OAuthSwift.Headers? = nil if accessTokenBasicAuthentification { let authentification = "\(self.consumerKey):\(self.consumerSecret)".data(using: String.Encoding.utf8) if let base64Encoded = authentification?.base64EncodedString(options: Data.Base64EncodingOptions(rawValue: 0)) { finalHeaders += ["Authorization": "Basic \(base64Encoded)"] as OAuthSwift.Headers } } // Request new access token by disabling check on current token expiration. This is safe because the implementation wants the user to retrieve a new token. return self.client.request(accessTokenUrl, method: .POST, parameters: filteredParams, headers: finalHeaders, checkTokenExpiration: false, success: successHandler, failure: failure) } ``` The first line is what makes the magic, avoid any nil or empty description string. After that is just replacing "parameter" with filteredParams in the request methods.
kerem 2026-03-03 16:46:51 +03:00
Author
Owner

@phimage commented on GitHub (Apr 15, 2017):

that's not oauth authentication flow, maybe it's a security issue...
there is consumer secret in salesforce declared app
if you have a refresh/renew token its because you have already connected using secret...

https://developer.salesforce.com/page/Digging_Deeper_into_OAuth_2.0_on_Force.com#Token_Refresh

<!-- gh-comment-id:294302921 --> @phimage commented on GitHub (Apr 15, 2017): that's not oauth authentication flow, maybe it's a security issue... there is consumer secret in salesforce declared app if you have a refresh/renew token its because you have already connected using secret... https://developer.salesforce.com/page/Digging_Deeper_into_OAuth_2.0_on_Force.com#Token_Refresh
Author
Owner

@rhvall commented on GitHub (May 26, 2017):

Hello @phimage,

Thanks for the reference, I have ran the Salesforce example in the project and certainly that helped me to understand the whole flow. Also, I checked that again and you can notice there a very important detail in it:

client_secret Your application's client secret (optional).

The value of client_secret is not mandatory, reason why the flow we have in the app is not using a client secret. If you go back to the section "Obtaining an Access Token in a Browser or Native Application (User-Agent Flow)", you will notice that client_secret is not part of the response, we have almost everything but that.

I hope we can revisit this trouble.

Thanks

<!-- gh-comment-id:304311272 --> @rhvall commented on GitHub (May 26, 2017): Hello @phimage, Thanks for the reference, I have ran the Salesforce example in the project and certainly that helped me to understand the whole flow. Also, I checked that again and you can notice there a very important detail in it: ```client_secret Your application's client secret (optional).``` The value of ```client_secret``` is not mandatory, reason why the flow we have in the app is not using a client secret. If you go back to the section "Obtaining an Access Token in a Browser or Native Application (User-Agent Flow)", you will notice that ```client_secret``` is not part of the response, we have almost everything but that. I hope we can revisit this trouble. Thanks
Author
Owner

@phimage commented on GitHub (Jun 2, 2017):

@rhvall could you show me in documentation where client secret is optional
maybe not oauth standard flow, but for JWT token or SAML

<!-- gh-comment-id:305802328 --> @phimage commented on GitHub (Jun 2, 2017): @rhvall could you show me in documentation where client secret is optional maybe not oauth standard flow, but for JWT token or SAML
Author
Owner

@rhvall commented on GitHub (Jun 6, 2017):

That line I took is exactly from the link to Salesforce that you had in your response:

https://developer.salesforce.com/page/Digging_Deeper_into_OAuth_2.0_on_Force.com#Token_Refresh

If you check the list of elements to send to the server, the "client secret" is an optional value.

<!-- gh-comment-id:306519762 --> @rhvall commented on GitHub (Jun 6, 2017): That line I took is exactly from the link to Salesforce that you had in your response: https://developer.salesforce.com/page/Digging_Deeper_into_OAuth_2.0_on_Force.com#Token_Refresh If you check the list of elements to send to the server, the "client secret" is an optional value.
Author
Owner

@phimage commented on GitHub (Jun 7, 2017):

client secret here could be optional because refresh token can contain enough information to be trusted, but could also be expired

what I do not understand is how you get a refresh token without this client secret (and so why here stop to use it)
I do not understand the authentification flow

You can PR a code which check if client_secret is empty that do not add it

<!-- gh-comment-id:306709637 --> @phimage commented on GitHub (Jun 7, 2017): client secret here could be optional because refresh token can contain enough information to be trusted, but could also be expired what I do not understand is how you get a refresh token without this client secret (and so why here stop to use it) I do not understand the authentification flow You can PR a code which check if client_secret is empty that do not add it
Author
Owner

@phimage commented on GitHub (Aug 14, 2017):

I close, no PR..

<!-- gh-comment-id:322110195 --> @phimage commented on GitHub (Aug 14, 2017): I close, no PR..
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#226
No description provided.