I’m doing an application and I’m using “NestJS” for the back.
In my application, I have a button that allows the user to connect his Spotify account (using passport).
For the moment, when the user clicks on the button, I get the access token but I can’t stock it for now.
My problem is that I have no idea of how to tell my back which user clicked on the button, and how to stock the user id somewhere until I have the token. Here is my code :
In my front, I just have a button that redirects to my back :
const handleSpotifyButton = () => {
window.location.href = "http://localhost:8080/auth/spotify";
};
I guess that I can pass an extra parameter like this :
window.location.href = "http://localhost:8080/auth/spotify?userId=${userId}";
But then, I don’t know how to use it in my back. Here is my controller :
import { SpotifyAuthGuard } from "./spotify-auth.guard";
import { Controller, Get, Request, UseGuards } from "@nestjs/common";
import { SpotifyService } from "./spotify-auth.service";
import { Redirect } from "@nestjs/common";
@Controller("auth")
export class SpotifyController {
constructor(private spotifyService: SpotifyService) {}
@Get("spotify")
@UseGuards(SpotifyAuthGuard)
async spotifyAuth() {}
@Get("spotify-redirect")
@Redirect("http://localhost:8081")
@UseGuards(SpotifyAuthGuard)
spotifyAuthRedirect(@Request() req) {
this.spotifyService.spotifyLogin(req);
}
}
Here I could get the parameter in the route “spotify”, but then I don’t really know how it works to open the spotify authorization window.
The ideal would be to get it in my service, where I print the token, so I could just add it in my database from here :
import { Injectable } from "@nestjs/common";
@Injectable()
export class SpotifyService {
async spotifyLogin(req): Promise<string> {
if (!req.user) {
return "No user from spotify";
}
const spotifyUser = req.user;
console.log(spotifyUser.accessToken);
return spotifyUser;
}
}
Here is my guard :
import { Injectable } from "@nestjs/common";
import { ConfigService } from "@nestjs/config";
import { AuthGuard } from "@nestjs/passport";
@Injectable()
export class SpotifyAuthGuard extends AuthGuard("spotify") {
constructor(private configService: ConfigService) {
super({
accessType: "offline",
});
}
}
My module :
import { SpotifyAuthStrategy } from "./spotify-auth.strategy";
import { Module } from "@nestjs/common";
import { SpotifyController } from "./spotify-auth.controller";
import { SpotifyService } from "./spotify-auth.service";
import { ConfigModule } from "@nestjs/config";
@Module({
imports: [ConfigModule.forRoot()],
controllers: [SpotifyController],
providers: [SpotifyService, SpotifyAuthStrategy],
})
export class SpotifyAuthModule {}
And my strategy :
import { PassportStrategy } from "@nestjs/passport";
import { Strategy, VerifyCallback, Profile } from "passport-spotify";
import { Injectable } from "@nestjs/common";
@Injectable()
export class SpotifyAuthStrategy extends PassportStrategy(Strategy, "spotify") {
constructor() {
super({
clientID: "myClientId",
clientSecret: "myClientSecret",
callbackURL: "http://localhost:8080/auth/spotify-redirect",
scope: ["user-library-read", "user-library-modify"],
});
}
async validate(
accessToken: string,
refreshToken: string,
profile: Profile,
done: VerifyCallback,
): Promise<any> {
try {
const { id, displayName, emails } = profile;
const user = {
id,
displayName,
email: emails ? emails[0].value : null,
accessToken,
refreshToken,
};
done(null, user);
} catch (error) {
done(error, null);
}
}
}
Ask me if you need more informations about my code
Thanks