Feathers: 认证下一步

创建于 2018-10-06  ·  10评论  ·  资料来源: feathersjs/feathers

我已经在Feathers Crow 路线图更新中对此进行了一些讨论。 本期旨在收集下一版 Feathers 身份验证将涵盖的所有相关问题。

独立于框架

在当前 (Buzzard) 版本中,Feathers 核心变得完全独立于框架,但是,身份验证插件仍在注册一些 Express 中间件。 在下一个版本中,中间件将移至 @feathersjs/express 并使身份验证核心也独立于框架。 这将允许像 Koa 或 MQTT 这样的新传输。

改进的套接字身份验证

目前,websockets 通过自定义事件机制进行身份验证和注销。 这导致了一些问题(例如,很少出现“无身份验证令牌”错误),尤其是在双方、服务器和客户端的可靠重新连接方面。

改进的身份验证客户端

这将消除对有状态访问令牌的依赖并优雅地处理套接字重新身份验证。

没有更多的 cookie,改进的 oAuth

Feathers 是一个用于创建使用 JWT 进行身份验证的 API 的库。 正常 Feathers 设置使用 cookie 的一个实例是在 oAuth(Facebook、Google 等)身份验证流程之后将 JWT 传递给浏览器。 新的 oAuth 和身份验证客户端将不再使用 cookie 并将 oAuth 流拆分为两部分,而不是尝试一次完成所有操作。 oAuth 访问令牌将设置在跨域友好(仅可本地访问)的 URL 哈希中,然后可以使用 Feathers 标准身份验证机制将其交换为 JWT。

更好的选项处理

现在将在运行时评估所有身份验证设置,因此可以动态设置它们,并且不需要的选项不会出错。 它还允许通过自定义身份验证服务。

刷新令牌和黑名单

标准身份验证服务现在还将返回一个寿命更长的刷新令牌,而不是允许使用现有的 JWT 进行刷新。 令牌黑名单仍然需要手动实现,但通过新的身份验证服务中的方法更容易集成。

Authentication Breaking Change

最有用的评论

您可以在 master 分支中查看当前的进度,当 beta 测试人员可以尝试时,我会发布一篇博文。 状态是:

| 模块 | 代码 | 文档 | 命令行界面
| --- |:---:|:---:|---:|
| @feathersjs/认证| ✅| 100% | ❌|
| @feathersjs/authentication-local | ✅ | 80% | ❌|
| @featherjs/authentication-oauth | ✅| 90%| ❌|
| @feathersjs/authentication-client | ✅ | 80%| ❌|

所有10条评论

弃用护照

此讨论始于 #844,并在https://github.com/feathersjs/feathers/issues/844#issuecomment -390123148 中总结了发生这种情况的原因。 简而言之,PassportJS 并没有太多的发展,尤其是围绕 Express 以外的支持框架,大多数其他 HTTP 框架(如 Koa 或 Hapi)转而使用更灵活和简约的身份验证库(如 https://github.com/simov/grant oAuth)。 事实证明,真正需要的策略只有四种:

  • 本地(用户名/密码)
  • 智威汤逊
  • oAuth(+ oAuth 访问令牌)
  • API 密钥

无需处理 Passport,Feathers 可以轻松地置于任何 HTTP 库和任何其他传输机制(如 MQTT 甚至 P2P 连接)之上,并具有明确的关注点分离,并提供更易于理解和定制的身份验证机制。

使用params.authentication

在 Feathers 方面,在服务调用中设置params.authentication将是_唯一_提供身份验证信息的方式。 params.authentication将包含验证服务调用所需的信息,格式为{ strategy: 'local', email: 'email', password: 'password' }已被使用:

// Call `find` with a given JWT
app.service('messages').find({
  authentication: {
    strategy: 'jwt',
    accessToken: 'someJWT'
  }
});

调用者(如 REST 或 websocket 传输、钩子或单元测试)将负责传递params.authentication 。 这意味着authenticate钩子是否为内部调用运行或身份验证信息实际来自何处,将不会再出现混淆。

authenticate钩子

authenticate钩子将继续存在。 它将需要一个策略名称列表,并且将

  • 使用第一个没有抛出错误的策略继续下一个钩子并将其返回值(见下文)合并到params
  • 或者如果所有策略都失败,则抛出第一个失败的策略的错误

    如果params.authentication包含strategy名称,则只会调用该策略。 否则将调用所有策略。 如果params.authentication根本没有设置,钩子会

  • 为外部调用抛出错误

  • 像往常一样继续内部呼叫(例如手动设置params.user
app.service('messages').hooks({
  before: authenticate('jwt', 'local', 'anonymous')
});

认证策略

一个基本的认证策略是一个带有authenticate方法的对象,该方法获取params.authentication并返回一个成功对象,如果不成功则抛出错误:

const { Forbidden } = require('@feathersjs/errors');

const daveStrategy = {
  async authenticate (authParams) {
    const { username, password } = authParams;

    if (username === 'david' && password === 'secret') {
      return {
        user: {
          name: 'Dave',
          admin: true
        }
      };
    }

    throw new Forbidden('Not super Dave');
  }
};

app.authentication.registerStrategy('superdave', daveStrategy);

authenticate挂钩中,返回的对象将合并到服务调用params因此本示例将设置params.user

扩展策略

身份验证策略可以在内部包含和调用其他方法。 Feathers 策略将实现为可以通过扩展自定义的类(这将取代 Verifiers 并基本上将策略和验证器合并为一个类):

class LocalStrategy {
  constructor(app);
  async findUser(authParams);
  async comparePassword(user, password);
  async authenticate (authParams);
}

class MyLocalStrategy extends LocalStrategy {
  async findUser(authParams);
}

app.authentication.registerStrategy('local', new MyLocalStrategy(app));

HTTP 解析

策略还可以提供parse方法,该方法将获得基本的 Node HTTP 请求和响应,并应返回params.authentication (或null )的值:

const daveStrategy = {
  async authenticate (authParams) {
    throw new Forbidden('Not super Dave');
  }

  async parse (req, res) {
    const apiKey = req.headers['x-super-dave'];

    if (apiKey) {
      return {
        strategy: 'superdave',
        apiKey
      }
    }

    return null;
  }
};

然后 HTTP 库可以决定是否以及如何使用这些方法来设置params.authentication或验证自己的中间件。

app.authenticate

app.authenticate(authParams, [ strategies ])将使用给定的身份验证参数运行给定的策略:

// Will return the user for a JWT (on the server)
const { user } = app.authenticate({ accessToken }, 'jwt');

在服务调用中设置params.authentication将是提供身份验证信息的 _only_ 方式。

您能否详细说明为什么需要在每次service()调用时提供accessToken的设计要点?

这仅适用于服务器,并且是通过params.providerparams.headers (在 websockets 的情况下,这只是假标头)隐式发生的事情,一旦配置了身份验证,它们就会为每个服务调用设置。 这打破了 Feathers 将独立于传输协议的钩子和服务与实际传输机制(如 HTTP with Express 或 Socket.io)之间的分离,并在authenticate('jwt')钩子实际运行及其用途时变得非常混乱其认证信息。

可用性方面,外部或内部调用不会真正改变,但如果您现在想在服务器上显式触发authenticate挂钩,您始终可以设置params.authentication 。 这对于 Express 以外的新框架插件(例如 Koa、HTTP2 或消息队列)尤其重要,这些插件现在具有将其身份验证信息传递给 Feathers 身份验证机制的标准化方法。

一旦通过调用app.authenticate()登录,身份验证客户端仍将发出经过身份验证的请求。

谢谢澄清。 非常期待使用 v3 进行测试,尤其是使用 socket.io React Native 客户端。

肯定会把关于预发布的信息放在这里。 只需包装身份验证客户端,它应该更可靠地处理经过身份验证的 websocket。 完成后,如果有一些帮助测试新的核心​​ + 本地和 jwt 身份验证,那就太好了。 oAuth 应该很快就会跟进。

版本3什么时候出来?

对我的问题有任何回应吗?

您可以在 master 分支中查看当前的进度,当 beta 测试人员可以尝试时,我会发布一篇博文。 状态是:

| 模块 | 代码 | 文档 | 命令行界面
| --- |:---:|:---:|---:|
| @feathersjs/认证| ✅| 100% | ❌|
| @feathersjs/authentication-local | ✅ | 80% | ❌|
| @featherjs/authentication-oauth | ✅| 90%| ❌|
| @feathersjs/authentication-client | ✅ | 80%| ❌|

嗨,这太棒了!

未来的灵活性很酷,但我对 FeathersJS 项目中的 auth 还没有信心,我正在经历一个令人困惑的过程来创建它。

拥有完整、经过测试且安全的身份验证实施意味着我可以自信地继续使用功能。 使用 MeteorJS 的最佳理由之一是它对客户端的出色帐户集成。

查看 FeatherJS 问题,很多都与身份验证有关,所以我很高兴这项工作能够落地!

目前 FeathersJS 中完整的安全身份验证系统(本地身份验证、访问控制、电子邮件等)的最佳文档(或参考实现)在哪里?

这就是我到目前为止所拥有的 - 还有什么更好的吗?

2018/02 - 在 FeathersJS 中设置电子邮件验证(2017 年文章的 rehash)
2018/02 - 以上文章的回购
2017/01 - 如何在 FeathersJS 中设置电子邮件验证(已损坏)
2018/06 - 使用 Feathersjs 进行 Vue 身份验证

提前致谢!

现在所有相关问题都已关闭,Feathers v4 的预发布版以及所有已实施的更改建议可供测试。 有关更多信息,请参阅迁移指南

此页面是否有帮助?
0 / 5 - 0 等级

相关问题

arkenstan picture arkenstan  ·  3评论

arve0 picture arve0  ·  4评论

RickEyre picture RickEyre  ·  4评论

huytran0605 picture huytran0605  ·  3评论

jordanbtucker picture jordanbtucker  ·  4评论