我使用Auth0来托管我的所有用户数据.我也有自己的后端,我希望有一个Users
表,它将我的数据库生成映射userId
到Auth0 user_id
.注册时,我在两个流程之间犹豫不决:
注册流程1:
前端显示Lock,用户注册.
Auth0重定向回前端后,前端有Auth0 user_id
.
前端调用后端POST /users
(公共端点)以创建新用户user_id
.
在对我的后端资源服务器的每个经过身份验证的请求中,JWT包含auth0 user_id
,因此db在user_id
和我之间进行查找userId
.
注册流程2:
前端显示Lock,用户注册.
在Auth0上配置一个后注册挂钩,用于调用POST /users
我的后端.此调用将生成我的数据库userId
并将其发送回Auth0.
把它userId
放到Auth0中user_metadata
.
这user_metadata
将包含在JWT中,因此对我的后端获取资源的所有调用都将包含db userId
(不需要额外的查找).
我觉得2更坚固.还有其他注册流程吗?一些auth0客户是否使用与我的#2类似的流程?我在他们的文档中找不到多少.
1> 小智..:
这是我的第一篇文章,如果我犯了任何新手错误,请原谅.
我发现注册流程1工作得很好.你没有指定你正在使用哪种技术,但这里有一个指向我的github的链接,我有一个功能齐全的博客,使用注册流程1与React,redux和Express后端.
https://github.com/iqbal125/react-redux-fullstack-blog
我将演示这些框架,以便您可以调整您正在使用的框架的代码.
我的注册过程如下:
前端显示Lock用户注册
用户被重定向到回调页面.
然后,我从回调页面重定向到"auth-check"页面.我在auth-check页面中有一个嵌套的api调用,它从auth0获取用户数据,然后立即调用api端点将用户数据保存到db.
api调用检查用户是否已经在sql db中然后保存用户数据,否则什么都不做.
然后,用户数据将保存到redux全局状态,并可用于在用户配置文件页面上显示数据.
当用户单击注销时,将再次调用authcheck并从全局状态中删除用户信息,然后注销用户.
验证然后重定向回主页.
1.前端显示Lock用户注册
login() {
this.auth0.authorize();
}
2.用户被重定向到回调页面.
我的回调页面非常简单,我将其用作功能组件.
Callback
3.然后,我从回调页面重定向到"auth-check"页面
我通过auth.js util组件中的handleAuthentication()函数执行此操作.代码稍微修改了auth0样本.
handleAuthentication() {
this.auth0.parseHash((err, authResult) => {
if (authResult && authResult.accessToken && authResult.idToken) {
this.setSession(authResult);
this.getProfile();
setTimeout( function() { history.replace('/authcheck') }, 2000);
} else if (err) {
history.replace('/');
console.log(err);
alert(`Error: ${err.error}. Check the console for further details.`);
}
});
}
你会注意到我添加了一个getProfile()函数
getProfile() {
let accessToken = this.getAccessToken();
if(accessToken) {
this.auth0.client.userInfo(accessToken, (err, profile) => {
if (profile) {
this.userProfile = { profile };
}
});
}
}
以及getAccessToken()函数
getAccessToken() {
if (localStorage.getItem('access_token')) {
const accessToken = localStorage.getItem('access_token')
return accessToken
}
else {
console.log("No accessToken")
return null
}
}
auth.js util组件中的这两个函数将允许我们从auth0获取信息并将其保存到我们在类中声明的空对象.
userProfile = {}
继续使用auth-check.js容器.我首先在构造函数中声明函数,然后是函数本身.然后我调用componentDidMount()生命周期方法,该方法在组件呈现时自动运行.
constructor() {
super()
this.send_profile_to_db = this.send_profile_to_db.bind(this)
}
send_profile_to_db (profile) {
const data = profile
axios.post('api/post/userprofiletodb', data)
.then(() => axios.get('api/get/userprofilefromdb', {params: {email: profile.profile.email}} )
.then(res => this.props.db_profile_success(res.data))
.then(history.replace('/')))
}
我的生命周期方法和我返回一个空div.
componentDidMount() {
if(this.props.auth.isAuthenticated()) {
this.props.login_success()
this.props.db_profile_success(this.props.auth.userProfile)
this.send_profile_to_db(this.props.auth.userProfile)
} else {
this.props.login_failure()
this.props.profile_failure()
this.props.db_profile_failure()
history.replace('/')
}
}
render() {
return (
)
}
}
我认为这里的代码是你问的问题的核心.
我将从send_profile_to_db()函数开始.
在这里我使用axios来发出请求.我开始向我的快速服务器发出后端api调用(我将在下一步中解释)并且我将用户配置文件作为数据对象参数传递给axios.您可能想知道实际用户配置文件数据的来源.
在我的routes.js根组件中,我导入并初始化了一个新的Auth实例
export const auth = new Auth();
然后将其作为支持传递给AuthCheck组件.
} />
这允许我使用"this.props"访问auth类的所有属性.所以我只使用我们在最后一步中初始化的"userProfile = {}"对象,该对象现在包含我们的用户数据.
在使用嵌套的".then()"函数将数据发布到数据库之后,使用用户电子邮件调用axios get请求作为从数据库中查找配置文件的参数.数据库配置文件包含有关用户帖子和用户评论的数据.这对于在应用程序中显示数据非常有用.然后我使用另一个".then()"语句和Redux Thunk将用户配置文件数据异步保存到全局redux状态.
总而言之,这个authcheck组件正在做4件事:
1.将我们从auth0获得的用户配置文件数据保存到我们自己的数据库中.
2.然后在保存数据后,立即从我们的数据库中检索相同的配置文件.
3.让我们的应用程序了解用户是否经过身份验证.
4.将我们的数据库用户配置文件数据保存到全局redux状态,以便在其他组件中使用.
如果你问我,真棒!
4. api调用检查用户是否已经在sql db中然后保存用户数据,否则什么都不做.
现在这是我的服务器设置.为用户提供数据库"发布"和"获取"请求.
router.post('/api/post/userprofiletodb', (req, res, next) => {
const values = [req.body.profile.nickname, req.body.profile.email, req.body.profile.email_verified]
pool.query('INSERT INTO users(username, email, date_created, email_verified) VALUES($1, $2, NOW(), $3) ON CONFLICT DO NOTHING', values, (q_err, q_res) => {
if (q_err) return next(q_err);
console.log(q_res)
res.json(q_res.rows);
});
});
/* Retrieve user profile from db */
router.get('/api/get/userprofilefromdb', (req, res, next) => {
// const email = [ "%" + req.query.email + "%"]
const email = String(req.query.email)
pool.query("SELECT * FROM users WHERE email = $1", [ email ], (q_err, q_res) => {
res.json(q_res.rows)
});
});
有几点需要注意:
路由器对象是express.router().我正在使用psql.
请记住添加"ON CONFLICT DO NOTHING",否则您将保存同一用户的多个版本.
我认为auth0会提供更多的数据点但我最终没有使用它们.
这是我的用户表的SQL架构.
CREATE TABLE users (
uid SERIAL PRIMARY KEY,
username VARCHAR(255) UNIQUE,
email VARCHAR(255),
email_verified BOOLEAN,
date_created DATE,
last_login DATE
);
5.然后将用户数据保存到redux全局状态,并可用于在用户配置文件页面上显示数据.
我最后在第3步中解释了这一点.
6.当用户单击注销时,将再次调用authcheck,并从全局状态中删除用户信息,然后注销用户.
见第3步
7. auth-check然后重定向回主页.
再次看到第3步大声笑.
如果你感兴趣或者我错过了任何东西,请务必查看我的回购,就像我说它是一个完整的功能齐全的博客.