首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Auth0:在Auth0注册后在本地数据库中创建用户

Auth0:在Auth0注册后在本地数据库中创建用户
EN

Stack Overflow用户
提问于 2018-08-10 23:55:29
回答 2查看 5.2K关注 0票数 35

我使用Auth0托管我所有的用户数据。我也有自己的后端,我希望在其中有一个Users表,它将我的db生成的userId映射到Auth0的user_id。我在两个注册流程之间犹豫不决:

注册流程1:

  1. 前端显示锁,用户注册。
  2. 在Auth0重定向回前端之后,前端就有了Auth0 user_id
  3. 前端调用POST /users (公共端点)的后端,使用user_id创建一个新用户。
  4. 在对我的后端资源服务器的每个经过身份验证的请求上,JWT包含auth0 user_id,因此db在user_id和my userId之间进行查找。

注册流程2:

  1. 前端显示锁,用户注册。
  2. 在Auth0上配置一个注册后挂钩,在后端调用POST /users。此调用将生成我的db的userId并将其发送回Auth0。
  3. 将此userId放入Auth0的user_metadata中。
  4. 这个user_metadata将包含在JWT中,这样所有对后端的调用都将包括db的userId (不需要额外的查找)。

我觉得2更坚固。还有其他的注册流程吗?有些auth0客户是否使用了与我的第二条类似的流程?我在他们的文件里没找到多少。

EN

回答 2

Stack Overflow用户

发布于 2018-08-12 07:59:30

这是我的第一篇帖子,如果我犯了什么错误,请原谅。

我发现注册流程1工作得很好。您没有指定您使用的是哪些技术,但是这里有一个指向我的github的链接,在这里我有一个功能齐全的博客,使用带有React、redux和Express后端的注册流程1。

https://github.com/iqbal125/react-redux-fullstack-blog

我将用这些框架演示,希望您能够调整您正在使用的框架的代码。

我的注册过程如下:

  1. 前端显示锁用户注册
  2. 用户被重定向回回调页。
  3. 然后,我将回调页重定向到“auth”页面。我在auth检查页面中有一个嵌套的api调用,它从auth0获取用户数据,然后立即调用api端点将用户数据保存到db。
  4. api调用检查用户是否已经在sql中,然后保存用户数据,否则什么也不做。
  5. 然后将用户数据保存到还原全局状态,并可用于在用户配置文件页上显示数据。
  6. 当用户单击“注销”时,会再次调用authcheck,并从全局状态中删除用户信息,然后注销用户。
  7. 8月-检查,然后重定向回主页。

1.前端显示锁用户注册

代码语言:javascript
运行
复制
  login() {
    this.auth0.authorize();
   }

2.用户被重定向回回调页.

我的回调页面非常简单,我使用它作为一个功能组件。

代码语言:javascript
运行
复制
  <div>
    <h2>Callback</h2>
  </div>

3.然后将回调页重定向到"auth-check“页面

我是通过我的handleAuthentication()组件中的auth.js ()函数来完成这个任务的。代码从auth0示例中略作修改。

代码语言:javascript
运行
复制
  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()函数

代码语言:javascript
运行
复制
   getProfile() {
    let accessToken = this.getAccessToken();
    if(accessToken) {
      this.auth0.client.userInfo(accessToken, (err, profile) => {
        if (profile) {
          this.userProfile = { profile };
         }
       });
     }
    }

与getAccessToken()函数一起使用

代码语言:javascript
运行
复制
  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获取信息并将其保存到类中声明的空对象中。

代码语言:javascript
运行
复制
  userProfile = {}

转到auth-check.js容器。我首先在构造函数中声明函数,然后再声明函数本身。然后调用componentDidMount()生命周期方法,该方法在组件呈现时自动运行。

代码语言:javascript
运行
复制
  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。

代码语言:javascript
运行
复制
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 (
        <div>
       </div>
    )
  }
}

我想这段代码就是你问的问题的核心。

我将从send_profile_to_db()函数开始。

在这里,我使用axios来提出请求。我开始对我的express服务器进行后端api调用(我将在下一步解释),并将用户配置文件作为带有axios的数据对象参数传递。您可能想知道实际的用户配置文件数据来自何处。

在我的routes.js根组件中,我导入并初始化了一个新的Auth实例

代码语言:javascript
运行
复制
export const auth = new Auth();

然后将其作为道具传递给AuthCheck组件。

代码语言:javascript
运行
复制
<Route path="/authcheck" render={(props) => <AuthCheck auth={auth} {...props} />} />

这允许我使用"this.props“访问auth类的所有属性。因此,我只使用我们在最后一步初始化的"userProfile = {}“对象,该对象现在包含我们的用户数据。

在将数据发布到数据库之后,我使用嵌套的".then()“函数调用axios请求,并将用户电子邮件作为从数据库查找概要文件的参数。数据库概要文件包含有关用户帖子和用户评论的数据。这对于显示应用程序中的数据非常有用。然后,我使用另一个".then()“语句和一个Redux异步地将用户配置文件数据保存到全局redux状态。

总之,这个authcheck组件正在做4件事:

  1. 将从auth0获得的用户配置文件数据保存到我们自己的数据库中。
  2. 然后,保存数据后,立即从数据库中检索相同的配置文件。
  3. 让我们的应用程序知道用户是否经过身份验证。
  4. 将数据库用户配置文件数据保存到全局redux状态,以便在其他组件中使用。

很棒,如果你问我的话!

api调用检查用户是否已经在sql db中,然后保存用户数据,否则什么也不做。

现在这是我的服务器设置。对于用户到数据库的"post“和"get”请求。

代码语言:javascript
运行
复制
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。

记住添加“在冲突中什么都不做”,否则您将保存同一用户的多个版本。

我认为auth0还提供了几个数据点,但我最终没有使用它们。

这是我的用户SQL模式表。

代码语言:javascript
运行
复制
CREATE TABLE users (
  uid SERIAL PRIMARY KEY,
  username VARCHAR(255) UNIQUE,
  email VARCHAR(255),
  email_verified BOOLEAN,
  date_created DATE,
  last_login DATE
);

然后将用户数据保存到还原全局状态,并可用于在用户配置文件页.上显示数据。

最后,我只是在第三步解释了这一点。

当用户单击“注销”时,再次调用检查,并从全局状态删除用户信息,然后注销.

见步骤3

7. auth检查,然后重定向回主页.

再次请参见步骤3 lol。

一定要检查我的回购如果你有兴趣或如果我错过了什么,就像我说的,这是一个完整的充分运作的博客。

票数 21
EN

Stack Overflow用户

发布于 2021-01-20 21:29:12

在每次成功登录时,Flow 1都会对您的db执行一个“insert-或-忽略”命令,而在大规模的情况下,这不是一个好的实践。事实上,它也是DoS的一个潜在点,因为这个端点直接公开db。

因此,在我看来,Flow 2似乎是一个更好的选择,因为它只在db和Auth0的db之间同步一次。这里唯一的挑战是处理后注册过程中的失败。

还请注意,正如注释中所建议的那样,app_metadata是存储此类信息的更合适的地方。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51795272

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档