trivago / Heimdallr.swift

Easy to use OAuth 2 library for iOS, written in Swift.
Apache License 2.0
639 stars 86 forks source link

Keep refresh token if the server does not return a new one on token refresh #82

Open poislagarde opened 8 years ago

poislagarde commented 8 years ago

My authorization server doesn't always send a new refresh token when refreshing access tokens (as allowed by the spec). When it doesn't, Heimdallr overrides the stored refresh token with nil.

This causes the next refresh to fail with a HeimdallrErrorNotAuthorized error.

I'll try to work on a PR for a fix. Let me know what you think.

domingguss commented 7 years ago

any updates on this issue?

Steps to reproduce: 1) do a proper request 2) enable airplane mode 3) put your device time sufficient enough further in time in order to exceed expiration 4) do the same request 5) Receive an error:

Error Domain=HeimdallrErrorDomain Code=1 "Could not authorize grant" 
UserInfo={
    NSLocalizedDescription=Could not authorize grant, 
    NSLocalizedFailureReason=
    Error Domain=NSURLErrorDomain 
    Code=-1009 "De internetverbinding is offline." 
    UserInfo={
        NSUnderlyingError=0x17064a380 { 
            Error Domain=kCFErrorDomainCFNetwork 
            Code=-1009 "(null)" 
            UserInfo= {
                _kCFStreamErrorCodeKey=50, 
                _kCFStreamErrorDomainKey=1
            }
        }, 
        `NSErrorFailingURLStringKey=https://www.XXXXXX.com/token,` 
        NSErrorFailingURLKey=https://www.XXXXXX.com/token, 
        _kCFStreamErrorDomainKey=1, 
        _kCFStreamErrorCodeKey=50, 
        NSLocalizedDescription=De internetverbinding is offline.
    }
}

6) turn airplane mode off 7) observe that the whole accesToken object has been cleared...

Possible Solution I experienced the same issue, but is it not simple enough to just never self.clearAccessToken(), but instead call self.invalidateAccessToken() ?

Why would one ever want to clear the whole OAuthAccessToken-object? Isn't that only when one would receive an error when your token isn't authorised anymore? How does Heimdallr detect the difference between wrong authorisation error and a simple timeout error?

domingguss commented 7 years ago

no updates on this one?

djuroalfirevic-oviva commented 5 years ago

Guys is this thing resolved perhaps?

RolandasRazma commented 4 years ago

we have this workaround in place

public class TokenServiceStore: OAuthAccessTokenStore {

    private let tokenKeychainStore: OAuthAccessTokenKeychainStore

    public init(service: String) {
        tokenKeychainStore = OAuthAccessTokenKeychainStore(service: service)
    }

    public func storeAccessToken(_ accessToken: OAuthAccessToken?) {
        if let accessToken = accessToken, accessToken.refreshToken == nil, let oldRefreshToken = retrieveAccessToken()?.refreshToken {
            tokenKeychainStore.storeAccessToken(OAuthAccessToken(accessToken: accessToken.accessToken, tokenType: accessToken.tokenType, expiresAt: accessToken.expiresAt, refreshToken: oldRefreshToken))
        } else {
            tokenKeychainStore.storeAccessToken(accessToken)
        }
    }

    public func retrieveAccessToken() -> OAuthAccessToken? {
        return tokenKeychainStore.retrieveAccessToken()
    }

}

let heimdallr: Heimdallr = Heimdallr(..., accessTokenStore: TokenServiceStore(service: ...), ...)