【问题标题】:How to SSO in another domain using express server/react client and redirect to another domain?如何使用快速服务器/反应客户端在另一个域中 SSO 并重定向到另一个域?
【发布时间】:2020-02-24 20:03:58
【问题描述】:

问题是创建一个 Web 应用程序,该应用程序具有将其发送到我的 express 服务器的表单,从具有表单值的外部端点发布生成令牌,使用来自外部域的令牌发布到外部端点然后获得身份验证到外部域

我能够在我的快递服务器上生成令牌,使用令牌向外部端点发布第二个帖子,并且能够登录并查看快递服务器上的响应。

但是,当我尝试将我的 react 客户端重定向到外部域时,它会显示超时消息。

我尝试使用 Axios 和 Fetch 从客户端发布第二个帖子,然后重定向到外部域,但它给了我 CORS 错误,直到我打开 CORS chrome 插件,然后它仍然给我相同的超时消息。

我尝试在我的帖子调用中添加不同的标题以允许重定向,但没有成功。

const router = require('express').Router();
const xml2js = require('xml2js');
const parseString = require('xml2js').parseString;
const request2 = require('request');
// const axios = require('axios')
var setCookie = require('set-cookie-parser')
var Cookies = require('js-cookie')
require('dotenv').config();

router.post('/sso', (req, response, next)=>{

  // SETTING UP XML BODY FOR TOKEN GENERATOR

  // USING TEMPLATE TO BUILD XML BODY FOR TOKEN GENERATOR

  // SETTING UP POST TO TOKEN GENERATOR WITH XML TEMPLATE

  // DECLARING TOKEN TO PASS TO SSO POST

  // PROMISE FOR RESPONSE POST TO TOKEN GENERATOR
  return new Promise((resolve)=>{

    // ERROR CATCH BLOCK FOR POST TO TOKEN GENERATOR
    try {

      // POST TO TOKEN GENERATOR USING XML TEMPLATE
      request2(TokenGenerator,
        (err, res, body)=>{
          // PARSE TOKEN GENERATOR BODY RESPONSE

              // CONVERTING TO STRING SOAP BODY

              // PARSING STRING INTO JSON TO TARGET TOKEN

              // DECLARING TOKEN RESPONSE IN RES WITH TOKEN VALUE FROM POST TO TOKEN GENERATOR

              // ASSIGNING IT TO GLOBAL VARIABLE

            })

          // TRYING POST FROM CLIENT HAS BEEN COMMENTED OUT
          // // response.send(token)
          // // next()

          // SETTING UP POST TO PARTICIPANT SSO WITH TOKEN VALUE
          const secondPostToSSO = {
            method: 'POST',
            url: 'externaldomain.com/sso.aspx',
            followAllRedirects: true,
            jar: true,
            headers: {
              'Content-Type': 'text/html'
            },
            form: {
              'TOKEN': token
            }
          }

          // POST TO PARTICIPANT SSO WITH TOKEN
          request2.post(secondPostToSSO,(err, response2, body2)=>{
               console.log(response2.request)

               var cookies = setCookie.parse(response2, {
                 decodeValues: true,
                 map: true
               })

               console.log(cookies)      




               next()
             })

          })

    } catch (e) {
      console.error(`[FATAL ERROR] - KAPUT - ${e}`)
      return res.redirect('/')
    }

  })

})

module.exports = router

我希望服务器帖子的输出然后将客户端重定向到我获取令牌的 externaldomain.com,并使用令牌发布帖子以验证客户端。结果应该是客户端已从我的 Web 应用程序登录到外部域。

【问题讨论】:

    标签: node.js reactjs express single-sign-on saml


    【解决方案1】:

    几周前我解决了 CORS 问题并完成了申请,我想分享我的答案。

    我解决 CORS 问题的方法是删除 React 并在同一端口上的服务器端使用简单的 HTML 客户端。我使用 npm 包 cors (https://www.npmjs.com/package/cors)。我在server.js 文件中添加了一行,如下所示:app.use(cors());

    之后,我更新了我的 SSO 路由以使用 response.send(token) 而不是使用 next() 传递令牌。

    一旦浏览器接收到令牌,请记住,我的服务器和客户端在同一个端口上,一旦从服务器接收到令牌,客户端就会触发隐藏表单 POST。

    瞧,解决了。

    API 路由:

    const path = require('path');
    const router = require('express').Router();
    const app = require('express')
    const xml2js = require('xml2js');
    const parseString = require('xml2js').parseString;
    const request2 = require('request');
    const cors = require('cors')
    require('dotenv').config();
    
    // API routes
    module.exports.routes = function (app) {
    
        // POST API
        app.post("/api/sso", (request, response, next)=>{
    
            // SETTING UP XML BODY FOR TOKEN GENERATOR
            const Template = {
               // YOUR TEMPLATE
            }
    
            // USING TEMPLATE TO BUILD XML BODY FOR TOKEN GENERATOR
            const builder = new xml2js.Builder()
            const xml = builder.buildObject(Template)
    
            // SETTING THE RIGHT ENVIRONMENT LINK FOR TOKEN GENERATOR BASED ON USER INPUT WITH IF STATEMENT
    
            // SETTING UP POST TO TOKEN GENERATOR WITH XML TEMPLATE
            const TokenGenerator = {
                url: tokenGeneratorUrl,
                method: 'POST',
                headers: {
                    'Content-Type': 'text/xml'
                },
                body: xml
            }
    
            // DECLARING TOKEN TO PASS TO SSO POST
            let TOKEN = ''
    
            // PROMISE FOR RESPONSE POST TO TOKEN GENERATOR
            return new Promise((resolve) => {
    
                // ERROR CATCH BLOCK FOR POST TO TOKEN GENERATOR
                try {
    
                    // POST TO TOKEN GENERATOR USING XML TEMPLATE
                    request2(TokenGenerator,
                        (err, res, body) => {
                            // PARSE TOKEN GENERATOR BODY RESPONSE
                            parseString(body,
                                (err, result) => {
                                    // CONVERTING TO STRING SOAP BODY
                                    const strBody = JSON.stringify(result['soap:Envelope']['soap:Body'])
    
                                    // PARSING STRING INTO JSON TO TARGET TOKEN
    
                                    // DECLARING TOKEN RESPONSE IN RES WITH TOKEN VALUE FROM POST TO TOKEN GENERATOR
    
                                    // ASSIGNING IT TO GLOBAL VARIABLE
                                    TOKEN = res.TokenResponse
                                })
    
                            // SENDING TOKEN TO CLIENT TO POST TO SSO
                            response.send(TOKEN)
    
                        })
    
                } catch (e) {
                    console.error(`[FATAL ERROR] - KAPUT - ${e}`)
                    return res.redirect('/')
                }
    
            })
        });
    };
    

    客户端上的隐藏表单:

    <form style="display: none;" novalidate autocomplete="off" name="hiddenForm" id="hiddenForm" action="https://api.endpoint.com/route" method="POST" class="hiddenForm">
            <input type="hidden" id="TOKEN" name="TOKEN" value="">
    </form>
    

    【讨论】:

      猜你喜欢
      • 2014-08-28
      • 2023-04-02
      • 2019-09-17
      • 2019-11-25
      • 2010-10-14
      • 2022-09-23
      • 2018-07-15
      • 2013-01-23
      • 2013-05-18
      相关资源
      最近更新 更多