gpt4 book ai didi

node.js - 在与 api 不同的域上对单页应用程序进行 Auth0 身份验证

转载 作者:搜寻专家 更新时间:2023-10-31 23:46:21 26 4
gpt4 key购买 nike

我正在尝试将 Auth0 身份验证添加到我的单页应用程序。我的应用程序在一个域下运行,比如 app.mycompany.com,而这个应用程序使用的 api 在不同的域下运行,比如 api.mycompany.com。

我知道这个线程:

Single Sign On (SSO) solution/architecture for Single Page App (SPA)

以及此处链接的 auth0 文章和 github 存储库。但我觉得我的场景稍微简单一些,因为我不一定希望在几个不同的单页应用程序之间进行单点登录。首先,我只想将 API 和应用程序分开。

这是我已经尝试过的:

我已经从文章 React Login With Auth0 开始了并下载了启动项目。我肯定可以毫无问题地登录,它会在我的 localStorage 中留下一个 id_token,其中包含一个由 Auth0 发布的 JWS。

我还可以直接登录 api.mycompany.com(我的 FeathersJS API 应用程序),我可以看到在 OAuth 重定向过程中,id_token token 被神奇地转换为我的 Feathers 应用程序发布的 feathers-jwt token ,其中包含与 auth0-ID 匹配的用户对象的内部 ID。我还实现了用于从 Auth0-ID 映射到我的内部 ID 的逻辑。此外,我所有的 Feathers Hook (例如 token 验证和用户人口)都在工作。

我想不通的是如何使用 localStorage 中的 Auth0 token 更改在 app.mycompany.com 下运行的 react 应用程序,以便该 token 被 api.mycompany.com 转换为 feathers-jwt token ,这样所有后续的 API 调用都会自动包含 feathers-jwt token ,这样 API 就可以验证用户并返回正确的数据。

任何关于如何进行的建议将不胜感激。

一些更多的背景细节:

  • 该 api 建立在 node.js 和 featherjs 上(基本上是 Express 的扩展)
  • 单页应用程序基于 ReactJS 构建,由一个简单的 Express 服务器提供服务,但它可以由任何可以通过 http 提供静态文件的服务器提供服务。单页应用程序向 api 发出 http 请求以读取数据和执行操作。
  • api 有以下几行代码负责身份验证:

    const authentication = require('feathers-authentication');
    const Auth0Strategy = require('passport-auth0').Strategy;
    app.configure(authentication({
    local:false,
    token: {
    secret: 'mysecret',
    payload: ['email', 'auth0Nickname'],
    issuer: 'mycompany'
    },
    idField: 'id',
    shouldSetupSuccessRoute: false,
    auth0: {
    strategy: Auth0Strategy,
    domain: 'mycompany.eu.auth0.com',
    'clientID': 'xxx',
    'clientSecret': 'yyy'
    }
    }));

最佳答案

我遇到了与您完全相同的问题,我想从单页应用程序调用位于其他服务器上的 API 对用户进行身份验证。

official auth0 example是一个经典的 Express Web 应用程序,它执行身份验证并呈现 html 页面,但它不是连接到托管在其他域上的 API 的 SPA。

让我们分解一下本例中用户进行身份验证时发生的情况:

  • 用户发起请求调用/auth/auth0路由
  • 用户被自动重定向到 Auth0 身份验证过程(Auth0 登录表单选择提供商,然后是提供商登录屏幕)
  • 用户被重定向到/auth/success 路由
  • /auth/success 路由重定向到静态 html 页面 public/success.html,同时发送一个 jwt-token cookie,其中包含用户的 token
  • 客户端,当 public/success.html 加载时,Feathers 客户端 authenticate() 方法从 cookie 中读取 token 并将其保存在本地存储中。

从现在开始,Feathers 客户端将验证从本地存储读取 cookie 的用户。

我尝试将这种场景适配为单页应用架构,实现了如下流程:

  • 在 SPA 中,使用包含 SPA URL 的 source 查询字符串参数调用身份验证 API。例如:http://my-api.com/auth/auth0?source=http://my-spa.com
  • 服务器端,在 /auth/auth0 路由处理程序中,创建一个 cookie 来存储该 URL
  • 成功登录后,读取 source cookie 将用户重定向回 SPA,在 cookie 中发送 JWT token 。

但是最后一步没有奏效,因为您不能在给定域(API 服务器域)上设置 cookie 并将用户重定向到其他域! (更多关于 Stackoverflow 上的 here)

所以实际上我通过以下方式解决了这个问题:

  • 服务器端:使用 URL 哈希将 token 发送回客户端。
  • 客户端:创建一个新的 html 页面,从 URL 哈希中读取 token

服务端代码:

// Add a middleware to write in a cookie where the user comes from
// This cookie will be used later to redirect the user to the SPA
app.get('/auth/auth0', (req, res, next) => {
const { origin } = req.query
if (origin) {
res.cookie(WEB_CLIENT_COOKIE, origin)
} else {
res.clearCookie(WEB_CLIENT_COOKIE)
}
next()
})

// Route called after a successful login
// Redirect the user to the single-page application "forwarding" the auth token
app.get('/auth/success', (req, res) => {
const origin = req.cookies[WEB_CLIENT_COOKIE]
if (origin) {
// if there is a cookie that contains the URL source, redirect the user to this URL
// and send the user's token in the URL hash
const token = req.cookies['feathers-jwt']
const redirectUrl = `${origin}/auth0.html#${token}`
res.redirect(redirectUrl)
} else {
// otherwise send the static page on the same domain.
res.sendFile(path.resolve(process.cwd(), 'public', 'success.html'))
}
})

客户端,SPA中的auth0.html页面

在 SPA 中,我创建了一个名为 auth0.html 的新 html 页面,它做了 3 件事:

  • 它从哈希中读取 token
  • 它将它保存在本地存储中(模仿 Feathers 客户端所做的)
  • 它将用户重定向到 SPA 主页 index.html

html代码:

<html>
<body>
<script>
function init() {
const token = getToken()
if (!token) {
console.error('No auth token found in the URL hash!')
}
// Save the token in the local storage
window.localStorage.setItem('feathers-jwt', token)
// Redirect to the single-page application
window.location.href = '/'
}

// Read the token from the URL hash
function getToken() {
const hash = self.location.hash
const array = /#(.*)/.exec(hash)
if (!array) return
return array[1]
}

init()
</script>
</body>
</html>

现在在 SPA 中,我可以使用 Feathers 客户端,在应用启动时从本地存储读取 token 。

如果有道理,请告诉我,谢谢!

关于node.js - 在与 api 不同的域上对单页应用程序进行 Auth0 身份验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40497554/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com