OAuth 2.0 Spotify InternalOAuthError

InternalOAuthError: failed to fetch user profile
    at C:UsersPAKSHALDocumentsPakshalProjectsSaarangbackendnode_modulespassport-spotifylibpassport-spotifystrategy.js:151:19
    at passBackControl (C:UsersPAKSHALDocumentsPakshalProjectsSaarangbackendnode_modulespassport-oauth2node_modulesoauthliboauth2.js:132:9)
    at IncomingMessage.<anonymous> (C:UsersPAKSHALDocumentsPakshalProjectsSaarangbackendnode_modulespassport-oauth2node_modulesoauthliboauth2.js:157:7)
    at IncomingMessage.emit (node:events:531:35)
    at endReadableNT (node:internal/streams/readable:1696:12)
    at process.processTicksAndRejections (node:internal/process/task_queues:82:21)

after refreshing page message gets changed:

TokenError: Invalid authorization code
    at OAuth2Strategy.parseErrorResponse (C:UsersPAKSHALDocumentsPakshalProjectsSaarangbackendnode_modulespassport-oauth2libstrategy.js:373:12)
    at OAuth2Strategy._createOAuthError (C:UsersPAKSHALDocumentsPakshalProjectsSaarangbackendnode_modulespassport-oauth2libstrategy.js:420:16)
    at C:UsersPAKSHALDocumentsPakshalProjectsSaarangbackendnode_modulespassport-oauth2libstrategy.js:177:45
    at C:UsersPAKSHALDocumentsPakshalProjectsSaarangbackendnode_modulespassport-spotifylibpassport-spotifystrategy.js:81:20
    at passBackControl (C:UsersPAKSHALDocumentsPakshalProjectsSaarangbackendnode_modulespassport-oauth2node_modulesoauthliboauth2.js:132:9)
    at IncomingMessage.<anonymous> (C:UsersPAKSHALDocumentsPakshalProjectsSaarangbackendnode_modulespassport-oauth2node_modulesoauthliboauth2.js:157:7)
    at IncomingMessage.emit (node:events:531:35)
    at endReadableNT (node:internal/streams/readable:1696:12)
    at process.processTicksAndRejections (node:internal/process/task_queues:82:21)
  • This happens for different user’s ,I tried with three users , two of the users get this problem, one user doesnt get this problem.

  • ‘/’ -> Hello World

  • ‘/auth/spotify’ -> ‘auth/spotify/callback’ -> enter credentials

  • ‘/dashboard’ -> Welcome, username!

    instead of above output of recieving username upon logging in with correct credentials i get those two errors listed.
    I am using Oauth 2.0 spotify for logging in my app , i created app in spotify dashboard , took client credentials , secret key and entered correct callback uri, used passport-spotify .
    This is what im doing :

  • Index.js

    const express = require('express');
    const mongoose = require('mongoose');
    const passport = require('passport');
    const session = require('express-session');
    const authRoutes = require('./routes/auth');
    const groupRoutes = require('./routes/grouproutes');
    require('dotenv').config();
    require('./config/passport');  // Initialize passport strategy
    const cors = require('cors');
    
    const app = express();
    
    app.use(cors());
    app.use(express.json());
    // Middleware for session management
    app.use(session({
      secret: process.env.SESSION_SECRET,
      resave: false,
      saveUninitialized: true
    }));
    
    // Passport middleware
    app.use(passport.initialize());
    app.use(passport.session());
    
    // MongoDB connection
    mongoose.connect(process.env.MONGO_URI)
      .then(() => console.log('MongoDB connected'))
      .catch(err => console.error('MongoDB connection error:', err));
    
    // Auth routes
    app.use('/auth', authRoutes);
    app.use('/group',groupRoutes);
    
    app.listen(process.env.PORT || 3000, () => {
      console.log(`Server running on port ${process.env.PORT || 3000}`);
      app.get('/', (req, res) => {
        res.send('Hello, world!');
      });
    });
    
    
    app.get('/dashboard', (req, res) => {
      if (!req.isAuthenticated()) {
        return res.redirect('/auth/spotify');
      }
      res.send(`Welcome, ${req.user.displayName}!`);  // Access user info from Spotify profile
    });
    
    
  • Passport.js

    const passport = require('passport');
    const SpotifyStrategy = require('passport-spotify').Strategy;
    const User = require('../models/User');  // Your User model
    
    passport.use(new SpotifyStrategy({
      clientID: process.env.SPOTIFY_CLIENT_ID,
      clientSecret: process.env.SPOTIFY_CLIENT_SECRET,
      callbackURL: "http://localhost:3000/auth/spotify/callback",
    },
      async function(accessToken, refreshToken, expires_in, profile, done) {
        try {
          // Check if the user already exists
          let user = await User.findOne({ spotifyId: profile.id });
    
          if (!user) {
            // If user doesn't exist, create a new one
            user = new User({
              spotifyId: profile.id,
              displayName: profile.displayName,
              email: profile.emails[0].value,
              profileImage: profile.photos[0]?.value,
              accessToken,
              refreshToken
            });
            await user.save();
          } else {
            // If user exists, update tokens
            user.accessToken = accessToken;
            user.refreshToken = refreshToken;
            await user.save();
          }
    
          return done(null, user);
        } catch (err) {
          return done(err, null);
        }
      }
    ));
    
    passport.serializeUser((user, done) => {
      done(null, user.id);
    });
    
    passport.deserializeUser(async (id, done) => {
      try {
        const user = await User.findById(id);
        done(null, user);
      } catch (err) {
        done(err, null);
      }
    });
    
    
  • authmiddleware.js

    const axios = require('axios');
    const User = require('../models/User');
    
    const ensureAuthenticated = async (req, res, next) => {
      const authHeader = req.headers.authorization;
    
      if (!authHeader || !authHeader.startsWith('Bearer ')) {
        return res.status(401).json({ message: 'User not authenticated' });
      }
    
      const token = authHeader.split(' ')[1];
    
      try {
        // Validate the token by making a request to Spotify API
        const response = await axios.get('https://api.spotify.com/v1/me', {
          headers: {
            Authorization: `Bearer ${token}`,
          },
        });
    
        const spotifyUserData = response.data;
    
        // Find the user in your MongoDB by spotifyId
        const user = await User.findOne({ spotifyId: spotifyUserData.id });
    
        if (!user) {
          return res.status(401).json({ message: 'User not found in the system' });
        }
    
        // Attach MongoDB user object to req.user
        req.user = user;
    
        next(); // Continue to the next middleware or route handler
      } catch (error) {
        return res.status(401).json({ message: 'Invalid token or session expired' });
      }
    };
    
    module.exports = ensureAuthenticated;
    
    
  • User.js (model)

    const mongoose = require('mongoose');
    
    const userSchema = new mongoose.Schema({
      spotifyId: { type: String, required: true, unique: true }, // Spotify ID
      displayName: { type: String },  // Spotify username
      email: { type: String },        // Spotify email
      profileImage: { type: String }, // Spotify profile picture
      accessToken: { type: String },  // Spotify OAuth access token
      refreshToken: { type: String }, // Spotify OAuth refresh token
      friends: [{ type: mongoose.Schema.Types.ObjectId, ref: 'User' }], // Friends in your app
      friendRequests: [{ type: mongoose.Schema.Types.ObjectId, ref: 'User' }], // Pending friend requests
      activeGroup: { type: mongoose.Schema.Types.ObjectId, ref: 'Group', default: null },  // Active group, null if not in any
      createdAt: { type: Date, default: Date.now }
    });
    
    module.exports = mongoose.model('User', userSchema);