passport-spotify accessToken 在会话中未定义

问题描述 投票:0回答:1

这是我正在网络上处理的一个博览会项目。它尝试使用 Spotify Web API 进行身份验证。访问令牌从 Spotify 身份验证页面返回,可在 req.user.accessToken 的回调中使用。

但是,在随后调用的其他路由中,req.user.accessToken 和 req.session.accessToken 都是未定义的。尽管在回调中尝试将令牌分配给会话,但仍然如此。

这里,访问令牌在身份验证回调中可用...

app.get(
"/auth/spotify/callback",
  passport.authenticate("spotify", { failureRedirect: "/" }),
  (req, res) => {
    req.session.accessToken = req.user.accessToken;
    console.log("callback: " + req.session.accessToken);
    res.redirect("http://localhost:8081");
  }
);

但其他路线没有

app.get("/spotify/get-currently-playing", async (req, res) => {
  try {
    const accessToken = req.session && req.session.accessToken;
    if (!accessToken) {
      throw new Error("Access token not found");
    }
    const userData = await getCurrentSongInfo(accessToken);
    res.json(userData);
...

中间件之前已设置如下

app.use(
  session({
    secret: "x",
    resave: false,
    saveUninitialized: false,
  })
);

app.use(passport.initialize());
app.use(passport.session());

passport.use(
  new SpotifyStrategy(
    {
      clientID: "x",
      clientSecret: "x",
      callbackURL: "http://localhost:5001/auth/spotify/callback",
    },
    (accessToken, refreshToken, expires_in, profile, done) => {
      // Store the access token in the session
      if (accessToken) {
        profile.accessToken = accessToken;
        console.log(profile);
        done(null, profile);
      } else {
        done(new Error("Failed to retrieve access token"));
      }
    }
  )
);
express expo passport.js spotify
1个回答
0
投票

您需要从用户会话数据中获取

来自

app.get(
"/auth/spotify/callback",
  passport.authenticate("spotify", { failureRedirect: "/" }),
  (req, res) => {
    req.session.accessToken = req.user.accessToken;
    console.log("callback: " + req.session.accessToken);
    res.redirect("http://localhost:8081");
  }
);

app.get(
"/auth/spotify/callback",
  passport.authenticate("spotify", { failureRedirect: "/" }),
  (req, res) => {
    if (req.user && req.user.accessToken) {
        console.log("callback: " + req.user.accessToken);
    } else {
        console.log('callback: accessToken is none');
    }
    res.redirect("http://localhost:8081");
  }
);

演示代码

package.json

{
  "dependencies": {
    "consolidate": "^1.0.3",
    "cors": "^2.8.5",
    "express": "^4.19.1",
    "express-session": "^1.18.0",
    "nunjucks": "^3.2.4",
    "passport": "^0.7.0",
    "passport-spotify": "^2.0.0"
  }
}

文件树

如何获得

client_id
client_secret
redirect_uri

通过浏览器打开网址

https://developer.spotify.com/dashboard

如何获取用户名

通过浏览器打开网址

https://open.spotify.com/

使用您的客户端 ID/密码和重定向 URI 另存为

server.js

const express = require('express');
const cors = require('cors');
const session = require('express-session');
const passport = require('passport');
const SpotifyStrategy = require('passport-spotify').Strategy;
const consolidate = require('consolidate');

const CLIENT_ID = '<your client id>';
const CLIENT_SECRET = '<your client secret>';
const port = 5001; // make sure your REDIRECT_URI's port
const authCallbackPath = '/auth/spotify/callback';

const REDIRECT_URI = `http://localhost:${port}${authCallbackPath}`;


passport.serializeUser(function (user, done) {
    done(null, user);
});

passport.deserializeUser(function (obj, done) {
    done(null, obj);
});

passport.use(
    new SpotifyStrategy(
        {
            clientID: CLIENT_ID,
            clientSecret: CLIENT_SECRET,
            callbackURL: REDIRECT_URI,
        },
        function (accessToken, refreshToken, expires_in, profile, done) {
            // asynchronous verification, for effect...
            process.nextTick(function () {
                try {
                    profile.accessToken = accessToken;
                    console.log(`accessToken is ${profile.accessToken}`);
                    return done(null, profile);
                } catch (error) {
                    return done(error);
                }
            });
        }
    )
);
const app = express();
app.use(cors()); // Enable CORS

app.use(
    session({ secret: 'keyboard cat', resave: false, saveUninitialized: false })
);

// Initialize Passport!  Also use passport.session() middleware, to support
app.use(passport.initialize());
app.use(passport.session());
app.use(express.static(__dirname + '/public'));

app.engine('html', consolidate.nunjucks);

app.get('/', function (req, res) {
    res.render('index.html', { user: req.user });
});

app.get('/account', ensureAuthenticated, function (req, res) {
    if (req.user && req.user.accessToken) {
        console.log(`In account accessToken is ${req.user.accessToken}`);
    } else {
        console.log('In account accessToken is none');
    }
    res.render('account.html', { user: req.user });
});

app.get('/login', function (req, res) {
    res.render('login.html', { user: req.user });
});

app.get('/logout', function (req, res) {
    req.logout();
    res.redirect('/');
});

// GET /auth/spotify
app.get(
    '/auth/spotify',
    passport.authenticate('spotify', {
        scope: ['user-read-email', 'user-read-private'], // you can add more scopes it depends on your require APIs call
        showDialog: false, // if set true force shows login UI
    })
);

// GET /callback
app.get(
    authCallbackPath,
    passport.authenticate('spotify', { failureRedirect: '/login' }),
    function (req, res) {
        res.redirect('/');
    }
);

// Logout route. it has a defect, I think `passport-spotify` not address it.
app.get('/logout', function (req, res) {
    req.logout(); // No need for a callback function here
    res.redirect('/'); // Redirect to login page or any desired page
});

app.listen(port, () => {
    console.log(`Server is running on port ${port}`);
});

function ensureAuthenticated(req, res, next) {
    if (req.isAuthenticated()) {
        return next();
    }
    res.redirect('/login');
}

HTML 文件

account.html

{% extends 'layout.html' %} {% block content %}
<p>ID: {{ user.id }}</p>
<p>Token: {{ user.accessToken }}</p>
<p>Profile:
    <a href=" {{ user.profileUrl }}">{{ user.profileUrl }}</a>
</p>
{% endblock %}

index.html

{% extends 'layout.html' %}

{% block content %}
{% if not user %}
    <h2>Welcome! Please log in.</h2>
    <p><a href="/login">login</a></p>
{% else %}
    <h2>Hello, {{ user.username }}.</h2>
    <p>Your email is {{ user.emails[0].value }}</p>
{% endif %}
{% endblock %}

layout.html

<!DOCTYPE html>
<html>

<head>
    <title>Passport-Spotify Example</title>
</head>

<body>
    {% if not user %}
    <p>
        <a href="/">Home</a> |
        <a href="/login">Log In</a>
    </p>
    {% else %}
    <p>
        <a href="/">Home</a> |
        <a href="/account">Account</a> |
        <a href="/logout">Log Out</a>
    </p>
    {% endif %} {% block content %}{% endblock %}
</body>

</html>

login.html

{% extends 'layout.html' %} {% block content %}
<a href="/auth/spotify">Login with Spotify</a>
{% endblock %}

结果

© www.soinside.com 2019 - 2024. All rights reserved.