spotify-dart icon indicating copy to clipboard operation
spotify-dart copied to clipboard

Support of Authorization Code Flow with Proof Key for Code Exchange (PKCE)

Open nkovshov opened this issue 3 years ago • 5 comments

It's not documented, but passing null for clientSecret:

final credentials = SpotifyApiCredentials(clientId, null);

forces oauth2 lib to generate challenge and follow PKCE auth flow (https://developer.spotify.com/documentation/general/guides/authorization-guide/#authorization-code-flow-with-proof-key-for-code-exchange-pkce) and it worked out of the box for me.

It may be worth to document it.

nkovshov avatar Oct 30 '20 14:10 nkovshov

It seems like PKCE works fine when passing null for clientSecret when using the 'Authorization Code Flow': final credentials = SpotifyApiCredentials(clientId, null); spotify = SpotifyApi.fromAuthCodeGrant(grant, responseUri); But it doesn't work when later using the 'Saved Credentials Flow': spotify = SpotifyApi(spotifyCredentials);

It seems like PKCE works only with the SpotifyApi.fromAuthCodeGrant(grant, responseUri) constructor and not with the SpotifyApi(spotifyCredentials) default constructor.

Is there any way to use PKCE with the 'Saved Credentials Flow'?

Ruud14 avatar Dec 18 '21 19:12 Ruud14

Okay I managed to find a sloppy workaround:

I manually created an oauth2 client based on the saved credentials ('creds' here):

import 'package:oauth2/src/client.dart';
import 'package:oauth2/src/credentials.dart';

Credentials credentials = Credentials(creds.accessToken!,
          refreshToken: creds.refreshToken,
          idToken: creds.clientId,
          tokenEndpoint: creds.tokenEndpoint,
          scopes: creds.scopes,
          expiration: creds.expiration);
     
Client client = Client(credentials,
          identifier: clientId,
          secret: null,
          basicAuth: true,
          httpClient: http.Client(),
          onCredentialsRefreshed: _onCredentialsRefreshed);

And then create a SpotifyApi instance with the .fromClient constructor.

spotify = SpotifyApi.fromClient(client);

However there are multiple things wrong with this, one of which being that a direct import from another package is required.

For now this works, but I'd like to see a better solution.

Ruud14 avatar Dec 20 '21 12:12 Ruud14

Will this be added?

esskar avatar Aug 08 '22 20:08 esskar

Thanks for this! Getting the token and creating the client works fine using the hack from @Ruud14. But how do you manually refresh the token now that it's going outside the spotify-dart library?

adamkoch avatar Dec 01 '23 06:12 adamkoch

@rinukkusu should we add a "help wanted" label for this issue?

hayribakici avatar Dec 01 '23 11:12 hayribakici