authenticate method
Implementation
Future<void> authenticate(String clientId, String redirectUri, [List<String>? scopes]) async {
if (await tryRestoreToken()) return;
final codeVerifier = _generateCodeVerifier();
final codeChallenge = _codeChallenge(codeVerifier);
final authUri = Uri.https('accounts.spotify.com', '/authorize', {
'client_id': clientId,
'response_type': 'code',
'redirect_uri': redirectUri,
'code_challenge_method': 'S256',
'code_challenge': codeChallenge,
'scope': scopes?.join(' '),
});
final completer = Completer<String>();
_sub = uriLinkStream.listen((Uri? uri) {
if (uri != null && uri.toString().startsWith(redirectUri)) {
final code = uri.queryParameters['code'];
code != null
? completer.complete(code)
: completer.completeError('Authorization code missing');
_sub?.cancel();
}
});
if (!await launchUrl(authUri, mode: LaunchMode.externalApplication)) {
_sub?.cancel();
throw Exception("Coould not open authorization URL");
}
final code = await completer.future;
final response = await http.post(
Uri.parse('https://accounts.spotify.com/api/token'),
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
body: {
'client_id': clientId,
'grant_type': 'authorization_code',
'code': code,
'redirect_uri': redirectUri,
'code_verifier': codeVerifier,
},
);
if (response.statusCode != 200) {
throw Exception("Token exchange failed: ${response.body}");
}
final jsonBody = jsonDecode(response.body);
jsonBody['client_id'] = clientId;
await _saveTokenData(jsonBody);
_accessToken = jsonBody['access_token'];
}