Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Node.js 如何使用passport验证React应用程序?_Node.js_Reactjs_Express_Proxy_Passport.js - Fatal编程技术网

Node.js 如何使用passport验证React应用程序?

Node.js 如何使用passport验证React应用程序?,node.js,reactjs,express,proxy,passport.js,Node.js,Reactjs,Express,Proxy,Passport.js,我有一个React应用程序 我还有一个Express服务器,使用passport saml我可以根据公司的PingID SSO IdP进行身份验证 我想让React应用程序调用Express应用程序进行身份验证 Express服务器和React应用程序在同一台主机上运行 以下是我所拥有的: // Express App - rendering code pulled out const express = require('express'); var passport = require('p

我有一个React应用程序

我还有一个Express服务器,使用
passport saml
我可以根据公司的PingID SSO IdP进行身份验证

我想让React应用程序调用Express应用程序进行身份验证

Express服务器和React应用程序在同一台主机上运行

以下是我所拥有的:

// Express App - rendering code pulled out
const express = require('express');
var passport = require('passport');
var Strategy = require('passport-saml').Strategy;
var fs = require('fs')
const bodyParser = require('body-parser');
const cookieParser = require('cookie-parser');
const expressSession = require('express-session');
const app = express();
const port = process.env.PORT || 4005;

passport.use('saml2', new Strategy({
    path: 'http://MYSERVER:4005/assert',
    entryPoint: 'https://sso.connect.pingidentity.com/sso/idp/SSO.saml2?XXXXXXXX',
    issuer: 'MYAPP',
    audience: 'MYAPP',
  },
  function(profile, cb) {
    return cb(null, profile);
  }));

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

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

app.use(cookieParser());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(expressSession({
    secret: '123xyz',
    resave: true,
    saveUninitialized: true 
}));

// Initialize Passport and restore authentication state, if any, from the session.
app.use(passport.initialize());
app.use(passport.session());

app.get('/login/idp', () =>{
    passport.authenticate('saml2')
    console.log('Authentication called');
});

app.get('/login', () =>{
    console.log('Authentication failed, try again');
});

app.post('/assert', 
  passport.authenticate('saml2', { failureRedirect: '/login' }),
  function(req, res) {
    console.log('Authentication succeeded');
    console.log(req.user)
    res.redirect('/');
  });

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

在我的React应用程序的
package.json
中,我有:

{
  ...
  "proxy": "http://localhost:4005/",
  ...
}
toy Create React应用程序的概要如下:

// Create React App
import React, { useState } from 'react';
import './App.css';

function App() {

  const handleLogin = async e => {
    e.preventDefault();
    const response = await fetch('/login/idp', {
      method: 'GET',
      headers: {
        'Content-Type': 'application/json',
      }
    });
  };

  return (
    <div className="App">
      <form onSubmit={handleLogin}>
        <button type="submit">Login</button>
      </form>
    </div>
  );
}

export default App;
//创建React应用程序
从“React”导入React,{useState};
导入“/App.css”;
函数App(){
const handleLogin=async e=>{
e、 预防默认值();
const response=wait fetch('/login/idp'{
方法:“GET”,
标题:{
“内容类型”:“应用程序/json”,
}
});
};
返回(
登录
);
}
导出默认应用程序;
我可以愉快地单击按钮,控制台显示Express服务器的GET被触发,但没有返回到React客户端


代理是一种方式吗?我有正确的方法吗?如果是这样,我如何将结果从Express应用程序返回到React应用程序?

我有一个解决方案,但这似乎是一个可怕的黑客攻击。然而,它是有效的,我需要把这件事讲清楚。如果有人能提出改进或替代方法,我将不胜感激

我们从一个基本的Express服务器(托管在4005)开始,它可以通过Passport SAML SSO验证用户:

const express=require('express');
const jwt=require('jsonwebtoken')
const passport=require(‘passport’);
const Strategy=require('passport-saml')。策略;
require('dotenv').config()
常量签名=process.env.signature
const expiresIn=process.env.expiresIn
//简化:实际上这里有一个db查找
//基于req.user,以便仅获取id
//但你明白了
const createToken=user=>
签名({user.email},签名,{expiresIn:expiresIn})
passport.use('saml2',新策略({
路径:'http://localhost:4005/assert',
入口点:'https://sso.connect.pingidentity.com/sso/idp/SSO.saml2?idpid=XXXX_YOURVALUEHERE_XXXX',
发卡机构:“XXXX\u您的ID此处\u XXXX”,
观众:“XXXX\u你的名字在这里\u XXXX”,
},
功能(配置文件,cb){
返回cb(空,配置文件);
}));
passport.user(函数(user,done){
完成(空,用户);
});
passport.deserializeUser(函数(obj,done){
完成(空,obj);
});
//创建新的Express应用程序。
var-app=express();
app.use(require('cookie-parser')());
use(require('body-parser').urlencoded({extended:true}));
//初始化Passport并从
//会议。
app.use(passport.initialize());
app.get('/login/idp',passport.authenticate('saml2');
app.post(“/assert”,
passport.authenticate('saml2',
{故障重定向:`http://localhost:3000/?error=unauthenticated` } ),
功能(req、res){
const token=createToken(请求用户)
res.重定向(`http://localhost:3000/signinOK?token=${token}`);
});
app.listen(4005);
然后在React
src
文件夹中,添加所需的setupProxy.js:

const{createProxyMiddleware}=require('http-proxy-middleware');
module.exports=函数(应用程序){
应用程序使用(
“/login”,
CreateProxy中间件({
目标:'http://localhost:4005',
标题:{
“连接”:“保持活动”
}
})
);
};
然后在React应用程序(托管在端口3000)中,我们为首页创建一个简单的按钮组件:

import React from 'react'
import { Button } from '@material-ui/core'

function StartBtn() {
  return (
    <Button type="submit" variant="contained" color="primary" >
      <a href="/login/idp">Login</a>
    </Button>
  )
}

export default StartBtn
从“React”导入React
从“@material ui/core”导入{Button}
函数StartBtn(){
返回(
)
}
导出默认StartBtn
在这一点上,我们将
粘贴在首页上,并装配一条响应
http://localhost:3000/signinOK?token=...
通过抓取令牌,将其用作任何后续
承载:
身份验证中的值,并重定向到主站点

流程如下:

  • 用户加载首页,然后单击
  • 链接通过
    setupProxy.js
    重定向到Express服务器
  • Express server尝试进行
    Passport SAML
    身份验证
  • 身份验证过程的结果是通过
    /assert
    路由从IdP(PingID身份验证服务器)向Express服务器进行POST调用
  • 结果要么成功,要么失败,但在这两种情况下都会重新指向React应用程序
  • 如果成功,则返回用户详细信息作为JWT;或
  • 如果失败,将返回一个错误
  • 如果我能找到改进的方法,或者在JWT阶段进行扩展,我会回到这个答案上来


    我希望有人(a)觉得这很有用,或者(b)发明了一台时间机器,在3周前返回并发布这篇文章,这样我可以保存更多剩余的毛囊。或者(c)告诉我应该怎么做。

    我有一个解决方案,但它看起来像一个可怕的黑客。然而,它是有效的,我需要把这件事讲清楚。如果有人能提出改进或替代方法,我将不胜感激

    我们从一个基本的Express服务器(托管在4005)开始,它可以通过Passport SAML SSO验证用户:

    const express=require('express');
    const jwt=require('jsonwebtoken')
    const passport=require(‘passport’);
    const Strategy=require('passport-saml')。策略;
    require('dotenv').config()
    常量签名=process.env.signature
    const expiresIn=process.env.expiresIn
    //简化:实际上这里有一个db查找
    //基于req.user,以便仅获取id
    //但你明白了
    const createToken=user=>
    签名({user.email},签名,{expiresIn:expiresIn})
    passport.use('saml2',新策略({
    路径:'http://localhost:4005/assert',
    入口点:'https://sso.connect.pingidentity.com/sso/idp/SSO.saml2?idpid=XXXX_YOURVALUEH