[GH-ISSUE #450] startAuthorizedRequest() fails to refresh the access token on Google Api #292

Closed
opened 2026-03-03 16:47:27 +03:00 by kerem · 3 comments
Owner

Originally created by @mixable on GitHub (Apr 11, 2018).
Original GitHub issue: https://github.com/OAuthSwift/OAuthSwift/issues/450

Description:

I use OAuth2Swift for authentication on Google. After updating from version 1.1.2 to version 1.2.0, requesting an access token is not possible anymore.

To call the Google api, I use startAuthorizedRequest() in the following way. In 1.1.2 this automatically handled the authorization:

let oauthswift = OAuth2Swift(
    consumerKey:    "... .apps.googleusercontent.com",
    consumerSecret: "",
    authorizeUrl:   "https://accounts.google.com/o/oauth2/auth?access_type=offline&prompt=consent",
    accessTokenUrl: "https://accounts.google.com/o/oauth2/token",
    responseType:   "code"
)
oauthswift.client.credential = ...
oauthswift.startAuthorizedRequest(
    "https://www.googleapis.com/gmail/v1/users/me/messages/send",
    method: .POST,
    parameters: [
        "raw": "..."
    ],
    headers: [
        "Content-Type": "application/json",
        "Accept": "application/json"
    ],
    onTokenRenewal: { (credential) in
        // ...
    },
    success: { (response) in
        // ...
    }
) { (error) in
    // ...
}

The problem appears, when the current token expired and a new token is requested using the refresh token (inside the requestOAuthAccessToken() method). The error returned is:

invalid_request: Invalid header Content Type

It turned out, that this is a problem of the header I use. The send API (3) requires "Content-Type: application/json" to work, the access token API (2) does not allow this Content-Type. But the method requestOAuthAccessToken() uses the same header for both requests.

The reason for the same header is line 239 (OAuth2Swift.swift), which was changed from (v1.1.2):

var finalHeaders: OAuthSwift.Headers? = nil

to (v1.2.0):

var finalHeaders: OAuthSwift.Headers? = headers

The code seems to be correct, but I was wondering if anybody else has this problem. Or are there any suggestions, how to deal with this behavior?

OAuth Provider (Twitter, Github, ..):

Google, the API endpoints are:
(1) Authorize Url https://accounts.google.com/o/oauth2/auth?access_type=offline&prompt=consent
(2) Access Token Url: https://accounts.google.com/o/oauth2/token
(3) Send Email API: https://www.googleapis.com/gmail/v1/users/me/messages/send

OAuth Version:

  • Version 1
  • Version 2

OS (Please fill the version) :

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

Installation method:

  • Carthage
  • CocoaPods
  • Manually

Library version:

  • head
  • v1.2 (Swift 4.0)
  • v1.0.0
  • [x].6
  • [x]her: (Please fill in the version you are using.)

Xcode version:

  • 9.0 (Swift 4.0)

  • 9.0 (Swift 3.2)

  • 8.x (Swift 3.x)

  • 8.0 (Swift 2.3)

  • 7.3.1

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

  • objective c

Originally created by @mixable on GitHub (Apr 11, 2018). Original GitHub issue: https://github.com/OAuthSwift/OAuthSwift/issues/450 ### Description: I use OAuth2Swift for authentication on Google. After updating from version 1.1.2 to version 1.2.0, requesting an access token is not possible anymore. To call the Google api, I use startAuthorizedRequest() in the following way. In 1.1.2 this automatically handled the authorization: let oauthswift = OAuth2Swift( consumerKey: "... .apps.googleusercontent.com", consumerSecret: "", authorizeUrl: "https://accounts.google.com/o/oauth2/auth?access_type=offline&prompt=consent", accessTokenUrl: "https://accounts.google.com/o/oauth2/token", responseType: "code" ) oauthswift.client.credential = ... oauthswift.startAuthorizedRequest( "https://www.googleapis.com/gmail/v1/users/me/messages/send", method: .POST, parameters: [ "raw": "..." ], headers: [ "Content-Type": "application/json", "Accept": "application/json" ], onTokenRenewal: { (credential) in // ... }, success: { (response) in // ... } ) { (error) in // ... } The problem appears, when the current token expired and a new token is requested using the refresh token (inside the requestOAuthAccessToken() method). The error returned is: invalid_request: Invalid header Content Type It turned out, that this is a problem of the header I use. The send API (3) requires "Content-Type: application/json" to work, the access token API (2) does not allow this Content-Type. But the method requestOAuthAccessToken() uses the same header for both requests. The reason for the same header is line 239 (OAuth2Swift.swift), which was changed from (v1.1.2): var finalHeaders: OAuthSwift.Headers? = nil to (v1.2.0): var finalHeaders: OAuthSwift.Headers? = headers The code seems to be correct, but I was wondering if anybody else has this problem. Or are there any suggestions, how to deal with this behavior? ### OAuth Provider (Twitter, Github, ..): Google, the API endpoints are: (1) Authorize Url https://accounts.google.com/o/oauth2/auth?access_type=offline&prompt=consent (2) Access Token Url: https://accounts.google.com/o/oauth2/token (3) Send Email API: https://www.googleapis.com/gmail/v1/users/me/messages/send ### 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: - [ ] head - [x] v1.2 (Swift 4.0) - [ ] v1.0.0 - [ ][x].6 - [ ][x]her: (Please fill in the version you are using.) ### Xcode version: - [x] 9.0 (Swift 4.0) - [ ] 9.0 (Swift 3.2) - [ ] 8.x (Swift 3.x) - [ ] 8.0 (Swift 2.3) - [ ] 7.3.1 - [ ] other: (Please fill in the version you are using.) - [ ] objective c
kerem 2026-03-03 16:47:27 +03:00
  • closed this issue
  • added the
    bug
    label
Author
Owner

@phimage commented on GitHub (May 16, 2018):

I think that the fix for 1.2 reveal a real issue
why use request issue for authentication

there is this code in startAuthorizedRequest

            case OAuthSwiftError.tokenExpired:
                _ = self.renewAccessToken(withRefreshToken: self.client.credential.oauthRefreshToken, headers: headers, ...

@mixable maybe removing the header here will fix your issue
and if we want some specific header for renew, it must be another parameter

<!-- gh-comment-id:389402223 --> @phimage commented on GitHub (May 16, 2018): I think that the fix for 1.2 reveal a real issue why use request issue for authentication there is this code in startAuthorizedRequest ```swift case OAuthSwiftError.tokenExpired: _ = self.renewAccessToken(withRefreshToken: self.client.credential.oauthRefreshToken, headers: headers, ... ``` @mixable maybe removing the header here will fix your issue and if we want some specific header for renew, it must be another parameter
Author
Owner

@mixable commented on GitHub (Jun 14, 2018):

@phimage yes, using a different parameter for the renew request should fix the problem

<!-- gh-comment-id:397259979 --> @mixable commented on GitHub (Jun 14, 2018): @phimage yes, using a different parameter for the renew request should fix the problem
Author
Owner

@phimage commented on GitHub (Jun 25, 2018):

I do want to change the behaviour if some people have provider that need some header so I add a new parameters called renewHeaders

So @mixable you can do

oauthswift.startAuthorizedRequest(
    "https://www.googleapis.com/gmail/v1/users/me/messages/send",
    method: .POST,
    parameters: [
        "raw": "..."
    ],
    headers: [
        "Content-Type": "application/json",
        "Accept": "application/json"
    ],
    renewHeaders: [:], // here a empty header for renew request
    onTokenRenewal: { (credential) in
        // ...
    },
    success: { (response) in
        // ...
    }
) { (error) in
    // ...
}
<!-- gh-comment-id:399885421 --> @phimage commented on GitHub (Jun 25, 2018): I do want to change the behaviour if some people have provider that need some header so I add a new parameters called `renewHeaders` So @mixable you can do ```swift oauthswift.startAuthorizedRequest( "https://www.googleapis.com/gmail/v1/users/me/messages/send", method: .POST, parameters: [ "raw": "..." ], headers: [ "Content-Type": "application/json", "Accept": "application/json" ], renewHeaders: [:], // here a empty header for renew request onTokenRenewal: { (credential) in // ... }, success: { (response) in // ... } ) { (error) in // ... } ```
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#292
No description provided.