Feathers: Próxima autenticação

Criado em 6 out. 2018  ·  10Comentários  ·  Fonte: feathersjs/feathers

Eu já escrevi sobre isso na atualização do roteiro do

Estrutura independente

Com o lançamento atual (Buzzard), o núcleo do Feathers tornou-se totalmente independente do framework, no entanto, o plug-in de autenticação ainda está registrando algum middleware Express. Na próxima versão, esse middleware será movido para @ penasjs / express e tornará o núcleo de autenticação também independente do framework. Isso permitirá novos transportes como Koa ou MQTT.

Autenticação de soquete aprimorada

Atualmente, os websockets são autenticados e desconectados por meio de um mecanismo de evento personalizado. Isso estava causando alguns problemas (por exemplo, erros raros de “nenhum token de autenticação”), especialmente em relação à reconexão confiável em ambos os lados, o servidor e o cliente.

Cliente de autenticação aprimorado

Isso removerá a dependência do token de acesso com preservação de estado e manipulará a reautenticação de soquete.

Chega de cookies, oAuth melhorado

Feathers é uma biblioteca para criar APIs usando JWT para autenticação. A única instância em que uma configuração normal do Feathers usa cookies é para passar o JWT para o navegador após um fluxo de autenticação oAuth (Facebook, Google etc.). O novo oAuth e o cliente de autenticação não usarão mais cookies e dividirão o fluxo de oAuth em duas partes, em vez de tentar fazer tudo de uma vez. O token de acesso oAuth será definido em um hash de URL amigável entre domínios (acessível apenas localmente), que pode então ser trocado por um JWT usando o mecanismo de autenticação padrão Feathers.

Melhor manuseio de opções

Todas as configurações de autenticação agora serão avaliadas em tempo de execução para que seja possível defini-las dinamicamente e não haverá erros para opções que não são necessárias. Também permitirá a passagem de um serviço de autenticação personalizado.

Atualizar tokens e lista negra

Em vez de permitir a atualização com o JWT existente, o serviço de autenticação padrão agora também retornará um token de atualização de vida mais longa. A lista negra de tokens ainda precisa ser implementada manualmente, mas será mais fácil de integrar por meio dos métodos do novo serviço de autenticação.

Authentication Breaking Change

Comentários muito úteis

Você pode ver o progresso atual no branch master e colocarei uma postagem no blog quando os testadores beta puderem testá-lo. O status é:

| Módulo | Código | Docs | CLI
| --- |: ---: |: ---: | ---: |
| @ penasjs / autenticação | ✅ | 100% | ❌ |
| @ penasjs / autenticação-local | ✅ | 80% | ❌ |
| @ featherjs / authentication-oauth | ✅ | 90% | ❌ |
| @ penasjs / cliente de autenticação | ✅ | 80% | ❌ |

Todos 10 comentários

Obsoletar passaporte

Esta discussão começou em # 844 e em https://github.com/feathersjs/feathers/issues/844#issuecomment -390123148 ​​resume os pontos por que isso está acontecendo. Em suma, não houve muito desenvolvimento no PassportJS, especialmente em torno de estruturas de suporte diferentes do Express e a maioria das outras estruturas HTTP, como Koa ou Hapi, passaram a usar bibliotecas de autenticação mais flexíveis e minimalistas (como https://github.com/simov/grant para oAuth). Também descobrimos que existem apenas quatro tipos de estratégias realmente necessárias:

  • Local (nome de usuário / senha)
  • JWT
  • oAuth (+ token de acesso oAuth)
  • Chave API

Sem ter que contornar o Passport, o Feathers pode facilmente sentar em cima de qualquer biblioteca HTTP e qualquer outro mecanismo de transporte (como MQTT ou mesmo conexões P2P) com uma separação clara de interesses e fornecer um mecanismo de autenticação que é muito mais fácil de entender e personalizar.

Usando params.authentication

Do lado do Feathers, definir params.authentication em uma chamada de serviço será a _única_ maneira de fornecer informações de autenticação. params.authentication conterá as informações necessárias para autenticar a chamada de serviço e estará no formato de, por exemplo, { strategy: 'local', email: 'email', password: 'password' } que já está sendo usado:

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

O chamador (como um REST ou transporte de websocket, um gancho ou um teste de unidade) será responsável por passar params.authentication . Isso significa que não haverá mais confusão se o gancho authenticate for executado para chamadas internas ou não ou de onde as informações de autenticação estão realmente vindo.

O gancho authenticate

O gancho authenticate continuará existindo. Levará uma lista de nomes de estratégias e também

  • Continue para o próximo gancho com a primeira estratégia que não gerou um erro e mescle seu valor de retorno (veja abaixo) em params
  • Ou lance o erro da primeira estratégia que falhou se todas as estratégias falharam

    Se params.authentication contiver um strategy name, apenas essa estratégia será chamada. Caso contrário, todas as estratégias serão chamadas. Se params.authentication não for definido, o gancho irá

  • Lançar um erro para chamadas externas

  • Continue como de costume para chamadas internas (por exemplo, ao definir params.user manualmente)
app.service('messages').hooks({
  before: authenticate('jwt', 'local', 'anonymous')
});

Estratégias de autenticação

Uma estratégia de autenticação básica é um objeto com um método authenticate que obtém os dados de params.authentication e retorna um objeto de sucesso ou lança um erro se não foi bem-sucedido:

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);

No gancho authenticate , o objeto retornado será mesclado na chamada de serviço params portanto, este exemplo definiria params.user .

Estendendo estratégias

As estratégias de autenticação podem conter e chamar métodos adicionais internamente. As estratégias de penas serão implementadas como classes que podem ser personalizadas por meio de extensão (isso substituirá os verificadores e basicamente combina a estratégia e o verificador em uma única classe):

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));

Análise de HTTP

Uma estratégia também pode fornecer um método parse que obterá uma solicitação e resposta HTTP do nó básico e deve retornar o valor de params.authentication (ou 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;
  }
};

As bibliotecas HTTP podem então decidir se e como usar esses métodos para definir params.authentication ou autenticar seu próprio middleware.

app.authenticate

app.authenticate(authParams, [ strategies ]) executará as estratégias fornecidas com os parâmetros de autenticação fornecidos:

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

definir params.authentication em uma chamada de serviço será a _única_ maneira de fornecer informações de autenticação.

Você poderia examinar os pontos de design sobre por que foi necessário fornecer accessToken em cada service() chamada?

Isso se aplica apenas ao servidor e é o que implicitamente já acontece por meio de params.provider e params.headers (no caso de websockets, são apenas cabeçalhos falsos) que são definidos para cada chamada de serviço uma vez que a autenticação é configurada. Isso estava quebrando a separação do Feathers entre os ganchos e serviços independentes do protocolo de transporte e o mecanismo de transporte real (como HTTP com Express ou Socket.io) e tornou muito confuso quando, por exemplo, um gancho authenticate('jwt') realmente é executado e para que serve suas informações de autenticação.

Em termos de usabilidade, nada vai realmente mudar para chamadas externas ou internas, mas se agora você deseja acionar o gancho authenticate explicitamente no servidor, você sempre pode definir params.authentication . Isso é especialmente importante para novos plug-ins de estrutura diferentes do Express (por exemplo, Koa, HTTP2 ou uma fila de mensagens), que agora têm uma maneira padronizada de passar suas informações de autenticação para o mecanismo de autenticação Feathers.

O cliente de autenticação ainda fará solicitações autenticadas, uma vez que tenha sido logado, chamando app.authenticate() .

Obrigado por esclarecer. Estou ansioso para testar a v3, especialmente com os clientes nativos socket.io React.

Com certeza colocarei as informações sobre os pré-lançamentos aqui. Basta encerrar o cliente de autenticação que deve lidar com websockets autenticados de forma muito mais confiável. Uma vez feito isso, seria ótimo ter alguma ajuda para testar o novo núcleo + autenticação local e jwt. oAuth deve vir logo depois disso.

quando a versão 3 for lançada?

Alguma resposta à minha pergunta?

Você pode ver o progresso atual no branch master e colocarei uma postagem no blog quando os testadores beta puderem testá-lo. O status é:

| Módulo | Código | Docs | CLI
| --- |: ---: |: ---: | ---: |
| @ penasjs / autenticação | ✅ | 100% | ❌ |
| @ penasjs / autenticação-local | ✅ | 80% | ❌ |
| @ featherjs / authentication-oauth | ✅ | 90% | ❌ |
| @ penasjs / cliente de autenticação | ✅ | 80% | ❌ |

Oi, isso é ótimo!

Flexibilidade futura é legal, mas eu não tenho confiança no auth no meu projeto FeathersJS ainda e estou passando por um processo confuso para criá-lo.

Ter uma implementação de autenticação completa, testada e segura significa que posso passar com segurança para os recursos. Uma das melhores razões para usar o MeteorJS foi sua excelente integração de contas em todo o caminho até o cliente.

Analisando os problemas do FeatherJS, muitos são sobre autenticação, então estou animado para que este trabalho chegue!

Onde está a melhor documentação (ou implementação de referência) para um sistema de autenticação seguro completo (autenticação local, controle de acesso, e-mails, etc) no FeathersJS hoje?

Isso é o que eu tenho até agora - há algo melhor?

02/2018 - Configurando a verificação de e-mail no FeathersJS (revisão do artigo de 2017)
02/2018 - Repo do artigo acima
2017/01 - Como configurar a verificação de e-mail no FeathersJS (quebrado)
06 2018 - Autenticação Vue com Feathersjs

Desde já, obrigado!

Todos os problemas relacionados foram encerrados e o pré-lançamento do Feathers v4 com todas as alterações propostas implementadas está disponível para teste. Consulte o guia de migração para obter mais informações.

Esta página foi útil?
0 / 5 - 0 avaliações

Questões relacionadas

rstegg picture rstegg  ·  3Comentários

perminder-klair picture perminder-klair  ·  3Comentários

codeus-de picture codeus-de  ·  4Comentários

RickEyre picture RickEyre  ·  4Comentários

eric-burel picture eric-burel  ·  3Comentários