I’m building a web app that needs to connect with Spotify’s API. Users need to log into their Spotify accounts for my app to work properly.
The login flow works fine until the callback part. Users can click my “Connect with Spotify” button and see Spotify’s permission page. But when they approve access, I get a 403 error saying access is denied.
I think the problem is in my callback handler method handleSpotifyCallback. Maybe the tokens aren’t being set correctly after the user approves the connection.
Here’s my authentication controller:
import java.io.IOException;
import java.net.URI;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import jakarta.servlet.http.HttpServletResponse;
import se.michaelthelin.spotify.SpotifyApi;
import se.michaelthelin.spotify.SpotifyHttpManager;
import se.michaelthelin.spotify.exceptions.SpotifyWebApiException;
import se.michaelthelin.spotify.model_objects.credentials.AuthorizationCodeCredentials;
import se.michaelthelin.spotify.requests.authorization.authorization_code.AuthorizationCodeRequest;
import se.michaelthelin.spotify.requests.authorization.authorization_code.AuthorizationCodeUriRequest;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.view.RedirectView;
@RestController
@RequestMapping("/auth")
public class SpotifyAuthController {
private static final URI callbackUri = SpotifyHttpManager.makeUri("http://localhost:8080/auth/callback");
private String authCode = "";
private String userRefreshToken = "";
private static final SpotifyApi spotifyClient = new SpotifyApi.Builder()
.setClientId("abc123def456ghi789")
.setClientSecret("xyz987uvw654rst321")
.setRedirectUri(callbackUri)
.build();
@GetMapping("connect")
@ResponseBody
public RedirectView initiateSpotifyAuth() {
AuthorizationCodeUriRequest authUriRequest = spotifyClient.authorizationCodeUri()
.scope("playlist-modify-public, user-read-private, user-read-email, user-top-read")
.show_dialog(true)
.build();
final URI authUri = authUriRequest.execute();
RedirectView redirect = new RedirectView();
redirect.setUrl(authUri.toString());
return redirect;
}
@GetMapping(value = "callback")
public String handleSpotifyCallback(@RequestParam("code") String authorizationCode, HttpServletResponse response) throws IOException {
System.out.println("Got authorization code: " + authorizationCode);
if (authorizationCode == null || authorizationCode.isEmpty()) {
return "Missing authorization code.";
}
AuthorizationCodeRequest tokenRequest = spotifyClient.authorizationCode(authorizationCode).build();
try {
final AuthorizationCodeCredentials credentials = tokenRequest.execute();
spotifyClient.setAccessToken(credentials.getAccessToken());
spotifyClient.setRefreshToken(credentials.getRefreshToken());
userRefreshToken = credentials.getRefreshToken();
System.out.println("Got Access Token: " + credentials.getAccessToken());
System.out.println("Got Refresh Token: " + credentials.getRefreshToken());
System.out.println("Token expires in: " + credentials.getExpiresIn());
} catch (IOException | SpotifyWebApiException | org.apache.hc.core5.http.ParseException e) {
System.out.println("Token exchange failed: " + e.getMessage());
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Token exchange failed.");
return "Token exchange failed.";
}
response.sendRedirect("http://localhost:8080/dashboard");
return spotifyClient.getAccessToken();
}
}
What could be causing the 403 error after successful authentication?