Spring Boot Java OAuth2 integration with Spotify API authentication flow

I’m working on a Spring Boot app that needs to connect with Spotify’s web API. The user has to log into their Spotify account first through OAuth2.

I can get users to the login screen fine, but once they approve access, I’m hitting a 403 error saying I don’t have permission to view the page. My app has a homepage with a “Connect to Spotify” button that takes them to auth, then should redirect to another page after success. Instead I get the authorization error.

I think the issue is in my handleSpotifyCallback method. After the user approves on Spotify’s page, the redirect fails with unauthorized error. Maybe my token handling is wrong and the access token isn’t being set properly. 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("13e244917ca64efb96556f753fcd032b")
        .setClientSecret("ded93049447347769bcea9b2327c7ba6")
        .setRedirectUri(callbackUri)
        .build();

    @GetMapping("authorize")
    @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 in callback.";
        }
    
        AuthorizationCodeRequest tokenRequest = spotifyClient.authorizationCode(authorizationCode).build();
    
        try {
            final AuthorizationCodeCredentials tokenCredentials = tokenRequest.execute();
    
            spotifyClient.setAccessToken(tokenCredentials.getAccessToken());
            spotifyClient.setRefreshToken(tokenCredentials.getRefreshToken());
            userRefreshToken = tokenCredentials.getRefreshToken();
    
            System.out.println("Got Access Token: " + tokenCredentials.getAccessToken());
            System.out.println("Got Refresh Token: " + tokenCredentials.getRefreshToken());
            System.out.println("Token expires in: " + tokenCredentials.getExpiresIn());
    
        } catch (IOException | SpotifyWebApiException | org.apache.hc.core5.http.ParseException ex) {
            System.out.println("Token exchange failed: " + ex.getMessage());
            response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Token exchange failed.");
            return "Token exchange failed.";
        }
    
        response.sendRedirect("http://localhost:8080/dashboard");
        return spotifyClient.getAccessToken();
    }
    
}

Had the same issue building my Spotify integration last year. Your /dashboard endpoint probably doesn’t handle authentication properly. When you redirect after getting the token, Spring Security doesn’t know the user’s authenticated because you’re not creating a real session. You’ve got two options: store the access token in the session and configure Spring Security to recognize it, or create a custom authentication provider that validates the Spotify token. I stored mine in HttpSession and made a custom filter to check protected routes. Also check that your dashboard controller isn’t asking for different permissions than what you’re getting from Spotify OAuth. That 403 means your security config is rejecting the request even though Spotify already approved it.

This is probably a Spring Security config issue, not your OAuth flow. Your token exchange looks fine, but Spring Boot’s default security is likely blocking /dashboard even after Spotify auth succeeds. If you’ve got Spring Security on your classpath, it auto-protects all endpoints unless you tell it otherwise. You’ll need to either disable security for that route or set up proper session management. I hit this exact problem and fixed it by adding a SecurityConfig class that allows access to my post-auth endpoints. The Spotify integration works great - Spring just doesn’t trust your custom OAuth flow without the right config.

Your callback method’s doing two things at once - returning the access token AND redirecting. That’s the problem. Drop the return spotifyClient.getAccessToken(); line since you’re already redirecting anyway. Also check that your /dashboard endpoint actually exists and isn’t blocked by Spring Security. That 403 screams authentication issue - your dashboard probably expects auth but doesn’t know about the Spotify token you just grabbed.

This topic was automatically closed 4 days after the last reply. New replies are no longer allowed.