graphql 服务器电子邮件验证示例

Posted

技术标签:

【中文标题】graphql 服务器电子邮件验证示例【英文标题】:graphql server email verify example 【发布时间】:2018-01-15 19:23:24 【问题描述】:

我开始使用带有apollo-server-expressgraphql-tools 的graphql 开发一个express API。我的注册用户流程步骤是:

    用户提交用户名、邮箱和密码。

    服务器通过 Mailgun 向用户发送一封电子邮件,其中包含由uuid 生成的唯一链接。

    用户点击链接验证注册。

但我正在努力解决如何在解析器中绑定突变。见sn-ps:

server.js

  const buildOptions = async (req, res, done) => 
    const user = await authenticate(req, mongo.Users)
    return 
      schema,
      context: 
        dataloaders: buildDataloaders(mongo),
        mongo,
        user
      ,
    
    done()
  
  // JWT setting
  app.use('/graphAPI',
    jwt(
      secret: JWT_SECRET,
      credentialsRequired: false,
    ),
    graphqlExpress(buildOptions),
    res => data => res.send(JSON.stringify(data))
  )

解析器突变

 signupUser: async (root, data, mongo:  Users ) => 
      // Check existed accounts,
      // if account is not exist, assign new account
      const existed = await Users.findOne(email: data.email)
      if (!existed) 
        // create a token for sending email
        const registrationToken = 
          token: uuid.v4(),
          created_at: new Date(),
          expireAfterSeconds: 3600000 * 6 // half day
        
        const newUser = 
          name: data.name,
          email: data.email,
          password: await bcrypt.hash(data.password, 10),
          created_at: new Date(),
          verification_token: registrationToken,
          is_verified: false,
        
        const response = await Users.insert(newUser)
        // send and email to user
        await verifyEmail(newUser)
        return Object.assign(id: response.insertedIds[0], newUser)
      
      // Throw error when account existed
      const error = new Error('Email existed')
      error.status = 409
      throw error
    ,

    // VERIFY USER
    // Set verify to true (after user click on the link)
    // Add user to mailist
    verifiedUser: async (root, data, mongo:  Users ) => 
      await Users.updateOne(
         email: data.email ,
        
          set: is_verified: true,
          unset: verification_token: token: ''
        
      )
    ,

路由配置

routes.get('/verify?:token', (req, res, next) => 
  res.render('verified', title: 'Success')
) 

路由配置是我卡住的地方,因为对象通过graphqlExpress 中的上下文传递给所有解析器

任何人帮助我或为我推荐任何相关的文章。非常感谢。

【问题讨论】:

检查this comment 和我在那里提供的链接 是的,阅读这些东西是一条漫长的道路,我从中学到了很多,我被困在这里的问题是如何改变解析器以将 is_verified 字段设置为 @987654330 @ 当服务器向用户发送链接 mydomain.com/verify?:token 时,用户单击该链接以确认帐户。 【参考方案1】:

似乎与其使用verifiedUser 端点,不如将该逻辑保留在/verify 路由的控制器中会更简单。比如:

routes.get('/verify?:token', (req, res) => 
  Users.updateOne(
     verification_token:  token  ,
    
      $set: is_verified: true,
      $unset: verification_token: token: ''
    ,
    (err, data) => 
      const status = err ? 'Failure' : 'Success'
      res.render('verified', title: status)
        
  )
)

【讨论】:

是的,感谢@Daniel 的帮助,我将 更改为 verification_token: token: req.params.token t 更新,(我将 setunset 更改为 $set$unset 作为 mongodb 文档)【参考方案2】:

您将需要 3 个 graphql 端点和 1 个 apollo http 端点才能正常工作。

您可以选择将 3 个 graphql 端点合二为一,但这将是一个具有许多不同职责的大功能。

1# graphql 端点:changepass-request

需要电子邮件参数
    检查是否在 db 中找到具有此类电子邮件的用户: 生成代码 保存在本地账户节点 发送验证码到带有http链接的用户邮箱以确认验证码: http://yoursite.com/auth/verify?code=1234 返回redirect_uri:http://yoursite.com/auth/confirm-code 用于提示输入确认码的 UI 页面

2# graphql 端点:changepass-confirm

期望代码参数: 如果在 db 中找到具有此类代码的用户,则将 redirect_uri 返回到 UI 页面,并提示新的通过,并在参数中包含确认代码:http://yoursite.com/auth/change-pass?code=1234

3# graphql 端点:changepass-complete

期待代码和新的通行证:
    哈希新密码 在数据库中搜索具有此类代码的本地帐户 3a。如果没有找到: 使用 redirect_uri 将错误返回到登录页面: http://yoursite.com/auth?success=false&message="Confirmation 代码不正确,请重试。” 3b。如果找到: 更改新密码,使用 redirect_uri 将成功状态返回到登录页面: http://yoursite.com/auth?success=true&message="ok"

4# apollo HTTP 端点:http://yoursite.com/auth/verify?code=1234

如果没有提供代码: 重定向到 UI 注册页面,并在参数中显示错误消息: http://yoursite.com/auth?success=false&message="Confirmation 代码不正确,请重试。”

如果提供了代码:在数据库中搜索具有此类代码的本地帐户 1a。如果找不到用户: 重定向到 reg ui,参数中出现错误混乱: http://yoursite.com/auth?success=false&message="Confirmation 代码不正确,请重试。” 1.b 如果用户发现: 使用新密码提示重定向到 ui 页面并将新代码附加到参数

我没有在上面放任何代码,因此您可以在其他身份验证场景中使用此工作流程。

【讨论】:

以上是关于graphql 服务器电子邮件验证示例的主要内容,如果未能解决你的问题,请参考以下文章

graphql服务器端验证

如何更改验证邮件中`GRAPHQL_AUTH`中的`frontend_domain`端口?

GraphQL 中模式级和应用级错误的混合

Graphql 的登录突变未找到用户

如何从 Nuxt 前端访问经过身份验证的 GraphQL API

jQuery远程验证电子邮件验证服务