SweetzpotAS / StravaZpot-Swift

An API to integrate with Strava on iOS apps
21 stars 7 forks source link

"Unauthorized access. Request a new token." #4

Open frogg opened 5 years ago

frogg commented 5 years ago

I am able to retrieve a token from the AuthenticationAPI.

However, when I attempt to use that token for any use-case (e.g., submit new activity to Strava or retrieve the current athlete) I always receive an error message:

[Result]: FAILURE: responseValidationFailed(reason: Alamofire.AFError.ResponseValidationFailureReason.unacceptableStatusCode(code: 401))
[Timeline]: Timeline: { "Request Start Time": 564070180.995, "Initial Response Time": 564070181.299, "Request Completed Time": 564070181.300, "Serialization Completed Time": 564070181.301, "Latency": 0.305 secs, "Request Duration": 0.306 secs, "Serialization Duration": 0.000 secs, "Total Duration": 0.306 secs }
unauthorized(message: "Unauthorized access. Request a new token.")

I am not quite sure what I am doing wrong. What I noticed is, that the official Strava API is always talking about two tokens (which is kind of confusing): "Access tokens" and "Refresh Tokens". In your API however, I only read about one token. Is your code still up to date in this regard? Or am I missing something else?

Thanks a lot!

ehmjaysee commented 5 years ago

Hi, did you ever get past this error? I see your PR dated Dec 4 which is later than your comment here so I assume you got past it somehow. I pulled in your PR but I still have the same error.

I confirmed I am getting the correct access token by using a different library (StravaSwift) to fetch the token. Both libraries fetch the exact same token (the token value is the same, scope is the same, etc) and with the other library I can use this token to fetch strava activities. But with StravaZpot I always get '401' errors (aka unauthorized access)

ehmjaysee commented 5 years ago

RESOLVED!

Strava expects HTTP headers of the form: "Authorization: Bearer [[token]]"

When you extract the token from loginResult you must use the description property instead of the value property.

        let token = loginResult.token.value   // does not work
        let token = loginResult.token.description   // works!
        let client = HTTPClientBuilder.client(withToken: token, debug: true)

Now I am able to download the activity list.

frogg commented 5 years ago

I don't remember exactly, but this was my solution: let client = HTTPClientBuilder.client(withToken: "Bearer \(token)", debug: false) (note: added the Bearer in front).

Seems like that exactly what the .description var is doing that you've ended up using:

extension Token : CustomStringConvertible {
    public var description : String {
        return "Bearer \(value)"
    }
}