In this article, we'll walk you through authenticating a user with their Spotify account in Next.js 14. This method is compatible with Next.js 13 as well, so you're covered! π
We'll be using the Spotify Provider along with NextAuth, a powerful authentication library for Next.js applications. No worries if you're new to this; I'll guide you through each step! π
Setting Up Next.js
First, let's create a new Next.js 14 project. Open your terminal and run the following command in the directory where you want to create your project:
npx create-next-app@latest
Follow the prompts to name your app. For this example, I'll be using TypeScript, but feel free to stick with JavaScript if you prefer.
Next, ensure all packages are installed by running:
npm install
Installing NextAuth
Next, we need to install the NextAuth dependencies. NextAuth is an open-source authentication library for Next.js applications that makes it easy to add authentication to your project.
Run the following command to install NextAuth:
npm install next-auth
Running the Local Instance
To see your project live and start editing it, use this command:
npm run dev
This will likely load your application at http://localhost:3000 in your browser.
Spotify API credentials
To integrate Spotify authentication, you'll need to obtain API credentials from Spotify. Follow these steps to set it up:
Accessing Spotify for Developers
Go to the Spotify for Developers page here: https://developer.spotify.com/
Log in with your Spotify account.
Navigate to the Spotify Developer Dashboard here: https://developer.spotify.com/dashboard
Creating a New App
Click on "Create App" and fill out the form that appears.
This form requires details about your app, such as its name and description. Creating an app in the Spotify Developer Dashboard allows you to obtain the necessary credentials to interact with the Spotify API.
Providing Redirect URIs
In the form, you'll need to specify the redirect URI for your application in the "Website" field. This is where Spotify will send the user after authentication. For local development, use the following URL:
http://localhost:3000/api/auth/callback/spotify
When you deploy your app, remember to update this URL and URIs using your production URL.
Selecting Web API
Indicate that your app will be using the "Web API" by selecting this option in the form.
Click "Save" to create your app.
Retrieving Spotify Credentials
After creating your app, Spotify will provide you with essential credentials: the Client ID
and Client Secret
. These credentials are crucial for interacting with the Spotify API. Take them from here:
Setting Up Environment Variables
Go back to your Next.js project and create a .env.local
file in the root directory (not inside the src/ folder). Add your Spotify credentials to this file:
.env.local
SPOTIFY_CLIENT_ID=your_spotify_client_id
SPOTIFY_CLIENT_SECRET=your_spotify_client_secret
VERY IMPORTANT
If you deploy your app, you MUST provide two extra env variables. If you don't provide them, production will throw an error.
NEXTAUTH_URL=url_of_your_app
NEXTAUTH_SECRET=hash_key
You can execute this command on your terminal to generate a
hash_key
openssl rand -base64 32
Here the link to the error in production: https://next-auth.js.org/configuration/options#secret
Setup Authentication with NextAuth
Now, let's configure authentication to seamlessly integrate the Spotify Provider with NextAuth technology, utilizing the Spotify API credentials stored in the .env.local
file.
Creating Authentication Routes
- Inside your project directory (whether it's src/ or not), create the following path
src/app/api/auth/[...nextauth]/
. - Create a file named
route.ts
in this directory.
Configuration in route.ts
In the route.ts
file, set up NextAuth to authenticate users with the SpotifyProvider
. Additionally, include callbacks to retrieve the refresh-token
from the session object for further functionality. Like this:
route.ts
import NextAuth from "next-auth/next";
import { type NextAuthOptions } from "next-auth";
import SpotifyProvider from 'next-auth/providers/spotify';
const options: NextAuthOptions = {
providers: [
SpotifyProvider({
authorization:
'https://accounts.spotify.com/authorize?scope=user-read-email,playlist-read-private,playlist-modify-private,playlist-modify-public',
clientId: process.env.SPOTIFY_CLIENT_ID || '',
clientSecret: process.env.SPOTIFY_CLIENT_SECRET || '',
}),
],
callbacks: {
async jwt({ token, account }) {
if(account){
token.access_token = account.access_token;
}
return token;
},
async session({ session, token }) {
return {
...session,
token
};
},
}
}
const handler = NextAuth(options);
export { handler as GET, handler as POST };
Wrap App in the Session Provider
The next step involves creating a Session Provider Wrapper
to encompass the entire application with the authentication service.
Creating AuthProvider Component
Create a file named AuthProvider.tsx
.
In the AuthProvider.tsx
file, use the provider to create an element that wraps its children. This component will later be added to the layout.tsx
file inside the <body>
tag to encompass the entire application.
AuthProvider.tsx
'use client'
import React from 'react';
import { SessionProvider } from "next-auth/react";
function AuthProvider({ children }: { children: React.ReactNode }) {
return (
<SessionProvider>
{children}
</SessionProvider>
)
}
export default AuthProvider;
Implementation in layout.tsx
In the layout.tsx
file, add the AuthProvider.tsx
component to wrap the application. This approach is necessary for client-side rendering, as the provider should be in the layout.tsx
document, which cannot utilize client-side rendering directly.
layout.tsx
import type { Metadata } from "next";
import { Inter } from "next/font/google";
import "./globals.css";
import AuthProvider from "./AuthProvider";
const inter = Inter({ subsets: ["latin"] });
export const metadata: Metadata = {
title: "Create Next App",
description: "Generated by create next app",
};
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html lang="en">
<body className={inter.className}>
<AuthProvider>
{children}
</AuthProvider>
</body>
</html>
);
}
This setup integrates the authentication service into the application by creating an external component (AuthProvider.tsx
) for client-side rendering and then adding it to the layout.tsx
file.
Create the User Interface
Next, we'll develop the user interface, which could look something like this:
page.tsx
'use client'
import { useSession } from "next-auth/react";
import { signIn, signOut } from "next-auth/react";
export default function Home() {
const { data: session } = useSession();
console.log(session);
if (session) {
return (
<div className='p-6'>
<p className='text-white font-normal text-xl mt-5 mb-2'>Signed In as</p>
<span className='bold-txt'>{session?.user?.name}</span>
<p className='opacity-70 mt-8 mb-5 underline cursor-pointer' onClick={() => signOut()}>Sign Out</p>
</div>
)
} else {
return (
<button onClick={() => signIn()} className='shadow-primary w-56 h-16 rounded-xl bg-white border-0 text-black text-3xl active:scale-[0.99] m-6'>Sign In</button>
)
}
}
In the page.tsx
file, we'll start by extracting the session object using the useSession()
function, which, along with the signIn()
and signOut()
methods, is part of the NextAuth features. The session object provides us with user information from the authentication provider, in this case, Spotify. The signIn()
and signOut()
methods trigger the respective processes. By calling them, the authentication setup we've already configured will be executed.
If you've followed each step provided here, you shouldn't encounter any errors, and your project should successfully authenticate users with their Spotify accounts. π₯³
You can also check out an application that utilizes this exact same technologies Jamming. π
Ande here the Github repository for the code: https://github.com/Matdweb/spotify-api-tutorial/tree/how-to-authenticate-a-spotify-user-in-next.js-14-using-next-auth
NOTE:
If you need a nice interface but have no time. I provide you with this code with a simple but smooth interface:
page.tsx
'use client'
import { useSession } from "next-auth/react";
import Image from "next/image";
import { signIn, signOut } from "next-auth/react";
export default function Home() {
const { data: session } = useSession();
if (session) {
return (
<div className='max-w-[19rem] h-[22rem] rounded-[2rem] border-4 border-solid border-white flex justify-around items-center flex-col flex-nowrap mt-10 ml-10 mb-16'>
<div className='mt-8 w-full flex flex-col flex-nowrap justify-around items-center'>
<Image
src={'https://spotiy-playlist-retriever-experimental.vercel.app/_next/static/media/user_img.6db01878.svg'}
width={160}
height={160}
alt='Defualt user image'
/>
<p className='text-white font-normal text-xl mt-5 mb-2'>Sign In as</p>
<span className='bold-txt'>{session?.user?.name}</span>
</div>
<p className='opacity-70 mt-8 mb-5 underline cursor-pointer' onClick={() => signOut()}>Sign Out</p>
</div>
)
} else {
return (
<div className='max-w-[19rem] h-80 rounded-[2rem] border-4 border-solid border-white flex justify-around items-center flex-col flex-nowrap mt-10 ml-10'>
<Image
src={'https://spotiy-playlist-retriever-experimental.vercel.app/_next/static/media/sad_emoji.41405e6f.svg'}
width={160}
height={150}
alt='sad emoji'
/>
<button onClick={() => signIn()} className='shadow-primary w-56 h-16 rounded-xl bg-white border-0 text-black text-3xl active:scale-[0.99]'>Sign In</button>
</div>
)
}
}
Top comments (0)