我正在尝试将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中留下一个包含Auth0发布的JWS的id_token。
我也可以直接登录api.mycompany.com(我的FeathersJS API应用程序),我可以看到在OAuth重定向过程中,id_token令牌神奇地转换为我的Feathers应用程序发出的包含与auth0-ID匹配的用户对象的内部ID。我还实现了用于从Auth0-ID映射到我的内部ID的逻辑。此外,我的所有Feathers钩子,例如令牌的验证和用户的人口都在工作。
我无法弄清楚如何使用localStorage中的Auth0令牌更改app.mycompany.com下运行的react-application,以便api.mycompany.com将此令牌转换为feathers-jwt令牌,以这种方式,所有后续API调用自动包含feathers-jwt标记,以便API可以验证用户并返回正确的数据。
任何有关如何进行的建议将不胜感激。
更多背景细节:
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'
}
}));
答案 0 :(得分:2)
我遇到与您完全相同的问题,我想从单个页面应用程序验证用户,调用位于其他服务器上的API。
official auth0 example是一个经典的Express网络应用程序,可以进行身份验证并呈现html页面,但它不是连接到其他域上托管的API的SPA。
让我们分析用户在此示例中进行身份验证时发生的情况:
/auth/auth0
路线/auth/success
路径/auth/success
路由重定向到静态html页面public/success.html
,同时发送包含用户令牌的jwt-token
Cookie public/success.html
时,Feathers客户端authenticate()
方法会从Cookie中读取令牌并将其保存在本地存储中。从现在开始,Feathers客户端将对从本地存储中读取cookie的用户进行身份验证。
我尝试将此场景改编为单页面应用程序架构,实现以下过程:
source
查询字符串参数调用身份验证API。例如:http://my-api.com/auth/auth0?source=http://my-spa.com
/auth/auth0
路由处理程序中,创建一个用于存储该URL的cookie source
Cookie以将用户重定向回SPA,并在Cookie中发送JWT令牌。但最后一步不起作用,因为您无法在给定域(API服务器域)上设置cookie并将用户重定向到其他域! (更多关于Stackoverflow上的here)
所以实际上我通过以下方式解决了问题:
// 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'))
}
})
auth0.html
页面
在SPA中,我创建了一个名为auth0.html
的新html页面,它可以完成3件事:
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客户端,在应用程序启动时从本地存储中读取令牌。
让我知道它是否有意义,谢谢!
答案 1 :(得分:1)
如果您还没有这样做,则应遵循本文(React Login with Auth0)在React应用程序上实现身份验证。 如果您已尝试关注该问题,请使用您遇到的具体问题更新您的问题。
即使您当前不需要SSO,您的应用程序中实际的身份验证实现也不会有太大变化。通过使用Auth0在您的应用程序中启用SSO主要是启用配置开关。
最后,请参阅完整参考,了解您的确切方案检查的安全相关方面背后的所有理论:
Auth0 Architecture Scenarios: SPA + API
<强>更新强>
我链接的完整场景也涵盖了最全面的场景,其中许多客户端应用程序访问API,甚至可能由不拥有受保护API的第三方开发,但想要访问其背后的数据。
它通过利用目前仅在美国地区提供的最新功能来实现这一点,并且在非常高的级别上可以将其描述为作为服务提供的OAuth 2.0授权服务器。
您的特定情况更简单,API和客户端应用程序都在同一实体的控制之下,因此您有另一种选择。
在这种情况下,您的客户端应用程序在身份验证时会收到id_token
,该access_token
将用于了解当前经过身份验证的用户,并且还会收到可用于调用API的id_token
代表经过身份验证的用户。
这使客户端应用程序和API之间有明确的区别; access_token
用于客户端应用程序使用,id_token
用于API用途。
它的好处是授权与身份验证明确分开,您可以通过控制访问令牌中包含的范围对授权决策进行非常精细的控制。
您可以单独部署客户端应用程序和API,但仍然可以从概念角度将它们视为同一个应用程序(您将在Auth0中配置一个客户端,代表客户端和API)。
这样做的好处是,您可以使用身份验证完成后获得的id_token
来了解用户在客户端的用户身份以及验证每个API请求的机制。
您必须配置Featles API以验证Auth0 pkey (PKey)
作为访问API的接受令牌。这意味着您不会根据API上的身份验证使用任何羽毛,也就是说,您只需接受Auth0颁发给您的应用程序的令牌作为验证访问权限的方式。