diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 7a65758e..e6f8cc55 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -3,6 +3,7 @@ Contributors Contributors to the codebase, in reverse chronological order: +- Catalina Turlea @catalinaturlea - Maxime Le Moine, @MaximeLM - Seb Skuse, @sebskuse - David Hardiman, @dhardiman diff --git a/Sources/Base/OAuth2Error.swift b/Sources/Base/OAuth2Error.swift index 50bed17f..ef992677 100644 --- a/Sources/Base/OAuth2Error.swift +++ b/Sources/Base/OAuth2Error.swift @@ -82,6 +82,8 @@ public enum OAuth2Error: Error, CustomStringConvertible, Equatable { /// There is no delegate associated with the password grant flow instance. case noPasswordGrantDelegate + /// Generic server error 5xx + case serverErrorWithStatus(Int) // MARK: - Request errors @@ -273,6 +275,8 @@ public enum OAuth2Error: Error, CustomStringConvertible, Equatable { return message ?? "The requested scope is invalid, unknown, or malformed." case .serverError: return "The authorization server encountered an unexpected condition that prevented it from fulfilling the request." + case .serverErrorWithStatus(let statusCode): + return "The authorization server encountered an unexpected condition, returning \(statusCode)" case .temporarilyUnavailable(let message): return message ?? "The authorization server is currently unable to handle the request due to a temporary overloading or maintenance of the server." case .invalidGrant(let message): diff --git a/Sources/Flows/OAuth2.swift b/Sources/Flows/OAuth2.swift index 70702664..e549c05c 100644 --- a/Sources/Flows/OAuth2.swift +++ b/Sources/Flows/OAuth2.swift @@ -352,7 +352,7 @@ open class OAuth2: OAuth2Base { /** If there is a refresh token, use it to receive a fresh access token. - If the request returns an error, the refresh token is thrown away. + Does not remove the refresh_token in case of a failure. For server errors (5xx), the callback provides the status code in .serverErrorWithStatus(Int) - parameter params: Optional key/value pairs to pass during token refresh - parameter callback: The callback to call after the refresh token exchange has finished @@ -364,14 +364,19 @@ open class OAuth2: OAuth2Base { perform(request: post) { response in do { - let data = try response.responseData() - let json = try self.parseRefreshTokenResponseData(data) - if response.response.statusCode >= 400 { - self.clientConfig.refreshToken = nil + let statusCode = response.response.statusCode + switch statusCode { + case 500...599: + throw OAuth2Error.serverErrorWithStatus(statusCode) + // 2xx and 4xx responses should contain valid json data which can be parsed + case 200..<300, 400..<500: + let data = try response.responseData() + let json = try self.parseRefreshTokenResponseData(data) + self.logger?.debug("OAuth2", msg: "Did use refresh token for access token [\(nil != self.clientConfig.accessToken)]") + callback(json, nil) + default: throw OAuth2Error.generic("Failed with status \(response.response.statusCode)") } - self.logger?.debug("OAuth2", msg: "Did use refresh token for access token [\(nil != self.clientConfig.accessToken)]") - callback(json, nil) } catch let error { self.logger?.debug("OAuth2", msg: "Error refreshing access token: \(error)")