Announcements

Help Wizard

Step 1

NEXT STEP

FAQs

Please see below the most popular frequently asked questions.

Loading article...

Loading faqs...

VIEW ALL

Ongoing Issues

Please see below the current ongoing issues which are under investigation.

Loading issue...

Loading ongoing issues...

VIEW ALL

clerk authentication with spotify

Solved!

clerk authentication with spotify

So, I am making an NLP application where the emotions generated after processing some text are mapped to a genre and then used for searching songs related to that genre on spotify and creating a playlist for the user.

However, the issue is i am not able to understand how to go with the authentication flow when i am using clerk to authenticate my user. How will I generate access tokens? If anyone has any experience regarding this, kindly help! thankyou

Reply

Accepted Solutions
Marked as solution

Hey sejalapeno,

 

I can happily tell you I got basic functionality working.
Here is working code of how to display user information from Spotify:

 

// app/page.tsx
import SpotifyProfile from "./components/SpotifyProfile";

export default function HomePage() {
  return (
    <main>
      <h1>Welcome to Your Spotify Profile</h1>
      <SpotifyProfile />
    </main>
  );
}

 

 

 

// app/layout.tsx
import "./globals.css";
import type { Metadata } from "next";
import { ClerkProvider, SignInButton, UserButton } from "@clerk/nextjs";

export const metadata: Metadata = {
  title: "Spotify Profile",
  description: "View your Spotify profile",
};

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <body>
        <ClerkProvider>
          <div className="app-container">
            <header>
              <nav>
                {/* Clerk UI components for authentication */}
                <SignInButton />
                <UserButton afterSignOutUrl="/" />
              </nav>
            </header>
            <main>{children}</main>
          </div>
        </ClerkProvider>
      </body>
    </html>
  );
}

 

 

 

// app/components/SpotifyProfile.tsx
"use client";

import { useEffect, useState } from "react";
import { useAuth } from "@clerk/nextjs";

const SpotifyProfile = () => {
  const { isSignedIn } = useAuth(); // Clerk hook to check authentication state
  const [profile, setProfile] = useState<any>(null);
  const [error, setError] = useState<string | null>(null);

  useEffect(() => {
    const fetchSpotifyProfile = async () => {
      try {
        const response = await fetch("/api/spotify");
        const data = await response.json();

        if (response.ok) {
          setProfile(data.message);
        } else {
          setError(data.message || "Failed to fetch Spotify profile");
        }
      } catch (err) {
        setError("An error occurred while fetching Spotify profile");
      }
    };

    if (isSignedIn) {
      fetchSpotifyProfile();
    }
  }, [isSignedIn]); // Ensure this effect only runs if the user is signed in

  if (!isSignedIn) {
    return <div>Please sign in to view your Spotify profile.</div>;
  }

  if (error) {
    return <div>Error: {error}</div>;
  }

  if (!profile) {
    return <div>Loading...</div>;
  }

  return (
    <div>
      <h1>Spotify Profile</h1>
      <p>Name: {profile.display_name}</p>
      <p>Email: {profile.email}</p>
      {profile.images && profile.images.length > 0 && (
        <img src={profile.images[0]?.url} alt="Profile" width={100} />
      )}
    </div>
  );
};

export default SpotifyProfile;

 

 

 

// app/api/spotify/route.ts
import { auth, clerkClient } from "@clerk/nextjs/server";
import { NextResponse } from "next/server";

export async function GET() {
  // Get the current user ID using Clerk's auth object
  const { userId } = auth();

  // Check if the user is authenticated
  if (!userId) {
    return NextResponse.json({ message: "User not found" }, { status: 401 });
  }

  try {
    // Use the correct provider ID
    const provider = "spotify"; // Make sure this matches your Clerk configuration

    // Call the Clerk API to get the user's OAuth access tokens
    const clerkResponse = await clerkClient().users.getUserOauthAccessToken(
      userId,
      provider
    );

    // Log the Clerk response to debug
    console.log("Clerk Response:", clerkResponse);

    // Extract token from the response
    const accessToken = clerkResponse.data[0]?.token; // Use .data as shown in the logs

    // Check if the accessToken is undefined
    if (!accessToken) {
      return NextResponse.json(
        { message: "Access token is undefined" },
        { status: 500 }
      );
    }

    // Fetch the user data from the Spotify API
    const spotifyUrl = "https://api.spotify.com/v1/me";

    // Call the Spotify API with the access token
    const spotifyResponse = await fetch(spotifyUrl, {
      headers: {
        Authorization: `Bearer ${accessToken}`,
        "Content-Type": "application/json",
      },
    });

    // Log the Spotify response status to debug
    console.log("Spotify Response Status:", spotifyResponse.status);

    // Handle the response from the Spotify API
    if (!spotifyResponse.ok) {
      const errorData = await spotifyResponse.json();
      console.error("Spotify API Error:", errorData);
      return NextResponse.json(
        { message: "Failed to fetch Spotify data", error: errorData },
        { status: spotifyResponse.status }
      );
    }

    const spotifyData = await spotifyResponse.json();

    // Log the Spotify data to debug
    console.log("Spotify Data:", spotifyData);

    // Return the Spotify data in the response
    return NextResponse.json({ message: spotifyData });
  } catch (error) {
    // Catch and handle any errors during the API request
    console.error("Error fetching Spotify data:", error);
    return NextResponse.json(
      { message: "Internal Server Error", error: error.message },
      { status: 500 }
    );
  }
}

 

 

I hope this code helps you on how to get an access token from Clerk.

Page used as reference: Social connections (OAuth)
Scopes used: user-read-email, user-read-private

P.S. I could have rewritten this code using Clerk's build in hide and show elements when (not) signed in. This was only the quickest way for now.

XimzendSpotify Star
Help others find this answer and click "Accept as Solution".
If you appreciate my answer, maybe give me a Like.
Note: I'm not a Spotify employee.

View solution in original post

9 Replies

Hi sejalapeno, Welcome to the Community!

 

I had to look it up, and I found this page.

The next steps are too complicated to describe here, so I refer you to the Spotify documentation page here.

You already have done the Request User Authorization step with Clerk, so you should look at it's respons, and how to use it with request an access token.

 

Let me know if this helps, and if you have other questions.

XimzendSpotify Star
Help others find this answer and click "Accept as Solution".
If you appreciate my answer, maybe give me a Like.
Note: I'm not a Spotify employee.

hello, I am not able to fetch access token. Not sure if clerk authentication gets an access token from spotify. 

Hey sejalapeno,

 

Could you please send code or a picture of what you already have so I can look into it?

XimzendSpotify Star
Help others find this answer and click "Accept as Solution".
If you appreciate my answer, maybe give me a Like.
Note: I'm not a Spotify employee.

I am working on next.js project

sejalapeno_0-1722793578640.png

 

sejalapeno_1-1722793626639.png

this is the basic implementation which i have done following the clerk documentation. This allows the user to sign up or sign in to my application with spotify.
Then, I tried to implement the following code snippet where I thought clerk can provide me the access_token which it might have stored when the user signed in, but I am getting errors.

 

 

// pages/api/get-spotify-token.ts
import { auth, clerkClient } from "@clerk/nextjs/server";
import { NextResponse } from "next/server";

export async function GET() {
  const { userId } = auth();

  if (!userId) {
    return new NextResponse("Unauthorized", { status: 401 });
  }

  try {
    const oauthTokens = await clerkClient.users.getUserOauthAccessToken(userId, "oauth_spotify");

    // Log the response structure
    console.log("OAuth Tokens:", oauthTokens);

    if (oauthTokens.length > 0) {
      const token = oauthTokens[0]; // Adjust based on the actual structure
      return NextResponse.json({ accessToken: token });
    } else {
      return new NextResponse("No tokens found", { status: 404 });
    }
  } catch (err) {
    console.error("Error:", err);
    return new NextResponse("Failed to retrieve access token", { status: 500 });
  }
}

 

 

 

Hey sejalapeno,

 

Today I tried to get it working by watching a 100 second tutorial, but the Chrome Console shows that the code is not send to localhost:3000

I have tried it another way, but VSCode is not user friendly with making files and folders. So I will try this again from scratch later.

 

I'll keep you posted.

XimzendSpotify Star
Help others find this answer and click "Accept as Solution".
If you appreciate my answer, maybe give me a Like.
Note: I'm not a Spotify employee.

Hello, thankyou so much for following up with this!
how did you get it working? are you getting access_token from the auth() object in clerk?

Marked as solution

Hey sejalapeno,

 

I can happily tell you I got basic functionality working.
Here is working code of how to display user information from Spotify:

 

// app/page.tsx
import SpotifyProfile from "./components/SpotifyProfile";

export default function HomePage() {
  return (
    <main>
      <h1>Welcome to Your Spotify Profile</h1>
      <SpotifyProfile />
    </main>
  );
}

 

 

 

// app/layout.tsx
import "./globals.css";
import type { Metadata } from "next";
import { ClerkProvider, SignInButton, UserButton } from "@clerk/nextjs";

export const metadata: Metadata = {
  title: "Spotify Profile",
  description: "View your Spotify profile",
};

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <body>
        <ClerkProvider>
          <div className="app-container">
            <header>
              <nav>
                {/* Clerk UI components for authentication */}
                <SignInButton />
                <UserButton afterSignOutUrl="/" />
              </nav>
            </header>
            <main>{children}</main>
          </div>
        </ClerkProvider>
      </body>
    </html>
  );
}

 

 

 

// app/components/SpotifyProfile.tsx
"use client";

import { useEffect, useState } from "react";
import { useAuth } from "@clerk/nextjs";

const SpotifyProfile = () => {
  const { isSignedIn } = useAuth(); // Clerk hook to check authentication state
  const [profile, setProfile] = useState<any>(null);
  const [error, setError] = useState<string | null>(null);

  useEffect(() => {
    const fetchSpotifyProfile = async () => {
      try {
        const response = await fetch("/api/spotify");
        const data = await response.json();

        if (response.ok) {
          setProfile(data.message);
        } else {
          setError(data.message || "Failed to fetch Spotify profile");
        }
      } catch (err) {
        setError("An error occurred while fetching Spotify profile");
      }
    };

    if (isSignedIn) {
      fetchSpotifyProfile();
    }
  }, [isSignedIn]); // Ensure this effect only runs if the user is signed in

  if (!isSignedIn) {
    return <div>Please sign in to view your Spotify profile.</div>;
  }

  if (error) {
    return <div>Error: {error}</div>;
  }

  if (!profile) {
    return <div>Loading...</div>;
  }

  return (
    <div>
      <h1>Spotify Profile</h1>
      <p>Name: {profile.display_name}</p>
      <p>Email: {profile.email}</p>
      {profile.images && profile.images.length > 0 && (
        <img src={profile.images[0]?.url} alt="Profile" width={100} />
      )}
    </div>
  );
};

export default SpotifyProfile;

 

 

 

// app/api/spotify/route.ts
import { auth, clerkClient } from "@clerk/nextjs/server";
import { NextResponse } from "next/server";

export async function GET() {
  // Get the current user ID using Clerk's auth object
  const { userId } = auth();

  // Check if the user is authenticated
  if (!userId) {
    return NextResponse.json({ message: "User not found" }, { status: 401 });
  }

  try {
    // Use the correct provider ID
    const provider = "spotify"; // Make sure this matches your Clerk configuration

    // Call the Clerk API to get the user's OAuth access tokens
    const clerkResponse = await clerkClient().users.getUserOauthAccessToken(
      userId,
      provider
    );

    // Log the Clerk response to debug
    console.log("Clerk Response:", clerkResponse);

    // Extract token from the response
    const accessToken = clerkResponse.data[0]?.token; // Use .data as shown in the logs

    // Check if the accessToken is undefined
    if (!accessToken) {
      return NextResponse.json(
        { message: "Access token is undefined" },
        { status: 500 }
      );
    }

    // Fetch the user data from the Spotify API
    const spotifyUrl = "https://api.spotify.com/v1/me";

    // Call the Spotify API with the access token
    const spotifyResponse = await fetch(spotifyUrl, {
      headers: {
        Authorization: `Bearer ${accessToken}`,
        "Content-Type": "application/json",
      },
    });

    // Log the Spotify response status to debug
    console.log("Spotify Response Status:", spotifyResponse.status);

    // Handle the response from the Spotify API
    if (!spotifyResponse.ok) {
      const errorData = await spotifyResponse.json();
      console.error("Spotify API Error:", errorData);
      return NextResponse.json(
        { message: "Failed to fetch Spotify data", error: errorData },
        { status: spotifyResponse.status }
      );
    }

    const spotifyData = await spotifyResponse.json();

    // Log the Spotify data to debug
    console.log("Spotify Data:", spotifyData);

    // Return the Spotify data in the response
    return NextResponse.json({ message: spotifyData });
  } catch (error) {
    // Catch and handle any errors during the API request
    console.error("Error fetching Spotify data:", error);
    return NextResponse.json(
      { message: "Internal Server Error", error: error.message },
      { status: 500 }
    );
  }
}

 

 

I hope this code helps you on how to get an access token from Clerk.

Page used as reference: Social connections (OAuth)
Scopes used: user-read-email, user-read-private

P.S. I could have rewritten this code using Clerk's build in hide and show elements when (not) signed in. This was only the quickest way for now.

XimzendSpotify Star
Help others find this answer and click "Accept as Solution".
If you appreciate my answer, maybe give me a Like.
Note: I'm not a Spotify employee.

Hey!!! So sorry for such a late reply. I am very thankful for you followed up throughout. This code is working! and my app works as well!
I had switched to nextjs auth but then saw this and went back again to clerk. Thankyou so much! I should have read the documentation more carefully ๐Ÿ˜›
Marking this as solved!

 

No worries. I also found that documentation page late in the process. Therefore my reply was also delayed.

XimzendSpotify Star
Help others find this answer and click "Accept as Solution".
If you appreciate my answer, maybe give me a Like.
Note: I'm not a Spotify employee.

Suggested posts

Type a product name