Google APi + Passport + React:身份验证流程

Posted

技术标签:

【中文标题】Google APi + Passport + React:身份验证流程【英文标题】:Google APi + Passport + React : Authentication flow 【发布时间】:2020-06-02 14:58:16 【问题描述】:

我正在使用护照通过 Google API 进行身份验证,我正在通过 URL 向客户端(React 应用程序)发送一个令牌,客户端将其保存在 localStorage 中。

我想使用该令牌:对于每个 API 调用(get、post、put),我都想将该令牌发送到服务器,但我不知道如何在服务器端验证该令牌。

护照攻略:

app.use(passport.initialize()); // Used to initialize passport
app.use(passport.session()); // Used to persist login sessions

passport.use(new GoogleStrategy(
    clientID: 'IDxxxxx',
    clientSecret: 'SecreXXX',
    callbackURL: 'http://localhost:3000/callback'
,
(accessToken, refreshToken, profile, done) => 

    // Directory API here

    var userData = 
        name: profile.displayName,
        token: accessToken
       ;

    done(null, userData);

身份验证:

app.get('/auth/google', passport.authenticate('google', 
    scope: ['profile'] // Used to specify the required data
));


// The middleware receives the data from Google and runs the function on Strategy config
app.get('/callback', passport.authenticate('google'), (req, res) => 
    var token = req.user.token;
    res.redirect("http://localhost:8000?token=" + token);
);

express 中的 API(包含 CRUD 方法):

app.use('/api', movieRouter)

在反应方面:获取令牌

  componentWillMount() 
    var query = queryString.parse(this.props.location.search);
    if (query.token) 
      window.localStorage.setItem("jwt", query.token);
      // appel a directory api (avec token) puis sauvergarder dans redux puis redirection vers liste demandes
      this.props.history.push("/");
    
  

做 API 调用:

import axios from 'axios'

const api = axios.create(
    baseURL: 'http://localhost:3000/api',
)

export const insertMovie = payload => api.post(`/movie`, payload)

我只需要在每次调用中发送令牌并在服务器端检查它。

谢谢

【问题讨论】:

【参考方案1】:

对于您要验证令牌的每个 API,您可以在执行以下操作之前传递一个验证令牌函数(我称之为“isCorrectToken”):

router.get("/api", isCorrectToken, (req, res) => 
// your api content )

然后,这就是我们的 isCorrectToken 函数:

const isCorrectToken = (req, res, next) => 
const token = req.headers.authorization;
if(token)
    const onlyToken = token.slice(7, token.length);
    jwt.verify(onlyToken, accessToken, (err, decode) => 
        if(err) return res.status(401).send( msg: 'Invalid Token' );
        req.user = decode;
        next();
        return;
    );

else return res.status(401).send( msg: 'Token is not supplied');

数字 7 是“Bearer”的长度(来自 Bill Metcalf 的上述回答)。

【讨论】:

【参考方案2】:

如 Bill Metcalf 所述,如果客户端在标头、会话或 cookie 中正确设置了令牌,则 express 能够通过将 passport.authenticate 中间件函数添加到路由来对路由/端点进行身份验证,如下所示

app.use('/api', passport.authenticate('google', failureRedirect:'/login'), movieRouter)

更多信息请参考http://www.passportjs.org/docs/google/

【讨论】:

从源“localhost:8000”访问“accounts.google.com/o/oauth2/v2/…”处的 XMLHttpRequest(从“localhost:3000/api/movie/5e46bc5b8467a51ae4b90f3a'”重定向)已被 CORS 策略阻止:对预检请求的响应未通过访问控制检查: 请求的资源上不存在“Access-Control-Allow-Origin”标头。【参考方案3】:

您最有可能在标头中设置令牌,尝试将您的 axios 客户端更改为类似

const api = axios.create(
  baseURL: 'http://localhost:3000/api',
  headers: 
    Authorization: `Bearer $your_token_here`
  
)

我不能 100% 确定这是否是护照所期望的正确标题格式,但这是您需要做的一般想法。

【讨论】:

以及如何在服务器端验证该令牌? API 仍对公众开放调用

以上是关于Google APi + Passport + React:身份验证流程的主要内容,如果未能解决你的问题,请参考以下文章

使用 passport.js 将本地策略连接到另一个(Facebook、Twitter、Google 等)

我如何通过带有请求的Express传递请求API响应?

如何使用 JWT 和 Passport 正确使用 nodeJs API 的身份验证?

Google oauth20 的 Passport,未使用中间件,passport.initialize()

使用 google-passport-oauth 登录后 req.user 未定义

Passport.js 在 nginx 上表达 google oauth 502 Bad Gateway