Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AuthenticationInterceptor 'refresh' delegate called many times for multiple requests #3297

Open
1 task done
youss-cs opened this issue Sep 7, 2020 · 3 comments
Open
1 task done
Assignees
Labels

Comments

@youss-cs
Copy link

youss-cs commented Sep 7, 2020

ℹ Please fill out this template when filing an issue.
All lines beginning with an ℹ symbol instruct you with what info we expect. You can delete those lines once you've filled in the info.

Per our *CONTRIBUTING guidelines, we use GitHub for
bugs and feature requests, not general support. Other issues should be opened on Stack Overflow with the tag alamofire.

Please remove this line and everything above it before submitting.

What did you do?

import Alamofire
import SwiftyJSON

struct OAuthCredential: AuthenticationCredential {
    let accessToken: String
    let refreshToken: String
    let expiration: Date

    // Require refresh if within 5 minutes of expiration
    var requiresRefresh: Bool { Date(timeIntervalSinceNow: 60 * 5) > expiration }
}

class OAuthAuthenticator: Authenticator {
    func apply(_ credential: OAuthCredential, to urlRequest: inout URLRequest) {
        urlRequest.headers.add(.authorization(bearerToken: credential.accessToken))
    }

    func refresh(_ credential: OAuthCredential, for session: Session, completion: @escaping (Result<OAuthCredential, Error>) -> Void) {
        
        NetworkManager.shared.oauth.doRefreshToken { (jsonDict, error) in
            if let jsonDict = jsonDict {
                let json = JSON(jsonDict)
                let accessToken = json["access_token"].stringValue
                let refreshToken = json["refresh_token"].stringValue
                let expiration = json["expires_in"].doubleValue
                let newCredential = OAuthCredential(accessToken: accessToken, refreshToken: refreshToken, expiration: Date(timeIntervalSinceNow: expiration))
                completion(.success(newCredential))
            }
        }
    }

    func didRequest(_ urlRequest: URLRequest, with response: HTTPURLResponse, failDueToAuthenticationError error: Error) -> Bool {
        return response.statusCode == 401
    }

    func isRequest(_ urlRequest: URLRequest, authenticatedWith credential: OAuthCredential) -> Bool {
        let bearerToken = HTTPHeader.authorization(bearerToken: credential.accessToken).value
        return urlRequest.headers["Authorization"] == bearerToken
    }
}  

What did you expect to happen?

ℹ 'refresh' delegate method will be called once to refresh token and then recall all the other requests with new credentials

What happened instead?

ℹ 'refresh' delegate method is called for each request when 'requiresRefresh' is set

Alamofire Environment

Alamofire version: 5.2.2
Xcode version: 11.7
Swift version: 4.2
Platform(s) running Alamofire: iOS
macOS version running Xcode: 10.15.6 (19G2021)

Demo Project

ℹ Cannot provide demo project

@jshier
Copy link
Contributor

jshier commented Sep 8, 2020

@cnoon Can you take a look?

@rmdan90
Copy link

rmdan90 commented Jan 15, 2022

Did you find a solution for this.

@ReilganInt
Copy link

ReilganInt commented Jun 17, 2022

Where is 'completion(.failure(error))' in 'func refresh(_ credential: OAuthCredential, for session: Session, completion: @escaping (Result<OAuthCredential, Error>) -> Void)'?

And Are you sure you chose the correct initializer? In 'Date(timeIntervalSinceNow: expiration)' ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

5 participants