Peter-Schorn / SpotifyAPI

A Swift library for the Spotify web API. Supports all endpoints.
https://peter-schorn.github.io/SpotifyAPI/documentation/spotifywebapi
MIT License
259 stars 32 forks source link

Setting up SpotifyAPI and Spotify SDK in the same app #8

Closed zdurlan closed 3 years ago

zdurlan commented 3 years ago

Hello!

I was wondering if there is a way to use the access token that we got from logging in via Spotify SDK (using session manager) in order to set it to the SpotifyAPI so we can use both of them inside one app, without asking for permissions twice?

In my particular case we need both of them as we need both the track events that we get from the app remote delegate, and the web api functions like search.

Is there a way to use them both or is it better to just create the search api locally?

Peter-Schorn commented 3 years ago

I was wondering if there is a way to use the access token that we got from logging in via Spotify SDK (using session manager) in order to set it to the SpotifyAPI

Yes, this is possible.

both AuthorizationCodeFlowManager (docs) and AuthorizationCodeFlowPKCEManager (docs) have the following initializers for exactly this purpose:

public convenience init(
    clientId: String,
    clientSecret: String,
    accessToken: String,
    expirationDate: Date,
    refreshToken: String?,
    scopes: Set<Scope>,
    networkAdaptor: (
        (URLRequest) -> AnyPublisher<(data: Data, response: HTTPURLResponse), Error>
    )? = nil
)

You can pass the access token retrieved from the Spotify SDK into these initializers. You'll have to leave refreshToken as nil because the SDK doesn't seem to provide that (I may be wrong). You should set the expiration date to an hour after the access token was received. Make sure the scopes match what you requested during the authorization process. If you get a "Permissions Missing" error when making a request to an endpoint, then that means you're missing the required scope(s).

The downside of this strategy, however, is that my library cannot automatically refresh the access token after it expires (it expires after an hour), because that requires a refresh token.

Here's an alternative strategy:

Authorize your app using the Spotify web API through my library, and include the appRemoteControl scope. Then, after the authorization process completes, assign the access token you received to the app remote/session manager.

Peter-Schorn commented 3 years ago

Each time you need to get a new access token from the SDK, you'll need to create a new authorization manager (because you cannot mutate the access token) and assign it to SpotifyAPI.authorizationManager, which is a mutable property.

zdurlan commented 3 years ago

Thanks a lot! This helps a ton.

You are correct in saying that the sdk does not provide a way to refresh the tokens, so I think the other way (logging via your library and assigning the token to the app remote) is the winner here. I just don't know how that will affect the app remote, I would think that it must be reconnected with the new token. I'll have to test it out.

Thanks again!

Peter-Schorn commented 3 years ago

Yes, I think the second method is better, based on my limited experience with the SDK. In order to keep the access token for the app remote up to date after my library automatically refreshes it, you need to subscribe to SpotifyAPI. authorizationManagerDidChange and reassign the access token from SpotifyAPI.authorizationManager to the app remote each time this publisher emits. See this article: Saving authorization information to persistent storage.

You might also want to take a look at the "SpotifySDK" branch of my example app. It's not very polished and may not represent the best practices, but it may be helpful nonetheless. In particular, look at the Spotify class.

Peter-Schorn commented 3 years ago

I'm closing this for now. I can reopen it if you have any other questions. I'm always available for help.