Search code examples
swiftswiftuigraphqlapollo

Apollo Grapql Refresh Token swift


I'm trying to build network layer using Apollo, and got one problem. I'm using tutorial from Apollo docs to refresh tokens. And they said that I should provide interceptor to handle token expired date. I did it. But I should create network request to refresh token, and this request catch by interceptor too. How I can resolve it?

class NetworkInterceptorProvider: DefaultInterceptorProvider {
override func interceptors<Operation: GraphQLOperation>(for operation: Operation) -> [ApolloInterceptor] {
    var interceptors = super.interceptors(for: operation)
    interceptors.insert(UserManagementInterceptor(), at: 0)
    return interceptors
}

My UserManagementInterceptor:

 func interceptAsync<Operation: GraphQLOperation>(
    chain: RequestChain,
    request: HTTPRequest<Operation>,
    response: HTTPResponse<Operation>?,
    completion: @escaping (Result<GraphQLResult<Operation.Data>, Error>) -> Void
) {
    guard let token = AuthenticationService.shared.getAccessToken() else {
        chain.handleErrorAsync(
            UserError.noUserLoggedIn,
            request: request,
            response: response,
            completion: completion
        )
        AuthenticationService.shared.status = .unauthenticated
        print("No access token")
        return
    }
    if AuthenticationService.shared.checkTokenExpired() {
        print("Token expired")
        guard let refreshToken = AuthenticationService.shared.getRefreshToken() else {
            AuthenticationService.shared.status = .unauthenticated
            print("No refresh token")
            return
        }
        NetworkManager.shared.apollo.perform(mutation: Network.RefreshTokenMutation(token: refreshToken)) { [weak self] tokenRenewResult in
            guard let self else { return }
            switch tokenRenewResult {
            case .failure:
                AuthenticationService.shared.status = .unauthenticated
                print("Filed request")
                break
            case let .success(token):

As result I've got recursion with "Token expired", because my network request RefreshTokenMutation passed through this interceptor too... How I can create exception for token refresh network method?


Solution

  • This is my solution:

     class NetworkInterceptorProvider: DefaultInterceptorProvider {
            override func interceptors<Operation: GraphQLOperation>(for operation: Operation) -> [ApolloInterceptor] {
                var interceptors = super.interceptors(for: operation)
                if checkIsAuthorizationRequired(for: operation) {} else {
                    interceptors.insert(UserManagementInterceptor(), at: 0)
                }
                return interceptors
            }
        
            func checkIsAuthorizationRequired<Operation: GraphQLOperation>(for _: Operation) -> Bool {
                let authLoginOperation = Operation.operationName == "AuthLoginMutation"
                let refreshTokenOperation = Operation.operationName == "RefreshToken"
                let signUp = Operation.operationName == "AuthSignUp"
                if authLoginOperation || refreshTokenOperation || signUp {
                    return true
                } else {
                    return false
                }
            }
        }