与 parse-server 和 auth0 的自定义身份验证集成

Posted

技术标签:

【中文标题】与 parse-server 和 auth0 的自定义身份验证集成【英文标题】:Custom authentication integration with parse-server and auth0 【发布时间】:2016-10-30 09:41:15 【问题描述】:

我想将 auth0.com 与开源解析服务器结合使用。

我目前的方法是通过 ios 的 Lock 库使用标准登录从 auth0 获取令牌。使用该令牌,我想在我的解析服务器上调用自定义身份验证方法,检查令牌是否有效,如果有效,它将登录用户。

我的问题是几乎没有关于为 parse-server 编写自定义 oauth 的文档。

到目前为止,我有这个代码用于我的自定义身份验证。

var Parse = require('parse/node').Parse;

function validateAuthData(authData, options) 
  console.log('validateAuthData()');
  return new Promise((resolve, reject) => 
    try 
      var decoded = jwt.verify(authData.access_token, opions.sharedSecret);
      if (authData.id === decoded.sub) 
        resolve();
      
      throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Unauthorized');
     catch(e) 
      throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, e.message);
    
  );


function validateAppId(appIds, authData) 
  console.log('validateAppId()');
  return Promise.resolve();


module.exports = 
  validateAppId: validateAppId,
  validateAuthData: validateAuthData
;

但是,它不起作用,而且我不明白如何使用此代码对特定用户进行身份验证。解析服务器是否进行数据库查找以将特定身份验证数据与特定用户匹配?另外,如何使用自定义身份验证注册新用户。当用户尝试登录但他在我的解析数据库中尚不存在时会发生什么?

替代方案似乎是this,使用规则 auth0.com。有什么区别以及规则将如何运作?我对身份验证、oauth 和 jwt 的经验很少。

最后,我使用this 从我的 iOS 客户端调用我的自定义身份验证。但是这也不起作用,但我不确定这是由于 iOS 部分还是因为我的自定义身份验证还没有工作。

总之,我在一些看起来相当容易的事情上遇到了麻烦。我想使用 auth0 作为我的身份验证提供程序,并且我想将它集成为解析服务器,因为我非常感谢解析和客户端 sdk 带来的便利。我相当肯定更多人有类似的问题,但是我还没有找到任何关于如何正确执行此操作的明确资源。

更多链接

Parse user authenticated using Auth0 https://auth0.com/blog/2016/03/07/hapijs-authentication-secure-your-api-with-json-web-tokens/ https://github.com/ParsePlatform/parse-server/wiki/OAuth https://jwt.io/introduction/

【问题讨论】:

您是否找到了一个很好的解决方案来解决这个问题?我目前正在努力寻找一种从 macOS 应用程序使用 Google、Facebook 等登录的方法,而不是在我的应用程序中保留消费者密钥和秘密,而是在我的 Parse 服务器上。如果您对此有任何消息,我将不胜感激。 ***.com/questions/45065984/… 【参考方案1】:

迟到的答案,但我正在解决同样的问题并遇到了这篇文章:

Auth0 具有您可以在登录时应用的规则。我已经从https://github.com/auth0/rules/blob/master/src/rules/parse.js 修改了他们的示例之一,将 API 端点提取到一个常量中。

function(user, context, callback) 
  // run this only for the Parse application
  // if (context.clientID !== 'PARSE CLIENT ID IN AUTH0') return callback(null, user, context);

  const request = require('request');

  const MY_API = 'https://subdomian.back4app.io';
  const PARSE_APP_ID = '*********';
  const PARSE_API_KEY = '**********';
  const PARSE_USER_PASSWORD = 'REPLACE_WITH_RANDOM_STRING'; // you can use this to generate one http://www.random.org/strings/

  const username = user.email || user.name || user.user_id; // this is the Auth0 user prop that will be mapped to the username in the db

  request.get(
      url: `$MY_API/login`,
      qs: 
        username: username,
        password: PARSE_USER_PASSWORD
      ,
      headers: 
        'X-Parse-Application-Id': PARSE_APP_ID,
        'X-Parse-REST-API-Key': PARSE_API_KEY
      
    ,
    function(err, response, body) 
      if (err) return callback(err);

      // user was found, add sessionToken to user profile
      if (response.statusCode === 200) 
        context.idToken[`$MY_API/parse_session_token`] = JSON.parse(body).sessionToken;
        return callback(null, user, context);
      

      // Not found. Likely the user doesn't exist, we provision one
      if (response.statusCode === 404) 
        request.post(
            url: `$MY_API/users`,
            json: 
              username: username,
              password: PARSE_USER_PASSWORD
            ,
            headers: 
              'X-Parse-Application-Id': PARSE_APP_ID,
              'X-Parse-REST-API-Key': PARSE_API_KEY,
              'Content-Type': 'application/json'
            
          ,
          function(err, response, body) 
            if (err) return callback(new Error('user already exists'));

            // user created, add sessionToken to user profile
            if (response.statusCode === 201) 
              context.idToken[`$MY_API/parse_session_token`] = body.sessionToken;
              return callback(null, user, context);
            
            return callback(new Error(username + ' The user provisioning returned an unknown error. Body: ' + JSON.stringify(body)));
          );
       else 
        return callback(new Error('The login returned an unknown error. Status: ' + response.statusCode + ' Body: ' + body));
      
    );

我正在用 JS 编写一个 SPA,所以我有一些处理 Auth0 登录的客户端代码,(将“https://subdomian.back4app.io”替换为您自己的解析服务器的 API 地址 - 与上述 Auth0 规则中使用的值相同)。注意Parse.User.become函数,它将Auth0规则中创建的会话id分配给当前解析用户:

handleAuthentication() 
  this.auth0.parseHash((err, authResult) => 
    if (authResult && authResult.accessToken && authResult.idToken) 
      this.setSession(authResult);
      Parse.User.become(authResult.idTokenPayload['https://subdomian.back4app.io/parse_session_token']);
      history.replace('/');
     else if (err) 
      history.replace('/home');
      console.log(err);
    
  );

【讨论】:

以上是关于与 parse-server 和 auth0 的自定义身份验证集成的主要内容,如果未能解决你的问题,请参考以下文章

Auth0 端点 API 的自定义实现?

集成 Auth0 自定义数据库和无密码

从自托管 Parse-Server 转移到 Amazon SNS

Parse-Server后台搭建与使用进阶篇(二)- Parse-server常见问题及解决方法

parse-server:如何区分用户类 BeforeSave 中的 signUp 和常规 ParseUser.save?

将 Parse-Dashboard 与 Parse-Server (Docker-Container) 连接起来