spotify / ios-sdk

Spotify SDK for iOS
https://developer.spotify.com/documentation/ios/
641 stars 187 forks source link

SDK includes PKCE parameters to obtain the authorisation code #257

Open azatZul opened 4 years ago

azatZul commented 4 years ago

Last couple days our users can't connect their Spotify account to our app. According to the topic on the Spotify forum: https://community.spotify.com/t5/Spotify-for-Developers/Authentication-API-failing-in-production-right-now/td-p/4959662, it can happen when we start an OAuth flow including PKCE parameters. When we use a Spotify SDK to authorise users, it opens a web-page with the parameter code_challenge. We send received authorisation code to our server to get the access token on their side but now they can't do it. I couldn't find a way how to make SPTSessionManager not to use PKCE. What is the options of the resolving this problem?

Antonio-Melo commented 4 years ago

I'm using the SPTSessionManager to log in and the access token return works just fine. But the refresh token it's not valid. Every time I try to refresh I receive a error: { "error": "invalid_grant", "error_description": "Invalid refresh token" }

oliveroneill commented 4 years ago

I was facing the same issue. Here's a hack I used to retrieve the code_verifier to be passed along with the authorisation code in the grant:

guard let pkceProvider = sessionManager.value(forKey: "PKCEProvider"),
    let codeVerifier = (pkceProvider as AnyObject).value(forKey: "codeVerifier") as? String else {
        // Handle missing value
}

where sessionManager is an SPTSessionManager

oliveroneill commented 4 years ago

Another workaround that does not require PKCE: I've forked and modified SpotifyLogin to retrieve the auth code without the client secret here.

Christilut commented 3 months ago

For anyone reading this and getting an code_verifier required error when using the /api/token endpoint, this is what I did and it doesn't really make sense:

Add this to your configuration (any URL, doesnt seem to get called):

        configuration.tokenSwapURL = URL(string: "https://api.my-server")

Get the code that comes from the Spotify SDK callback URL like this:

    func getQueryStringParameter(url: String, param: String) -> String? {
      guard let url = URLComponents(string: url) else { return nil }
      return url.queryItems?.first(where: { $0.name == param })?.value
    }

  let code = getQueryStringParameter(url: url.absoluteString, param: "code")

For some reason, the code now works on the /api/token endpoint (without PKCE so no code_challenge required).

Without the tokenSwapURL (which is never called, I checked on my server) the code looks good but gives the code_verifier required error.

This works now, maybe it breaks in the future... But maybe it helps someone else who has been breaking his head on this for the entire day :)

gabrielbiga commented 3 months ago

Reading the documentation: https://spotify.github.io/ios-sdk/html/Classes/SPTConfiguration.html#//api/name/tokenSwapURL the behavior makes sense.

The URL to use for attempting to swap an authorization code for an access token. You should only set this if your clientID has a clientSecret and you have a backend service that holds the secret and can exchange the code and secret for an access token.

If we want to fetch the token outside the APP, we probably have some backend that holds the secret.

Thanks for finding it @Christilut !