spotify / ios-sdk

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

How to do Token Refresh #139

Open dataexcess opened 5 years ago

dataexcess commented 5 years ago

Hi,

In the old SDK we should check for an active token and refresh if expired by doing something amongst the lines:

SPTAuth *spotifyAuth = [SPTAuth defaultInstance];
                if (spotifyAuth.session == nil) { }
                if ([spotifyAuth.session isValid]) { }
                if (spotifyAuth.hasTokenRefreshService) { }

Do we need to do something similar in this new SDK? Or is token refresh automatically handled once given a tokenSwapUrl to the SPTConfiguration instance? Thank you.

jonahpelfrey commented 5 years ago

The Spotify documentation outlines token swap / refresh here

According to the documentation:

By setting tokenSwapURL and tokenRefreshURL it is possible for the iOS-SDK to request a new access token with a refresh token whenever needed.

You can set these URL's when you are configuring the SPTConfiguration instance. An example might look like this:

private lazy var configuration: SPTConfiguration = {
  let configuration = SPTConfiguration(clientID: SpotifyClientID, redirectURL: SpotifyRedirectURI)
  configuration.playURI = ""
  configuration.tokenSwapURL = URL(string: "swapurl")
  configuration.tokenRefreshURL = URL(string: "refreshurl")
  return configuration
}()

If you follow the instructions here, you can easily set up a Heroku instance to provide the swap and refresh functionality for you, although it's not recommended to use it in production. Then you would simply replace "swap url" and "token url" with the url's from the Heroku instance.

katehuds commented 4 years ago

@jonahpelfrey I keep seeing so many places in the Spotify documentation that say the token exchange processes are "not recommended to use in production". Does there exist an example or suggested way to actually do this in production?

jonahpelfrey commented 4 years ago

@katehuds I think they are making a recommendation against using their example token swap because in a production environment, it should be a part of the application backend.

In terms of building out an authorization flow, Spotify also outlines this here. They outline Authorization Code, Implicit Grant, and Client Credentials Flow (Three different authorization patterns).

There are other resources on authorization, but this should give you a good idea on how to structure an authorization system to use with Spotify. Does that answer your question?

katehuds commented 4 years ago

@jonahpelfrey I'm very new to app development, so I'm sorry if these questions sound naive.

When you say "part of the application backend", would this be using something like Firebase, through the authentication feature? The practice app I'm working on only needs to keep track of a pretty small amount of data, so I've just been saving it in the UserDefaults. I guess if the amount of data that needs to be kept is bigger, then it would require a database and the user to create a login, in order to keep it all.

I've been using the SPTLoginSampleAppSwift example provided by Spotify which utilizes the authorization Code flow, but just with the local host server running. I didn't realize I couldn't just host a server (like on Heroku) and continue to use this implementation of the authorization code flow.

katehuds commented 4 years ago

@jonahpelfrey Sorry to bother you, I just want to make sure I'm on the right path with this.

Thanks in advance!

jonahpelfrey commented 4 years ago

@katehuds No worries. Yes when I say application backend it could be something like firebase.

To be more clear on the phrase "not recommended to use in production" -- If you are building a sample app (which it sounds like you are) don't worry about this comment. Use the Heroku deployment option / run it locally.

If you hope to publish this app, you might want to revisit this discussion. Firebase is a good option for storing / authenticating users, but not necessary for a practice project.

katehuds commented 4 years ago

@jonahpelfrey Thanks for the response! I've been running it locally since I started working on the app. I am definitely interested in publishing it at some point, so I'm trying to make sure I understand what is needed prior to doing that.

jonahpelfrey commented 4 years ago

The process for Authorization Code Flow (Controlling the flow of authorization instead of implicitly granting authorization) is outlined in a README here:

https://github.com/bih/spotify-token-swap-service/blob/master/README.md#authorization-code-flow

If you wanted to replace the above heroku example with your own API, it would just need to provide the outlined functionality. Then your API would allow you to control if and when new tokens should be requested, with the client facing app having only to communicate with your API to request the current token.

downdrown commented 2 years ago

@jonahpelfrey I'm a bit late to the party, but I am struggling with similar issues. I managed to create my exchange backend for token swap and refresh and also the initial authorization in my SwiftUI app works well. However I am unsure whether I need to manually fetch a new token from the exchange service or the SDK does the work for me automatically. I was a bit confused because you can actually set the refresh url for the SDK but whenever I try to reconnect after I disconnected from the remote playing api I get errors. Not sure if I understood correctly how it should work ...

griffinbaker12 commented 1 year ago

Yeah I am similarly confused on this point...the token swap endpoint also does not work for me and throws "invalid_client" every time even though it works for routes like refresh.

jonahpelfrey commented 1 year ago

@downdrown Now I am the one who is late to the party! Sorry for not getting back to you. Hopefully this can still be helpful for you or someone else.

The SPTSessionManager class has a function called renewSession(). In my side project from a few years back, I was calling that manually to refresh. I'm assuming that the SDK is having you provide the refresh URL up front so that the call to renew the session doesn't require any parameters. I did something along the lines of this:

lazy var configuration: SPTConfiguration = {
  let configuration = SPTConfiguration(clientID: SpotifyClientID, redirectURL: SpotifyRedirectURI)
  configuration.playURI = ""
  configuration.tokenSwapURL = URL(string: "swapurl")
  configuration.tokenRefreshURL = URL(string: "refreshurl")
  return configuration
}()

lazy var sessionManager: SPTSessionManager = {
    let manager = SPTSessionManager(configuration: configuration, delegate: self)
    return manager
}()

...

func start() {
    sessionManager.initiateSession()
}

...

extension AppDelegate: SPTSessionManagerDelegate {
    func sessionManager(manager: SPTSessionManager, didInitiate session: SPTSession) {
        if session.isExpired() {
            sessionManager.renewSession()
        } else {
            // Store session and credentials
        }
    }
}

Helpful links:

Authentication: https://developer.spotify.com/documentation/ios/tutorials/advanced-auth

Session Manager: https://spotify.github.io/ios-sdk/html/Classes/SPTSessionManager.html

jonahpelfrey commented 1 year ago

@griffinbaker12 Are you using the one-click-deploy heroku instance that Spotify provides? Based on your error it would seem that you are (potentially) missing some configuration for that environment. The doc for that can be found here

I'm not sure what you mean by "even though it works for routes like refresh". Could you clarify for me?

ollyde commented 1 year ago

Be-aware people because of the rate limits on this service you can only ever use Spotify as an MVP utility. We found out the hard way.

griffinbaker12 commented 1 year ago

Finally got this to work! Thank you for the reply! > me?

griffinbaker12 commented 1 year ago

@ollyde At what point did you start to run into issues? > Be-aware people because of the rate limits on this service you can only ever use Spotify as an MVP utility. We found out the hard way.

griffinbaker12 commented 1 year ago

Pre-receiving a quota extension, does their rate limit policy under "User Management" mean that only 25 unique users can be issued an access token?

ollyde commented 1 year ago

@griffinbaker12 there are multiple rate limits, when they noticed you are reaching them aka, you have proved an MVP they will stop the service and look into it themselfs; kind of scummy; don't use this service.

griffinbaker12 commented 1 year ago

@ollyde do you have any recommendations as to what to use instead? My plan was to apply for increased API rate limits (which I did 3 weeks ago) and use this package to interact with their APIs. What other options are there?

ollyde commented 1 year ago

@griffinbaker12 there's a few services that gives paid access to music APIs. I can't remember what we used for this project, was a while ago.