In angular, Spotify get token API, using the PCKE flow, returns error 404 Collection 'token' not found

80 views Asked by At

This problem has been bugging me a lot. I'm trying to implement the PKCE auth method described here. I have a log in button in the app template file and it is connected to the login function via (click). This function creates a code_verifier saves it in the local storage and redirects the user to the Spotify authorization server login page. After Spotify redirects the user back and appends a code in the query params, I retrieve it in ngOnInit and subscribe to generateToken service. the generateToken then calls an API that should get the token. the problem is this API gives me ERROR 404 not found. Can you help me with this problem?

auth.service.ts Class functions

tokenUrl = 'https://accounts.spotify.com/api/token';

private generateCodeChallenge(codeVerifier: string): Observable<ArrayBuffer> {
    const encoder = new TextEncoder();
    const data = encoder.encode(codeVerifier);
  
    return defer(()=> from(window.crypto.subtle.digest('SHA-256', data)));
}

private redirectToAuthCodeFlow() {
    let codeVerifier = generateRandomString(128);
    
    localStorage.setItem('code_verifier', codeVerifier);

    return this.generateCodeChallenge(codeVerifier)
}

generateCode(): Observable<ArrayBuffer> {
    return this.redirectToAuthCodeFlow();
}

generateToken(code: string) {
    let codeVerifier = localStorage.getItem('code_verifier') as string;
    console.log(codeVerifier);
    const options = {
      headers: new HttpHeaders().append('Content-Type', 'application/x-www-        urlencoded') };
    
    let body = new URLSearchParams({
      grant_type: 'client_credentials',
      code: code,
      redirect_uri: environment.frontUrl,
      client_id: environment.clientId,
      code_verifier: codeVerifier
    });

    return this.http.post(this.tokenUrl, body ,options);
}

app.component.ts

ngOnInit(): void{
    this.route.queryParams.subscribe(params=>{
        const code = params['code']
        this.code = (code)? code: '';
        if (this.code){
        console.log(this.code)
        this.authServces.generateToken(this.code).subscribe(resp=>            
    {console.log(resp)})
        }
    })
}
    
login(): void{
    this.authServces.generateCode().subscribe(digest => {
        function base64encode(str: ArrayBuffer) {
        return btoa(String.fromCharCode(...new Uint8Array(str)))
          .replace(/\+/g, '-')
          .replace(/\//g, '_')
          .replace(/=+$/, '');
        }
        const codeChallenge = base64encode(digest);
        let scope = 'user-read-private user-read-email';
        
        let args = new URLSearchParams({
        response_type: 'code',
        client_id: environment.clientId,
        scope: scope,
        redirect_uri: environment.frontUrl,
        code_challenge_method: 'S256',
        code_challenge: codeChallenge
        });
    
        document.location = 'https://accounts.spotify.com/authorize?' + args;
    });
}

I tried to use postman to test what I'm doing. I entered the exact same data and it returned ERROR 400 Your client has issued a malformed or illegal request.

0

There are 0 answers