Next.js: Adicionar exemplo de login / autenticação

Criado em 29 out. 2016  ¬∑  208Coment√°rios  ¬∑  Fonte: vercel/next.js

Com:

  • auxiliar de autentica√ß√£o reutiliz√°vel em todas as p√°ginas
  • sincroniza√ß√£o de sess√£o entre guias
  • back-end de e-mail simples sem senha hospedado em now.sh

Acho que isso ser√° extremamente √ļtil para muitos novatos.

p0

Coment√°rios muito √ļteis

Ent√£o, eu tenho auth funcionando perfeitamente. Conforme mencionado em outro lugar, √© apenas do lado do cliente, o que, em √ļltima an√°lise, √© apenas metade da batalha.

"Bastante seguro"

Como o php, a unidade at√īmica do Next √© a p√°gina. Um dos recursos mais legais √© que ele carrega lentamente cada p√°gina apenas quando solicitado. Com autentica√ß√£o apenas do lado do cliente, mas com renderiza√ß√£o do servidor, o js para aquela p√°gina protegida √© de fato baixado pelo navegador. No futuro, quando o Next adicionar fluxos de trabalho do servidor, voc√™ poder√° bloquear a renderiza√ß√£o e redirecionar no servidor para evitar isso completamente. Isso exigir√° cookies, sess√Ķes e armazenamentos de sess√£o AFAIK, mas esse √© apenas o custo de fazer aplicativos h√≠bridos como esses.

Exemplo de autenticação

Suponha que voc√™ tenha uma API protegida por JWT com dois pontos de extremidade de interesse: /token e /me . /token aceita credenciais de e-mail / senha e retorna um JWT assinado ( id_token ), enquanto /me retorna informa√ß√Ķes de perfil relacionadas ao usu√°rio autenticado pelo JWT. Eu adaptei o seguinte AuthService.js do bloqueio do Auth0 (removendo o emissor de evento, embora essa n√£o seja a pior ideia). Ele extrai quase todo o manuseio do token JWT para que possa ser usado na p√°gina de login e tamb√©m em um componente de ordem superior (mais sobre isso posteriormente).

// utils/AuthService.js
export default class AuthService {
  constructor(domain) {
    this.domain = domain || 'http://localhost:5000'
    this.fetch = this.fetch.bind(this)
    this.login = this.login.bind(this)
    this.getProfile = this.getProfile.bind(this)
  }

  login(email, password) {
    // Get a token
    return this.fetch(`${this.domain}/token`, {
      method: 'POST',
      body: JSON.stringify({
        email,
        password
      })
    }).then(res => {
      this.setToken(res.id_token)
      return this.fetch(`${this.domain}/user`, {
        method: 'GET'
      })
    }).then(res => {
      this.setProfile(res)
      return Promise.resolve(res)
    })
  }

  loggedIn(){
    // Checks if there is a saved token and it's still valid
    const token = this.getToken()
    return !!token && !isTokenExpired(token) // handwaiving here
  }

  setProfile(profile){
    // Saves profile data to localStorage
    localStorage.setItem('profile', JSON.stringify(profile))
  }

  getProfile(){
    // Retrieves the profile data from localStorage
    const profile = localStorage.getItem('profile')
    return profile ? JSON.parse(localStorage.profile) : {}
  }

  setToken(idToken){
    // Saves user token to localStorage
    localStorage.setItem('id_token', idToken)
  }

  getToken(){
    // Retrieves the user token from localStorage
    return localStorage.getItem('id_token')
  }

  logout(){
    // Clear user token and profile data from localStorage
    localStorage.removeItem('id_token');
    localStorage.removeItem('profile');
  }

  _checkStatus(response) {
    // raises an error in case response status is not a success
    if (response.status >= 200 && response.status < 300) {
      return response
    } else {
      var error = new Error(response.statusText)
      error.response = response
      throw error
    }
  }

  fetch(url, options){
    // performs api calls sending the required authentication headers
    const headers = {
      'Accept': 'application/json',
      'Content-Type': 'application/json'
    }

    if (this.loggedIn()){
      headers['Authorization'] = 'Bearer ' + this.getToken()
    }

    return fetch(url, {
      headers,
      ...options
    })
    .then(this._checkStatus)
    .then(response => response.json())
  }
}

O pr√≥ximo passo √© um HOC para simplificar a prote√ß√£o das p√°ginas. Para evitar um flash indesejado de informa√ß√Ķes confidenciais, a p√°gina renderizar√° Loading... no servidor na primeira renderiza√ß√£o enquanto o react inicializa / l√™ o token de localStorage. Isso significa que as p√°ginas protegidas n√£o far√£o o SEO, o que provavelmente est√° bom a partir de agora, mas definitivamente n√£o √© o ideal.

// utils/withAuth.js - a HOC for protected pages
import React, {Component} from 'react'
import AuthService from './auth'

export default function withAuth(AuthComponent) {
    const Auth = new AuthService('http://localhost:5000')
    return class Authenticated extends Component {
      constructor(props) {
        super(props)
        this.state = {
          isLoading: true
        };
      }

      componentDidMount () {
        if (!Auth.loggedIn()) {
          this.props.url.replaceTo('/')
        }
        this.setState({ isLoading: false })
      }

      render() {
        return (
          <div>
          {this.state.isLoading ? (
              <div>LOADING....</div>
            ) : (
              <AuthComponent {...this.props}  auth={Auth} />
            )}
          </div>
        )
      }
    }
}
// ./pages/dashboard.js
// example of a protected page
import React from 'react'
import withAuth from  '../utils/withAuth'

class Dashboard extends Component {
   render() {
     const user = this.props.auth.getProfile()
     return (   
         <div>Current user: {user.email}</div>
     )
   }
}

export default withAuth(Dashboard) 

A p√°gina de login n√£o pode usar o HOC como est√° agora, porque o login precisa ser p√ļblico. Portanto, ele apenas cria uma inst√Ęncia de AuthService diretamente. Voc√™ faria algo semelhante para uma p√°gina de inscri√ß√£o tamb√©m.

// ./pages/login.js
import React, {Component} from 'react'
import AuthService from '../utils/AuthService'

const auth = new AuthService('http://localhost:5000')

class Login extends Component {
  constructor(props) {
    super(props)
    this.handleSubmit = this.handleSubmit.bind(this)
  }

  componentDidMount () {
    if (auth.loggedIn()) {
      this.props.url.replaceTo('/admin')   // redirect if you're already logged in
    }
  }

  handleSubmit (e) {
    e.preventDefault()
    // yay uncontrolled forms!
    auth.login(this.refs.email.value, this.refs.password.value)
      .then(res => {
        console.log(res)
        this.props.url.replaceTo('/admin')
      })
      .catch(e => console.log(e))  // you would show/hide error messages with component state here 
  }

  render () {
    return (
      <div>
         Login
          <form onSubmit={this.handleSubmit} >
            <input type="text" ref="email"/>
            <input type="password" ref="password"/>
            <input type="submit" value="Submit"/>
          </form>
      </div>
    )
  }
}

export default Login

Inspirado pelos estilos de reação do Airbnb, também comecei a trabalhar em um next-with-auth lib, que seria uma função retorna um HOC para ser usado nas páginas. Também joguei com a fusão de AuthService e este HOC. Uma solução pode ser fazer este HOC aceitar uma função de nível de permissão como um argumento além do componente, como redux connect. Independentemente disso, em minha mente, você usaria next-with-auth assim:

// ./utils/withAuth.js
import nextAuth from 'next/auth'
import parseScopes from './parseScopes'

const Loading = () => <div>Loading...</div>

export default nextAuth({
  url: 'http://localhost:5000',
  tokenEndpoint: '/api/token',
  profileEndpoint: '/api/me',
  getTokenFromResponse: (res) => res.id_token,
  getProfileFromResponse: (res) => res,
  parseScopes,
})

Fazer tudo isso com o Redux parecia desnecessariamente complicado, mas basicamente voc√™ pode seguir o exemplo do wiki, mas mover AuthService para Actions (login e logout) e ter um redutor de usu√°rio. Voc√™ s√≥ pode chamar essas a√ß√Ķes no cliente, j√° que n√£o h√° localStorage no servidor, ent√£o voc√™ precisa verificar isso em suas A√ß√Ķes. Em √ļltima an√°lise, a loja redux √© colocada em window qualquer maneira. Portanto, voc√™ poderia simplesmente armazenar em cache o usu√°rio em window por conta pr√≥pria em vez de usar o contexto. Se voc√™ n√£o quiser redux, tamb√©m pode experimentar react-broadcast .

Por √ļltimo, supondo que next/server enviado de acordo com o item # 25. next-with-auth poderia abstrair o localStorage vs. cookie do desenvolvedor com middleware + um HOC. Ele tamb√©m pode lidar com a atualiza√ß√£o de tokens.

Todos 208 coment√°rios

Sugest√£o: Use Redux e JWT para realizar o exemplo

Estou trabalhando em um exemplo para isso. Atualmente tendo problemas para fazer o componentWillReceiveProps disparar no meu componente de alto nível (onde estou planejando verificar se o usuário está autenticado e redirecionar para a página de login, caso não esteja)

Ent√£o, eu tenho auth funcionando perfeitamente. Conforme mencionado em outro lugar, √© apenas do lado do cliente, o que, em √ļltima an√°lise, √© apenas metade da batalha.

"Bastante seguro"

Como o php, a unidade at√īmica do Next √© a p√°gina. Um dos recursos mais legais √© que ele carrega lentamente cada p√°gina apenas quando solicitado. Com autentica√ß√£o apenas do lado do cliente, mas com renderiza√ß√£o do servidor, o js para aquela p√°gina protegida √© de fato baixado pelo navegador. No futuro, quando o Next adicionar fluxos de trabalho do servidor, voc√™ poder√° bloquear a renderiza√ß√£o e redirecionar no servidor para evitar isso completamente. Isso exigir√° cookies, sess√Ķes e armazenamentos de sess√£o AFAIK, mas esse √© apenas o custo de fazer aplicativos h√≠bridos como esses.

Exemplo de autenticação

Suponha que voc√™ tenha uma API protegida por JWT com dois pontos de extremidade de interesse: /token e /me . /token aceita credenciais de e-mail / senha e retorna um JWT assinado ( id_token ), enquanto /me retorna informa√ß√Ķes de perfil relacionadas ao usu√°rio autenticado pelo JWT. Eu adaptei o seguinte AuthService.js do bloqueio do Auth0 (removendo o emissor de evento, embora essa n√£o seja a pior ideia). Ele extrai quase todo o manuseio do token JWT para que possa ser usado na p√°gina de login e tamb√©m em um componente de ordem superior (mais sobre isso posteriormente).

// utils/AuthService.js
export default class AuthService {
  constructor(domain) {
    this.domain = domain || 'http://localhost:5000'
    this.fetch = this.fetch.bind(this)
    this.login = this.login.bind(this)
    this.getProfile = this.getProfile.bind(this)
  }

  login(email, password) {
    // Get a token
    return this.fetch(`${this.domain}/token`, {
      method: 'POST',
      body: JSON.stringify({
        email,
        password
      })
    }).then(res => {
      this.setToken(res.id_token)
      return this.fetch(`${this.domain}/user`, {
        method: 'GET'
      })
    }).then(res => {
      this.setProfile(res)
      return Promise.resolve(res)
    })
  }

  loggedIn(){
    // Checks if there is a saved token and it's still valid
    const token = this.getToken()
    return !!token && !isTokenExpired(token) // handwaiving here
  }

  setProfile(profile){
    // Saves profile data to localStorage
    localStorage.setItem('profile', JSON.stringify(profile))
  }

  getProfile(){
    // Retrieves the profile data from localStorage
    const profile = localStorage.getItem('profile')
    return profile ? JSON.parse(localStorage.profile) : {}
  }

  setToken(idToken){
    // Saves user token to localStorage
    localStorage.setItem('id_token', idToken)
  }

  getToken(){
    // Retrieves the user token from localStorage
    return localStorage.getItem('id_token')
  }

  logout(){
    // Clear user token and profile data from localStorage
    localStorage.removeItem('id_token');
    localStorage.removeItem('profile');
  }

  _checkStatus(response) {
    // raises an error in case response status is not a success
    if (response.status >= 200 && response.status < 300) {
      return response
    } else {
      var error = new Error(response.statusText)
      error.response = response
      throw error
    }
  }

  fetch(url, options){
    // performs api calls sending the required authentication headers
    const headers = {
      'Accept': 'application/json',
      'Content-Type': 'application/json'
    }

    if (this.loggedIn()){
      headers['Authorization'] = 'Bearer ' + this.getToken()
    }

    return fetch(url, {
      headers,
      ...options
    })
    .then(this._checkStatus)
    .then(response => response.json())
  }
}

O pr√≥ximo passo √© um HOC para simplificar a prote√ß√£o das p√°ginas. Para evitar um flash indesejado de informa√ß√Ķes confidenciais, a p√°gina renderizar√° Loading... no servidor na primeira renderiza√ß√£o enquanto o react inicializa / l√™ o token de localStorage. Isso significa que as p√°ginas protegidas n√£o far√£o o SEO, o que provavelmente est√° bom a partir de agora, mas definitivamente n√£o √© o ideal.

// utils/withAuth.js - a HOC for protected pages
import React, {Component} from 'react'
import AuthService from './auth'

export default function withAuth(AuthComponent) {
    const Auth = new AuthService('http://localhost:5000')
    return class Authenticated extends Component {
      constructor(props) {
        super(props)
        this.state = {
          isLoading: true
        };
      }

      componentDidMount () {
        if (!Auth.loggedIn()) {
          this.props.url.replaceTo('/')
        }
        this.setState({ isLoading: false })
      }

      render() {
        return (
          <div>
          {this.state.isLoading ? (
              <div>LOADING....</div>
            ) : (
              <AuthComponent {...this.props}  auth={Auth} />
            )}
          </div>
        )
      }
    }
}
// ./pages/dashboard.js
// example of a protected page
import React from 'react'
import withAuth from  '../utils/withAuth'

class Dashboard extends Component {
   render() {
     const user = this.props.auth.getProfile()
     return (   
         <div>Current user: {user.email}</div>
     )
   }
}

export default withAuth(Dashboard) 

A p√°gina de login n√£o pode usar o HOC como est√° agora, porque o login precisa ser p√ļblico. Portanto, ele apenas cria uma inst√Ęncia de AuthService diretamente. Voc√™ faria algo semelhante para uma p√°gina de inscri√ß√£o tamb√©m.

// ./pages/login.js
import React, {Component} from 'react'
import AuthService from '../utils/AuthService'

const auth = new AuthService('http://localhost:5000')

class Login extends Component {
  constructor(props) {
    super(props)
    this.handleSubmit = this.handleSubmit.bind(this)
  }

  componentDidMount () {
    if (auth.loggedIn()) {
      this.props.url.replaceTo('/admin')   // redirect if you're already logged in
    }
  }

  handleSubmit (e) {
    e.preventDefault()
    // yay uncontrolled forms!
    auth.login(this.refs.email.value, this.refs.password.value)
      .then(res => {
        console.log(res)
        this.props.url.replaceTo('/admin')
      })
      .catch(e => console.log(e))  // you would show/hide error messages with component state here 
  }

  render () {
    return (
      <div>
         Login
          <form onSubmit={this.handleSubmit} >
            <input type="text" ref="email"/>
            <input type="password" ref="password"/>
            <input type="submit" value="Submit"/>
          </form>
      </div>
    )
  }
}

export default Login

Inspirado pelos estilos de reação do Airbnb, também comecei a trabalhar em um next-with-auth lib, que seria uma função retorna um HOC para ser usado nas páginas. Também joguei com a fusão de AuthService e este HOC. Uma solução pode ser fazer este HOC aceitar uma função de nível de permissão como um argumento além do componente, como redux connect. Independentemente disso, em minha mente, você usaria next-with-auth assim:

// ./utils/withAuth.js
import nextAuth from 'next/auth'
import parseScopes from './parseScopes'

const Loading = () => <div>Loading...</div>

export default nextAuth({
  url: 'http://localhost:5000',
  tokenEndpoint: '/api/token',
  profileEndpoint: '/api/me',
  getTokenFromResponse: (res) => res.id_token,
  getProfileFromResponse: (res) => res,
  parseScopes,
})

Fazer tudo isso com o Redux parecia desnecessariamente complicado, mas basicamente voc√™ pode seguir o exemplo do wiki, mas mover AuthService para Actions (login e logout) e ter um redutor de usu√°rio. Voc√™ s√≥ pode chamar essas a√ß√Ķes no cliente, j√° que n√£o h√° localStorage no servidor, ent√£o voc√™ precisa verificar isso em suas A√ß√Ķes. Em √ļltima an√°lise, a loja redux √© colocada em window qualquer maneira. Portanto, voc√™ poderia simplesmente armazenar em cache o usu√°rio em window por conta pr√≥pria em vez de usar o contexto. Se voc√™ n√£o quiser redux, tamb√©m pode experimentar react-broadcast .

Por √ļltimo, supondo que next/server enviado de acordo com o item # 25. next-with-auth poderia abstrair o localStorage vs. cookie do desenvolvedor com middleware + um HOC. Ele tamb√©m pode lidar com a atualiza√ß√£o de tokens.

Estou ansioso para experimentar! Obrigado pela implementação barebones :)

@jaredpalmer Estou trabalhando em algo semelhante. Como seu AuthService funciona quando um componente é renderizado no lado do servidor? O servidor precisaria acessar o JWT, mas não pode lê-lo do armazenamento local.

@amccloud Não. Esse é todo o problema. O HOC renderiza <div>Loading..</div> em rotas protegidas e deve ler o token e decidir se deve ou não redirecionar em componentDidMount . Para que funcione da maneira que você deseja e renderize do lado do servidor, o Next precisa de # 25, ou pelo menos a capacidade de definir um cookie com o valor do JWT AFAIK.

Eu usei o cookie-js para definir um cookie, mas é um pouco hack ..
a questão é: se você não enviar um cookie, você perderá todos os benefícios do nextjs e da renderização do lado do servidor em rotas autenticadas

@jaredpalmer isso é ótimo! obrigado pelo esforço. Vou tentar terminar de implementar seu exemplo (ou ajudá-lo a fazer isso se quiser) nos próximos dias

Ei! Publiquei um exemplo com nextjs e auth0 aqui: https://github.com/luisrudge/next.js-auth0
Tem o conceito de layout principal e tamb√©m de ‚Äúp√°ginas seguras‚ÄĚ que carregam apenas quando o usu√°rio √© autenticado.
Deixe-me saber o que voc√™ acha ūüéČ

@luisrudge incr√≠vel. Estou clonando e fazendo algumas altera√ß√Ķes, mas parece √≥timo

Legal! O que você acha que está faltando? Que mudanças você está pensando?

No domingo, 6 de novembro de 2016 √†s 13h12 -0200, "Dan Zajdband" < [email protected] [email protected] > escreveu:

@luisr udgehttps: //github.com/luisrudge incr√≠vel. Estou clonando e fazendo algumas altera√ß√Ķes, mas parece √≥timo

Você está recebendo isso porque foi mencionado.
Responda a este e-mail diretamente, visualize-o em Gi tHubhttps: //github.com/zeit/next.js/issues/153#issuecomment -258687108 ou silencie o th readhttps: //github.com/notifications/unsubscribe-auth/ AA5cE8NIsvQ_ITjc1gArTFgNXzEda4TSks5q7e5NgaJpZM4KkJmi.

1) Usando standard para linting (portanto, é consistente com tudo o que estamos construindo a seguir)
2) Adicionando suporte multi-aba solicitado por @rauchg
3) A parte css pode ser simplificada

Eu vou te enviar um pr :)

O que você quer dizer com suporte a várias guias?

No domingo, 6 de novembro de 2016 √†s 13h16 -0200, "Dan Zajdband" < [email protected] [email protected] > escreveu:

1) Usar padrão para linting (portanto, é consistente com tudo o que estamos construindo a seguir)
2) Adicionando suporte a v√°rias guias solicitado por @rauchghttps : //github.com/rauchg
3) A parte css pode ser simplificada

Eu vou te enviar um pr :)

Você está recebendo isso porque foi mencionado.
Responda a este e-mail diretamente, visualize-o em Gi tHubhttps: //github.com/zeit/next.js/issues/153#issuecomment -258687373 ou silencie o th readhttps: //github.com/notifications/unsubscribe-auth/ AA5cE1A6jq4KZc9_ynukTCI4mU-rdsNaks5q7e81gaJpZM4KkJmi.

Você tem 2 guias abertas, logout em 1, efetua logout automaticamente na outra

Ahh. Isso é muito legal!

No domingo, 6 de novembro de 2016 √†s 13h21 -0200, "Dan Zajdband" < [email protected] [email protected] > escreveu:

Você tem 2 guias abertas, logout em 1, efetua logout automaticamente nas outras

Você está recebendo isso porque foi mencionado.
Responda a este e-mail diretamente, visualize-o em Gi tHubhttps: //github.com/zeit/next.js/issues/153#issuecomment -258687707 ou silencie o th readhttps: //github.com/notifications/unsubscribe-auth/ AA5cE9e2DA4_GgNQIVTMp0hx74G-6RmUks5q7fBfgaJpZM4KkJmi.

Ol√° @luisrudge , enviei um PR com as altera√ß√Ķes https://github.com/luisrudge/next.js-auth0/pull/2

muito obrigado por fazer isso <3

btw este é o resultado:

2016-11-06 11 14 31

@impronunciable @luisrudge Implementa√ß√£o fant√°stica! Se voc√™ quiser us√°-lo sem o Auth0, parece que voc√™ s√≥ precisa alterar os arquivos no diret√≥rio ./utils, talvez apenas lock.js . Eu estarei experimentando isso em breve. A prop√≥sito, a multi-aba parece incr√≠vel ūüíĮ

@ugiacoman comecei a implementar um pequeno servidor com passwordless.net, deixe-me saber se você deseja obter meu código como ponto de partida

@impronunciable Isso seria incrível! Na verdade, eu ia fazer algo semelhante com o Digits do Twitter Fabric.

@impronuncível, eu sugiro não usar a senha less.net, em vez disso, você pode apenas usar o passaporte local e enviar aos usuários um link com seu e-mail e token na string de consulta.

Obrigado @impronunciable ‚̧ԳŹ

@ugiacoman sim, é muito fácil remover a dependência auth0. Usei porque não queria ter uma API separada para lidar com autenticação

@jaredpalmer at√© onde eu sei, ter o n√ļmero 25 seria √≥timo, mas n√£o est√° bloqueando? Quer dizer, temos acesso ao lado do servidor req em getInitialProps ent√£o nada impede a aplica√ß√£o de cookie-parser nele? A autentica√ß√£o do lado do servidor e o gerenciamento de sess√£o s√£o coisas novas para mim ūüė¨

BTW, considerando que localStorage n√£o pode ser usado do lado do servidor, os cookies s√£o a √ļnica maneira de ter sess√Ķes do lado do servidor? Tenho uma vaga lembran√ßa de que pode n√£o ser o mais seguro? Mas existe alguma outra op√ß√£o?

@sedubois

A abordagem do cookie pode ser muito segura se feita de maneira adequada. Fazer o seguinte é bastante trivial:

  • usar sinalizador httpOnly (impede o acesso de JavaScript ao cookie)
  • usar sinalizador seguro (definir cookie apenas para solicita√ß√Ķes https)
  • Cookies assinados (verifique a origem do cookie)

Tamb√©m h√° uma vantagem de lat√™ncia muito significativa quando voc√™ pode acessar as informa√ß√Ķes de autentica√ß√£o diretamente no servidor.

Devemos mover este exemplo para examples/ Verei o que posso fazer

Consegui usar react-cookie para cookies isomórficos envolvendo nextjs em um servidor expresso personalizado da seguinte maneira:

const express = require('express')
const next = require('next')
const cookie = require('react-cookie')
const cookieParser = require('cookie-parser')

const app = next({ dev: true, dir: process.cwd() })
const handle = app.getRequestHandler()

app.prepare().then(() => {
  const server = express()
  server.use(cookieParser())       // <---- this line

  server.get('*', (req, res) => {
    cookie.plugToRequest(req, res) // <---- this line
    return handle(req, res)
  })

  server.listen(3000, (err) => {
    if (err) throw err
    console.log('> Ready on http://localhost:3000')
  })
})

Isso me permite fazer uma solicitação autenticada do lado do servidor. Isso não resolve nenhum dos problemas originais, mas resolveu o problema de compartilhamento de estado entre cliente e servidor.

Do ponto de vista de quem está aprendendo muito dessas coisas. Acho que seria melhor se os exemplos não dependessem de serviços de terceiros como o auth0. Seria mais benéfico para os recém-chegados ver um exemplo mais básico com formulários de login / inscrição e usando Redux e JWT.

O exemplo que planejamos _bundle_ será baseado em APIs de servidor Node.js de código aberto

Eu adicionei um exemplo de autenticação baseada em e-mail para um projeto inicial de exemplo em https://github.com/iaincollins/nextjs-starter

Tem suporte de sessão (com Express Sessions no backend e a API sessionStorage do navegador para armazená-los em cache no front end), cookies httpOnly, projeção CSRF, usa SMTP embutido para enviar e-mails, um fácil de alterar o backend que é padronizado para SQL Lite . Nenhuma configuração é necessária para executá-lo.

O projeto tamb√©m possui p√°ginas de layout, rotas personalizadas e inclui o exemplo de rel√≥gio do wiki. N√£o √© o exemplo mais extravagante de autentica√ß√£o, mas pode ser √ļtil para quem procura uma introdu√ß√£o f√°cil com um projeto simples que seja f√°cil de entender e brincar.

Eu concordo com @iamjacks que um exemplo com JWT parece uma boa ideia.

Estou feliz em melhorar o tratamento de erros e adicionar recursos como uma p√°gina de perfil simples que os usu√°rios podem editar e integra√ß√£o de passaporte com exemplos para oAuth para Facebook, Google e Twitter, se isso for √ļtil para as pessoas. Se as pessoas tiverem boas id√©ias sobre as melhores maneiras de propagar / expor informa√ß√Ķes da sess√£o para componentes, estou muito interessado.

Example screenshot showing what to expect

Isso é incrível @iaincollins. Vamos apresentar isso nas notas de lançamento para 2.0 com certeza :)

@rauchg Obrigado! :)

Acho que devo acrescentar explicitamente que, neste exemplo, as sess√Ķes s√£o baseadas em cliente e servidor - ou seja, funcionam com e sem JavaScript (e em sistemas sem sessionStorage), e a mesma sess√£o √© compartilhada por ambos.

Conseguir isso fica um pouco complicado no componente Sess√£o, que investiga vari√°veis ‚Äč‚Äčcom nomes como req.connection._httpMessage.locals._csrf para obter o token CSRF dos cabe√ßalhos do servidor - como o objeto 'req' passado para p√°ginas em getInitialProps () √© curiosamente um pouco diferente do objeto req exposto no Express, pois eu normalmente o acessaria por meio de req.locals._csrf (no entanto, req.session √© o mesmo em ambos).

localStorage não é seguro. qual é a melhor maneira de torná-lo mais seguro. qualquer um pode roubar dados localStorage e colocá-los novamente em seu navegador e pode ser registrado como o usuário vítima !!

@Chathula isso não é verdade. Este argumento está errado.
Se alguém tiver acesso ao navegador fisicamente, pode fazer qualquer coisa.

Isso também é válido para cookies.

Usar localStorage para autenticação é meio seguro porque podemos nos livrar de problemas de segurança baseados em cookies.
Mas, por outro lado, afeta o SSR.

@arunoda eu criei um login com Laravel API e Next.js Client. eu armazeno authUser access_token dentro de localStorage. em seguida, verifique o usuário conectado ou não autenticando. mas não é seguro. se alguém roubou os dados localStorage. ele / ela pode usá-lo.

se alguém roubou os dados localStorage.

Como? Basicamente, ele deve ter acesso ao navegador fisicamente. Ent√£o essa pessoa pode fazer qualquer coisa.
Portanto, n√£o devemos nos preocupar com isso.

n√£o podemos usar qualquer criptografia para torn√°-lo muito mais seguro?

@Chathula, isso está saindo do assunto. Não é exatamente relevante para Next.js e queremos ver como as coisas da web normalmente funcionam.

@Chathula pode ser que você possa iniciar um novo tópico no projeto inicial acima.

@arunoda hahha !! Obrigado pela informação! : D

@Chathula Fico feliz em discutir isso mais em uma edi√ß√£o do projeto inicial se voc√™ tiver preocupa√ß√Ķes espec√≠ficas.

Gostaria de corrigir qualquer equívoco, para evitar que as pessoas fiquem desnecessariamente alarmadas.

A API de armazenamento da Web (ou seja, localStorage e sessionStorage) √© - como cookies sem httpOnly definido - restrita pela mesma pol√≠tica de origem (protocolo, nome de host, n√ļmero de porta), n√£o √© verdade que "qualquer um pode roubar [it]"; mas sim, se algu√©m for capaz de executar JavaScript arbitr√°rio em seu site por meio de uma vulnerabilidade de script entre sites em seu aplicativo, ele tamb√©m poder√° acessar o armazenamento, portanto, voc√™ n√£o deve armazenar identificadores de sess√£o nele.

√Č por isso que voc√™ ver√° que o token de sess√£o em si n√£o √© armazenado em localStorage / sessionStorage e n√£o √© leg√≠vel em JavaScript, ele √© transmitido apenas por um cookie HTTP Only (√© por isso que a classe de sess√£o usa XMLHttpRequest () em vez de fetch () - conforme explicado na documenta√ß√£o da classe).

Isso significa que mesmo se alguém for capaz de explorar uma vulnerabilidade de script entre sites em seu aplicativo e executar JavaScript arbitrário em seu aplicativo da web, ainda não será possível ler ou exportar um token de sessão de usuário.

Esta é talvez uma distinção importante que vale a pena trabalhar na documentação.

Observa√ß√£o: a criptografia adicional de dados do usu√°rio n√£o √© √ļtil aqui porque o aplicativo sempre precisa ser capaz de ler os dados para que possam ser renderizados (ent√£o voc√™ tamb√©m precisa armazenar uma chave de descri√ß√£o no aplicativo, o que renderizaria a criptografia do dados do usu√°rio bastante discut√≠veis).

_UPDATE: Na √ļltima semana ou duas, o exemplo foi refatorado para usar localStorage em vez de sessionStorage, j√° que sessionStorage n√£o √© compartilhado entre guias e o compartilhamento de dados n√£o sens√≠veis desta forma reduz o n√ļmero de verifica√ß√Ķes de autentica√ß√£o desnecess√°rias e mant√©m o status da sess√£o consistente entre as guias._

Talvez seja √ļtil para algumas pessoas que fiz este aplicativo de amostra enquanto experimentava:

https://github.com/possabilities/next.js-with-auth

Apoiado por este back-end de brinquedo:

https://github.com/possabilities/micro-auth

Implantado aqui:

https://next-with-auth.now.sh/

Backend aqui:

https://micro-auth.now.sh/

@possabilities Obrigado Mike! Além de expor um microsserviço separado que mostra uma boa maneira de lidar com páginas seguras que eu estava pensando que pode ser um bom pragma e pode me inspirar. Tenho algumas ideias que surgirão no repositório next.js-with-auth.

Depois de pensar um pouco mais, provavelmente não consideraria meus esforços um grande exemplo. Eu provavelmente mudaria para ter a inscrição / login totalmente submetida no estilo web 1.0 para que possamos estabelecer um cookie somente HTTP no servidor (eliminando a acessibilidade ao JWT via XSS) e, em seguida, anexar o objeto de usuário a req vez do que o token inteiro. Isso deixa a possibilidade de vulnerabilidades CSRF, mas acho que é mais simples de mitigar do que XSS (não?). Um bom efeito colateral disso é que o aplicativo cliente pode usar um fluxo quase idêntico para ao fazer login por meio de um serviço de juramento.

Também vejo, em retrospectiva, que poderia evitar o "middleware" (e, portanto, a necessidade de um servidor personalizado) analisando o cookie no Page HoC's getInitialProps .

@possibilidades Uma vez que a página 'secreta' é apenas uma página e é agrupada por webpack, ela não seria exibida para o navegador se eu fosse para / secret?

Sim, suponho que deve ser conectado para fazer um redirecionamento do lado do servidor.

Ali√°s, eu me distra√≠ de volta ao meu projeto inicial de entrar no github. O fluxo √© semelhante com mais cuidado com a seguran√ßa (ou seja, n√£o expondo nenhum segredo no cliente para evitar que o token oauth seja exposto via XSS). Ele est√° vinculado a um aplicativo adequado, mas se houver algum interesse, posso dividi-lo em algo que possa ser √ļtil para o fluxo de oauth em geral.

@ possibilidades Eu acho que seria uma ajuda incr√≠vel se pudesse haver um PR com um exemplo m√≠nimo (mas adequado) de with-auth ūüôā Estou trabalhando em auth em meu aplicativo (https://github.com/relatenow/ relacionar), mas atualmente √© apenas do lado do cliente (localStorage).

@sedubois Eu tenho um pr para isso usando passwordless.net https://github.com/zeit/next.js/pull/646, mas vamos mover o servidor de autenticação para outro lugar

que tal usar o Graphql?

Apollo dá um exemplo de autenticação Graphql:

https://dev-blog.apollodata.com/a-guide-to-authentication-in-graphql-e002a4039d1

Aqui estamos autenticando uma solicitação graphql, mas ela poderia ser adaptada para o nosso caso.

Além disso, o graphql pode abstrair a implementação e a lógica. Ele pode ser usado sem senha, auth0 ou qualquer outra coisa que possamos preferir.

@impronunciable FYI com seu exemplo, ainda n√£o sei como lidar com as sess√Ķes, pois quero me livrar do sem senha. Vou tentar adaptar o exemplo de @iaincollins em meu aplicativo.

Meus requisitos s√£o:

  • seguro
  • autenticar o lado do servidor e depois o lado do cliente
  • suporta Facebook e login / senha
  • os provedores de autentica√ß√£o devem ser facilmente alterados
  • criar usu√°rio no Graphcool
  • autenticar solicita√ß√Ķes GraphQL subsequentes para Graphcool

Caso ajude algu√©m aqui est√° meu aplicativo com autentica√ß√£o do lado do servidor ūüôā

A autenticação deve ser separada do servidor Next.js, mas estou esperando que alguém dê inspiração sobre isso ... Também não tenho certeza se está devidamente protegido contra CSRF.

Isso é o que eu fiz:

  • quando o usu√°rio faz login, o javascript do lado do cliente define um cookie no navegador que cont√©m o token do portador de autentica√ß√£o
  • ao fazer solicita√ß√Ķes autenticadas do lado do servidor (next.js), o c√≥digo l√™ o token do portador nos cabe√ßalhos da solicita√ß√£o do navegador e o usa para entrar em contato com o servidor API em nome do cliente

Isso é vulnerável a XSS (mesmo que reaja muito para evitá-lo) e ataques CSRF, mas é simples e funciona com SSR.

Apenas para adicionar aos pedidos

graph.cool + apollo + jwt + auth0 + next.js, as primeiras 4 partes j√° foram feitas em https://github.com/graphcool-examples/react-apollo-auth0-example

@balupton em seu exemplo, o que acontece quando o token expira enquanto o usuário ainda está conectado, a sessão acabou ou é renovada de alguma forma?

@nmaro não sei, não foi escrito por mim - melhor perguntar aí

Para meu próprio aplicativo, tenho auth em next.js e auth0 e, em seguida, com um servidor de API zeit / micro que verifica os tokens do portador.

Deve ser capaz de abrir o código em algum momento de fevereiro.

Seguindo a mesma filosofia que next.js tem seguido (faça uma coisa e faça bem), desenvolvi o esqueleto de um sistema de contas de usuário extensível para o nó. Veja a filosofia aqui: https://medium.com/the-ideal-system/ooth-user-accounts-for-node-js-93cfcd28ed1a#.97kyfg4xg

O projeto github est√° aqui: https://github.com/nmaro/ooth/

O objetivo é ter uma autenticação extensível e independente + serviço de gerenciamento de usuários ideal para ser usado como um microsserviço separado, uma estrutura de aplicativo que funcionaria muito bem com node.js.

Um exemplo com autenticação de e-mail + senha está aqui: https://github.com/nmaro/ooth/tree/master/examples/ooth
Já existem pacotes para autenticação do Facebook e Google (ooth-facebook e ooth-google), que devem ser fáceis de implementar com base no passport-facebook e no passport-google, respectivamente.

Estarei postando um exemplo de integração next.js o mais rápido possível. Sinta-se à vontade para participar da discussão e contribuir.

Desculpe pelo plug, mas √© para o bem maior - eu realmente acredito que ainda n√£o existe uma boa solu√ß√£o para o n√≥, e este √© o p√ļblico certo de pessoas que podem querer tal coisa. Paz

Enquanto isso ... aqui est√° um exemplo de API graphql que requer autentica√ß√£o com um JWT-Token apenas para opera√ß√Ķes de grava√ß√£o. Sinta-se √† vontade para us√°-lo com seu m√©todo de autentica√ß√£o favorito :)

https://github.com/nmaro/ooth/tree/master/examples/graphql-api-with-auth

Atualizei https://nextjs-starter.now.sh para adicionar suporte oAuth.

screen shot 2017-02-10 at 05 03 19

  • Ele usa o Passport for oAuth, junto com sess√Ķes expressas (como antes).
  • H√° suporte para Facebook, Google e Twitter + oAuth e √© f√°cil adicionar mais (consulte AUTHENTICATION.md e routes / auth-passport.js ).
  • Ele usa o sistema de sess√£o cliente / servidor universal (com tokens CSRF, prote√ß√£o XSS via cookies somente HTTP, a camada ORM que suporta Mongo, SQL DBs, Redshift, etc.) como o login de e-mail usa.
  • Pode relatar que a experi√™ncia de configura√ß√£o do oAuth em portais de desenvolvedor √© t√£o terr√≠vel como sempre (erros estranhos acontecem e √© dif√≠cil de depurar).

A natureza do oAuth - db + sess√Ķes + passaporte e tratamento de erros precisando trabalhar juntos - e das sess√Ķes que precisam funcionar tanto no cliente quanto no servidor e como isso funciona com a renderiza√ß√£o universal - significa um pouco demais para tentar resolver de uma vez se voc√™ est√° tentando descobrir o que est√° acontecendo, mas a l√≥gica do cliente n√£o tem nenhuma configura√ß√£o espec√≠fica do oAuth, portanto, n√£o √© muito confusa.

Eu ficaria feliz em dividir apenas a autenticação em um exemplo separado, embora eu suspeite que não seja muito menor. Se alguém mais quiser, ótimo. Provavelmente adicionarei um pouco mais ao exemplo em algum momento (como uma página de gerenciamento de conta). Provavelmente, vincular mais à documentação seria bom.

√ďtimo trabalho! Se voc√™ pudesse dividir a autentica√ß√£o e adicion√°-la ao reposit√≥rio next.js, seria incr√≠vel: cora√ß√£o:

Eu tamb√©m consigo fazer isso ūüĎćūüŹĽ

Não terei tempo nas próximas 2 semanas ou mais, então, se alguém quiser, seria ótimo.

Eu adoraria refator√°-lo e ver se ele poderia ser reduzido a apenas um m√≥dulo (que exp√Ķe componentes simples como bot√Ķes de login e formul√°rios de login para incorporar) e me inspirar no exemplo realmente bom do lado do cliente anterior por @impronunciable.

Atualização: Na verdade, estou indo embora, e é por isso que não posso, mas quando volto fico feliz em ver isso!

Eu segui o guia de in√≠cio r√°pido auth0 / react com algumas modifica√ß√Ķes, mas quando ligo para lock.show() , o aplicativo reclama:

Erro não detectado: addComponentAsRefTo (...): Apenas um ReactOwner pode ter refs. Você pode estar adicionando um ref a um componente que não foi criado dentro do método render um componente, ou você tem várias cópias do React carregadas

@iaincollins @timneutkens em relação ao seu exemplo, corrija-me se eu estiver errado.

O exemplo usa um cookie httpOnly para armazenar um token de sessão, tornando-o seguro contra ataques de injeção de javascript (XSS). Em seguida, ele tem o problema de ter um token csrf armazenado no armazenamento local para também proteger contra ataques CSRF.

Existe uma suposi√ß√£o subjacente de que essa combina√ß√£o de t√©cnicas torna as coisas seguras, o que pode enganar o usu√°rio / desenvolvedor. Um invasor ainda pode injetar javascript na p√°gina (XSS), ler o token csrf e us√°-lo para executar solicita√ß√Ķes autenticadas (cookie) para a apis. Vale a pena mencionar no readme?

Oi @davibe

Infelizmente, não há atualmente uma abordagem tecnicamente melhor do que um cookie de sessão e um token CSRF rotativo separado, então acho que devo dizer que estou muito feliz com o modelo, pois não há realmente outra maneira de fazê-lo (mesmo que a implementação real sempre possa ser melhorada).

Poderíamos adicionar a impressão digital do navegador, talvez o token de sessão pudesse girar com mais frequência (esqueci se isso é automático agora), o token CSRF poderia ser um cabeçalho em vez de param, os cookies deveriam ser SSL apenas em produção e poderíamos adicionar uma data de expiração para os tokens de login, mas AFAICS há um escopo bastante limitado para melhorias no que diz respeito ao modelo de segurança e nada que realmente conceda proteção adicional no caso de alguém ser capaz de injetar qualquer código que desejar em um aplicativo; mas sinta-se à vontade para levantar essas coisas como problemas para melhorias no repo.

Se houvesse alguma op√ß√£o de modifica√ß√£o de status da conta (que n√£o existe atualmente), poder√≠amos ter um CAPTCHA antes de execut√°-lo para tornar mais dif√≠cil fazer altera√ß√Ķes no servidor sem permiss√£o, mas tudo o que acontece no exemplo √© que os usu√°rios podem fazer login e fora de forma que atualmente est√° fora do escopo.

O armazenamento local de tokens de sessão o tornaria notavelmente menos seguro e iria contra o uso pretendido na especificação, então, pessoalmente, não sou a favor disso - embora eu aprecie que simplificaria as coisas, já que não ter projeção CSRF, mas provavelmente as pessoas não preciso de um exemplo disso, pois seria muito simples de fazer - só tentei fornecer um porque é muito estranho. :-)

Estou totalmente com você no sentido de que também odeio como isso é necessariamente estranho e não desisti de tentar transformá-lo em um módulo.

Hmm, eu entendo.
Esta edi√ß√£o foi muito √ļtil para mim, obrigado.

Este é o ponto de vista de Auth0 https://auth0.com/blog/cookies-vs-tokens-definitive-guide/
Basicamente, eles sugerem evitar cookies, mas isso deixaria de fora o SSR no carregamento da primeira p√°gina, eu acho.

Ei pessoal!

Também estou trabalhando na autenticação com next.js e os comentários desse problema, em particular @davibe + o repo de @iaincollins e o PR de @timneutkens foram de grande ajuda.

Minha solução faz o seguinte:

  • Ap√≥s o login bem-sucedido, meu redutor redux salva o token e os dados do usu√°rio em um cookie usando react-cookie .
  • Qualquer p√°gina / componente que precisa dessa informa√ß√£o √© empacotado em um componente de ordem superior semelhante a @timneutkens with-session.js . Se for SSR, o token estar√° dispon√≠vel em ctx.req.headers.cookie, caso contr√°rio, apenas pegue-o no documento do navegador (use o m√©todo de carregamento de cookie react).
  • Assim que tiver o token, posso defini-lo nos cabe√ßalhos do portador / autoriza√ß√£o sempre que fizer uma solicita√ß√£o.

Ajuda o fato de eu ter meu próprio microsserviço de autenticação de token JWT em execução em um contêiner do docker.
Talvez seja mais fácil fornecer um serviço JWT simples como parte do exemplo with-auth? Assim, evitando hackear o server.js e potencialmente perdendo os benefícios do next.js embutido no hot recarregamento, ssr e roteamento?

Também não tenho certeza se essa abordagem é segura em termos de CSRF / XSS. Quaisquer comentários são bem-vindos.

Obrigado a todos pelo incrível trabalho que fizeram até agora. Sou um grande fã desse projeto!

@jcsmesquita Estou trabalhando em uma nova versão do exemplo com tudo separado de Next.js semelhante a como o auth é implementado em zeit.co.

@subsumo Obrigado pela menção, FYI: NAP é meu, a autenticação via web é baseada em nextjs-starter e reage ao login do cliente nativo com token.

@timneutkens a solução na qual você está trabalhando permite que você se autentique em um serviço separado?

Estive olhando para o exemplo de solicitação de pull de autenticação atual https://github.com/zeit/next.js/pull/1141
Parece-me que só permite a autenticação no servidor next.js, mas não isomorficamente em um serviço separado.

Em outras palavras, suponha que você deseja separar o servidor next.js e a API do aplicativo real (por exemplo, REST ou GraphQL), então o que você deseja fazer é que o cliente e o servidor sejam capazes de se autenticar na API. Não acho que essa solução realmente o ajude nisso.

Eu pensei em um fluxo.

Entidades:

  • Cliente (C)
  • Servidor Next.js (S)
  • API (A)

O objetivo √© estabelecer 3 sess√Ķes baseadas em cookies:

  1. CS
  2. CA
  3. SA

A Sess√£o 1) √© para que o Cliente reconhe√ßa o Servidor e 2) 3) √© para que o Cliente e o Servidor possam usar suas respectivas sess√Ķes para acessar a API de forma independente.

Este é o fluxo:

  1. CS é feito facilmente, sem necessidade de autenticação
  2. O CA é feito com autenticação (por exemplo, com nome de usuário / senha). Além disso, um JWT é fornecido
  3. O cliente fornece JWT ao servidor e, em seguida, descarta-o
  4. SA é feito com JWT, que é então descartado

Qual a sua opini√£o? Existe uma maneira mais f√°cil? Devemos, em vez disso, apenas manter a API acoplada ao servidor next.js, de modo que apenas uma sess√£o seja necess√°ria (CS)?

@rauchg Não convoco você facilmente, mas acredito que também se trate de que direção o next.js deve seguir - como um "front-end universal", ele deve ser executado separadamente da API que fornece os dados? Se sim, precisamos fazer isso direito.

@timneutkens a solução na qual você está trabalhando permite que você se autentique em um serviço separado?

Essa é a ideia, sim. Estive ocupado consertando outras coisas no Next.js. Voltaremos a ele o mais rápido possível.

Eu dividi partes específicas do github-auth do meu aplicativo em um exemplo bem digerível. pode ser interessante para alguns e adoraria qualquer feedback sobre o código ou fluxo: https://github.com/possabilities/next-github-auth-example

ATUALIZAÇÃO: Refatorei o aplicativo de exemplo em um conjunto reutilizável de componentes que podem ser "colocados em" próximos aplicativos

Follow-up: Eu escrevi uma integração com Ooth e uma API GraphQL.

https://medium.com/the-ideal-system/ooth-user-accounts-for-node-js-93cfcd28ed1a#.ykoj1dhil

é baseado em abordagens existentes, ou seja, autenticação para o servidor next.js, ou seja, assume que a API e o servidor de autenticação rodam todos no mesmo processo, então apenas uma sessão precisa ser criada. A vantagem: em princípio, ele pode armazenar credenciais para / é extensível a praticamente qualquer estratégia passport.js.

@timneutkens algum progresso nessa frente?

Refatorei meu aplicativo de exemplo do github auth em um conjunto reutiliz√°vel de decoradores e componentes de p√°gina para ‚Äúsoltar o github auth nos‚ÄĚ pr√≥ximos aplicativos. Coment√°rios sobre c√≥digo e funcionalidade s√£o bem-vindos. https://github.com/possabilities/next-github-auth

_Acho_ que poderia ser interessante definir as placas aqui e depois continuar a evoluir para uma estrutura de autenticação mais genérica para a próxima.

@timneutkens
Desculpe por enviar um ping, mas você fez algum progresso nisso? Estou completamente perdido em como devo configurar a autenticação com next.js corretamente.

@kolpav Eu trabalhei nisso, atualmente atolado com outras coisas ūüė• De qualquer forma, isso est√° no topo da minha lista de prioridades para o Pr√≥ximo ūüėĄ

Uma maneira clara, bem documentada e segura de obter autenticação com um aplicativo next.js é fundamental para seu sucesso como estrutura.

N√£o me lembro da √ļltima vez que constru√≠ uma web que n√£o tivesse autentica√ß√£o.
Como a maioria das pessoas que imagino, também quero fazer chamadas seguras para meus dados de backup para descanso, então JWT parece a solução óbvia.

Mas h√° tanta discuss√£o entre as quest√Ķes e as rela√ß√Ķes p√ļblicas que n√£o tenho certeza por onde come√ßar!

@timneutkens
Legal ūüĎć Acho que vai ser muito valioso para os outros.

@camstuart @kolpav Existem alguns bons exemplos de trabalho acima, incluindo o suporte a oAuth e autenticação baseada em e-mail que usa cookies JWT e HTTP pelos contribuidores @jaredpalmer , @luisrudge , @impronunciable , @possilities e eu mesmo.

Para destacar alguns links funcionam check-out:

(O exemplo de microautenticação foi bom, mas acho que precisa ser atualizado.)

Há espaço para melhorias adicionais, que comentaristas adicionais comentaram acima - incluindo um componente de armazenamento de sessão e divisão da lógica do servidor; e um exemplo que simplifica ainda mais as coisas nas quais Tim está trabalhando.

Simplicidade para autenticação é uma área desafiadora para aplicativos universais, mas você deve ser capaz de seguir os exemplos acima - ou apenas experimentar as demos diretamente - e ver como funcionam sem muito barulho.

@iaincollins São ótimos exemplos. Mas como posso usar (por exemplo) o projeto inicial? Então, se eu quiser construir meu aplicativo. Eu preciso clonar este repo? Ou preciso "copiar e colar" o código do projeto inicial, pedaço por pedaço, para o meu próprio código?

Se o projeto inicial for atualizado - o que devo fazer?

@iaincollins
Bons exemplos, especialmente os seus.
Mesmo assim, gostaria de ver um exemplo de autentica√ß√£o com o selo de aprova√ß√£o zeit ūüėĄ todos os olhos apontariam em uma dire√ß√£o para que quaisquer erros ou erros n√£o passassem despercebidos. Por enquanto, tenho minha pr√≥pria autentica√ß√£o de trabalho, mas n√£o tenho certeza de qu√£o seguro √©.

Concordo, @kolpav ,

Eu criei uma pilha para isso que pode lidar com autenticação facilmente com GraphQL: https://github.com/thebillkidy/MERGE-Stack

@salmazov Eu descobri uma maneira √ļtil de come√ßar e entender o que est√° acontecendo em um exemplo ou projeto inicial pode ser bifurc√°-lo e, em seguida, remover coisas que n√£o s√£o relevantes at√© que voc√™ fique apenas com o c√≥digo relacionado √† funcionalidade voc√™ deseja implementar; e, em seguida, tentar transferir apenas essa funcionalidade para outro projeto.

@kolpav @camstuart Este t√≥pico cont√©m uma discuss√£o realmente extensa de v√°rios modelos de seguran√ßa, incluindo desmascarar alguns equ√≠vocos comuns e compensa√ß√Ķes. Eu observaria particularmente os pontos sobre cookies somente HTTP e tokens CSRF (e a prote√ß√£o adicional que eles fornecem contra XSS e CSRF sobre o uso de JWT e / ou API de armazenamento da Web para tokens de sess√£o). Realmente vale a pena ler.

@iaincollins Você queria vincular algo? :sorriso:

Ola pessoal :)

Tenho uma pergunta, estava lendo a seguir, não consigo obter os tokens para autenticação com jwt do localstorage.

Se eu tiver um servidor para render apenas a primeira cobrança do meu site com a próxima. E eu tenho outro servidor para minha api. Este recebe o usuário / passe do cliente e dá um jwt. Em quais casos preciso obter o token no servidor ??

Por que eu precisaria de um token no servidor de renderização (a seguir)?

Se o cliente n√£o enviar o token para o servidor api, a api n√£o fornecer√° os dados e o usu√°rio n√£o conseguir√° obter informa√ß√Ķes privadas. N√£o estou entendendo por que preciso enviar o token para o servidor de renderiza√ß√£o.

@kamilml

Isso pode ajudar. Em geral, voc√™ tem duas op√ß√Ķes:

  1. Forneça JWT ao próximo servidor (possivelmente por meio de cookie). Isso permitirá que o próximo servidor faça chamadas de API em nome do cliente. Você desejaria isso se a renderização completa do lado do servidor fosse importante para você.

  2. Armazene o JWT no armazenamento local do cliente e não conceda acesso ao servidor Next. Nesse caso, você pode simplesmente ignorar as chamadas de API do lado do servidor e adiar a renderização completa até que o carregamento do lado do cliente seja concluído.

Peço desculpas por reabrir isso, mas pensei em adicionar meus 2 centavos a este tópico, e como minha P&D inicial está se saindo nesta área. Menos exemplos de código, mais fluxo de alto nível.

Em primeiro lugar, para contextualizar, a maior parte de nosso aplicativo j√° √© constru√≠da em Symfony 3 (PHP) e usa Vue para uma experi√™ncia h√≠brida. O servidor renderiza uma p√°gina de wrapper e atribui dados do aplicativo a __INITIAL_STATE__ para o aplicativo selecionar. Isso resultou na tomada de decis√£o entre renderizar p√°ginas de marketing no Symfony (para SEO) e escolher UX / UI em vez de SEO em outras √°reas, buscando dados via JS e fornecendo uma sensa√ß√£o mais SPA. Tamb√©m vale a pena notar que nem todas as p√°ginas s√£o bin√°rias p√ļblicas / privadas (como vi em alguns exemplos). Algumas p√°ginas s√£o p√ļblicas por padr√£o e, em seguida, renderizadas de forma diferente se autenticadas. Est√°vamos pensando em usar um SPA para partes do site, mas de muitas maneiras pr√°ticas, era um UX / UI pior (TTI mais lento, barras de progresso etc.). Al√©m disso, isso n√£o resolve o problema de SEO, a menos que introduzamos FOUC e renderizemos o texto duas vezes (uma vez atrav√©s do Symfony, mais uma vez como componentes JS), etc.

Insira SSR / JS universal ...

No meu caso, o que fiz foi imitar a l√≥gica PHPSESSID , criando um cookie HttpOnly UJSSESSID (criou o nome) e definindo o valor para o usu√°rio JWT. O aplicativo Symfony passa isso adiante em cada solicita√ß√£o de p√°gina √† medida que o usu√°rio navega pelo site. Quando o usu√°rio acessa as p√°ginas UJS, o lado do servidor desses aplicativos receber√° os cookies na solicita√ß√£o (de acordo com o comportamento integrado do navegador). Se o cookie UJSSESSID estiver definido, o aplicativo chamar√° a API para obter as informa√ß√Ķes do usu√°rio (por exemplo, /api/v1/users/me passando o token via Authentication header). O restante das chamadas √© feito por meio da API, usando o mesmo token. O mecanismo de logout do Symfony limpa o cookie UJSSESSID . Na pr√≥xima vez que o aplicativo UJS for carregado, ele renderizar√° as p√°ginas no modo de usu√°rio an√īnimo. Para sua informa√ß√£o, o roteamento da p√°gina Symfony vs. UJS √© feito por meio do ProxyPass do Apache. LocalStorage n√£o √© usado.

O resultado final é uma UX perfeita em que o usuário está em algumas páginas que são PHP com JS do lado do cliente e algumas páginas que são UJS. Isso nos permite fazer testes A / B e atualizar o site de forma iterativa - nem todo mundo começa do zero :)

Embora isso seja um pouco mais complicado devido ao PHP / UJS simbiótico, o mesmo princípio pode ser usado em uma solução UJS completa com um middleware de servidor API ou Node.js (por exemplo, Express, Adonis, etc.). Em vez de definir o cookie UJSSESSID por meio de uma solicitação de página PHP (sinalizador HttpOnly ), faça com que o usuário faça o login através do seu SPA / UJS e defina o cookie lá. O que você NÃO DEVE fazer é usar seu aplicativo para decodificar o JWT ou fazer chamadas de terceiros que exijam client_secret . Use um middleware que permanece no servidor para isso.

Espero que ajude alguém. Outros exemplos que vi eram placas de Petri um pouco demais para mim.

@jaredpalmer Ei, obrigado por essa implementação, eu tentei, apenas

const index = () =>
  <div>
    <span>WoooHoooo</span>
  </div>

export default withAuth(index)

e em withAuth hoc eu mudei para redirecionar para a p√°gina de login.
Mas antes de redirecionar para a p√°gina de login, o conte√ļdo da p√°gina de √≠ndice ainda pisca um pouco. : S

Qual √© a situa√ß√£o desse problema? ūüėá

Isso é um pouco opressor para as pessoas novas que estão lendo toda a discussão. Decidi implementar a autenticação básica aqui. Apenas 2 páginas (índice, login) e um servidor personalizado
https://github.com/trandainhan/next.js-example-authentication-with-jwt

Basicamente, temos um middleware de autenticação no servidor para verificar o token no cabeçalho de cada solicitação. O jwt-token será armazenado em cookies. Acho isso muito simples, direto e funciona muito bem.

@trandainhan Você poderia adicionar um endpoint POST que usa um token secreto para evitar ataques CSRF?

@sbking Código-fonte atualizado com um endpoint de exemplo protegido por ataques CSRF

Est√° pronto para usar ūüė¨?

Alguém tentou autenticação com redux-auth-wrapper ?

Ol√° pessoal! Nos √ļltimos meses, criei e agora refinei

Possui:

  • Cadastro com email e senha
  • Login com e-mail ou nome de usu√°rio e senha
  • P√°gina da conta onde voc√™ pode definir seu nome de usu√°rio, alterar sua senha e reenviar um e-mail de verifica√ß√£o
  • Esqueceu a senha / redefiniu as p√°ginas de senha
  • Verificar p√°gina de e-mail
  • Uma API GraphQL b√°sica vinculada a um MongoDB (1 arquivo, pode ser facilmente removido)
  • Boilerplate m√≠nimo (o m√°ximo de l√≥gica poss√≠vel √© encapsulado em bibliotecas)

Confira uma demonstração ao vivo aqui: http://staart.nmr.io/

Eu fiz isso principalmente para mim mesmo para prototipagem rápida, para começar rapidamente com um aplicativo com um sistema de contas simples e funcional que não depende de serviços externos. Estou muito feliz com os resultados. Pretendo continuar usando e mantendo essas bibliotecas, então experimente se você sentir que um sistema de contas + IU para o nó ainda está faltando.

@trandainhan Obrigado, esse é um ótimo exemplo e muito mais simples para muitas pessoas e funcionaria em vários cenários.

Vou pensar se / como posso adaptar a lógica atual no nextjs-starter para usar algo assim, mas com segurança, embora ainda seja compatível com a lógica de sessão expressa para casos de uso do mundo real que tenho (como usar coisas como APIs oAuth do Google, onde preciso que o servidor mantenha e rastreie os tokens concedidos no primeiro login).

Ainda não descobri se isso é possível, mas seria muito mais fácil para as pessoas se fosse.

Se n√£o, pelo menos vale a pena escrever em algum lugar para explicar √†s pessoas as diferentes op√ß√Ķes.

@trandainhan : Se eu adicionar <Link href="/">Home</Link> ao login.js e clicar no link gerado, poderei acessar o index.js sem estar logado. Como você sugeriria corrigir isso em seu exemplo?

@iaincollins Vejo a maioria das solu√ß√Ķes aqui autenticadas em um servi√ßo oauth. Existe alguma boa solu√ß√£o para autentica√ß√£o em uma API que depende do JWT?

@paulwehner Acho que isso acontece porque @trandainhan só lidou com o roteamento de autenticação do lado do servidor. Ainda não estou certo de como o roteamento do lado do cliente funciona no next.js porque tudo é tratado internamente pelo próximo componente / Link.

@ carlos-peru Sob o cap√ī, o Link realmente usa next / router para inserir um novo caminho no hist√≥rico do navegador. Parece que a maioria das coisas √© tratada pelo navegador, n√£o h√° nada a fazer aqui para um middleware no lado do servidor. At√© agora, s√≥ consigo pensar em criar nosso pr√≥prio componente Link e fazer outras coisas sempre que mudarmos o url.

@ carlos-peru Você sempre pode usar o servidor personalizado para ter controle total sobre o roteamento.

Obrigado @trandainhan e @kolpav! Tive que entender melhor depois de passar algum tempo no fim de semana. Também consegui implementar uma solução que conta com HOC que mantém o token jwt em um cookie, para que tanto o servidor quanto o cliente consumam a api.

@nmaro Eu tenho um back-end com autenticação JWT para um site em next.js e um aplicativo (react-nativo).

Então. Acho que no próximo modelo: O cliente obtém um token do Facebook (o usuário aceita o login do facebook) e, em seguida, o cliente envia para o backend o token para verificar e validar o token do usuário (passport-facebook-token no backend node-js) . Então, se o token estiver bom, o back-end envia ao cliente o JWT gerado no back-end.

O problema? Sua ferramenta pode obter a chave no facebook e no google? Estou usando hello.js, mas não é compatível com next.js e todo o mundo usa passaporte-facebook. Acho que é um grande erro porque o servidor api precisa ser compatível com o cliente web e o aplicativo móvel.

Obrigado

PS: N√£o consigo obter um convite no seu canal slack.

@hmontes aqui - um convite para o canal de folga para o Ooth projeto (contas de usuário para o nó, em next.js particulares) sinta-se livre para participar. Ooth usa passport-facebook-token (não passport-facebook) e passport-google-id-token que acredito resolver seu problema.

@nmaro eu quero te ajudar com seu projeto. Eu tenho um back-end com Graphql com passport-facebok e passport-google-id-token também !!!

Mas. Você conhece um pacote compatível para conectar cliente facebook / google em next.js?

No lado do cliente, você pode usar um padrão semelhante ao que usei aqui: https://github.com/nmaro/staart/blob/master/packages/staart/src/components/login-facebook.js https: // github. com / nmaro / staart / blob / master / packages / staart / src / components / login-google.js
(em vez de oothClient.authenticate apenas envie uma solicitação de postagem para sua rota de autenticação).

@timneutkens um PR com um mínimo de exemplo seria bem-vindo?

@nmaro em seu exemplo. Por que você usa componentDidMount em vez de componentWillMount?

Estou criando um componente HoC (provedor) para o login do Google.

O componentWillMount é chamado apenas no cliente? Então deve ficar bem.

Ok. Muito obrigado por seus exemplos. Finalmente, posso implementar autenticação com mídia social.

Ultima quest√£o. Fui criado um access_token e um refresh_token e quero colocar em localStorage para salvar os dados.

Onde posso colocar isso em next.js para verificar o login quando a p√°gina for atualizada? Em create-react-app eu coloquei isso em index.js

...
import { loginUser } from './actions'
...
let accessToken = localStorage.getItem('access_token')
let refreshToken = localStorage.getItem('refresh_token')

if (accessToken && refreshToken) store.dispatch(loginUser({accessToken, refreshToken}))

ReactDOM.render(
  <ApolloProvider store={store} client={client}>
....

Obrigado

Com ooth, n√£o armazeno os tokens do Facebook, apenas os uso uma vez com o passaporte e, em seguida, crio uma sess√£o de usu√°rio normal baseada em cookies.

Ah. Ok. Estou usando JWT em vez de sess√Ķes. Ent√£o, eu envio access_token para o backend, ele verifica se o token √© v√°lido no servi√ßo (google, facebook), ent√£o se o usu√°rio existe no meu aplicativo e me envia de volta um JWT.

Obrigado :)

Devo acrescentar que √© perigoso armazenar JWTs no armazenamento local (por causa do XSS), melhor envi√°-los como cookies se estiverem todos em um servidor / dom√≠nio, de modo que o c√≥digo javascript do cliente n√£o possa obter o JWT, mas o navegador enviar√° o JWT automaticamente como cookies. Os JWTs s√£o complicados (veja as longas discuss√Ķes acima), √© por isso que em ooth eu uso sess√Ķes.

Eu uso um JWT apenas se outro for usado como um microsserviço de autenticação externa (porque os cookies só funcionam no mesmo domínio) e, mesmo assim, eu o uso exatamente uma vez para criar uma sessão com o servidor, de modo que não seja armazenado em nenhum lugar do cliente .

Para aumentar a segurança do JWT, você pode usar um token de atualização (obtido de oauth2).

Um aplicativo móvel pode lidar com cookies?

@nmaro Okey. Eu entendo você. Desculpe pelo meu erro.

Você tem um tutorial ou código para salvar o token JWT em um cookie? Estou procurando https://github.com/zeit/next.js/blob/master/examples/with-firebase-authentication (Meu sistema de autenticação é com graphql)

N√£o, desculpe, eu nunca fiz isso.

@hmontes @nmaro
Eu escrevi isso para mim, mas pode ajudar:
https://github.com/malixsys/mobazoo

Olá @malixsys, obrigado por compartilhar. Algo que não entendi do seu código: parece que você configuraria API_BASE_URL para algo externo, certo? Se você se autenticar nessa API, acho que isso iniciaria uma sessão baseada em cookie, certo? Mas então, como você transfere esse cookie para o servidor next.js, supondo que o servidor next.js esteja em outro domínio?

Ah não, vejo, você define / auth / signin no mesmo processo. Ok, então é basicamente a mesma abordagem que usei para o outro com next.js / staart.

Na verdade não, ainda estou confuso: em / auth / signin você devolve um JWT, mas nunca faz nada com isso no lado do cliente. Mais tarde, você "getUserFromCookie", mas não vejo onde definiu o cookie.

@nmaro Eu só queria um login básico para trabalhar com universal inicialmente. Eu defini um jwt e um cookie por enquanto. O cookie é usado para fazer universal. Ainda não usei o jwt em outra chamada de axios neste repo. Eu faço em uma bifurcação privada onde API_BASE_URL aponta para outro domínio ...
Est√° tudo na minha lista TODO, com PWA.
Sinta-se à vontade para abrir um problema ou enviar um ping aqui ...

Sei que esse problema está encerrado, mas gostaria de mostrar minha solução.
https://next-auth.now.sh/
Acho que é um pouco semelhante ao site zeit.co

9 de abril

Eu fiz algum trabalho nisso, atualmente atolado com outras coisas ūüė• De qualquer forma, isso est√° no topo da minha lista de prioridades para o Pr√≥ximo

22 de setembro # 2974

Estamos planejando lançar um exemplo de autenticação oficial em breve. Você poderia lançá-lo como um repositório separado? Thaaaanks!

@timneutkens

Ol√°, desculpe incomod√°-lo novamente, mas voc√™ poderia compartilhar como est√° o status do exemplo de autentica√ß√£o oficial? √Č definitivamente algo que eu adoraria ver e a julgar pela contagem de coment√°rios nesta edi√ß√£o tamb√©m. Ent√£o, qu√£o alto est√° na lista de prioridades e devemos ter esperan√ßas? ūüėĄ

Ol√° @kolpav , eles anunciaram oficialmente isso no roteiro do Next.js 5.

Finalmente, estamos adicionando alguns exemplos altamente solicitados (como autentica√ß√£o de usu√°rio), documenta√ß√£o aprimorada para internos do Next.js e recursos menores e corre√ß√Ķes de bugs.

https://zeit.co/blog/next-canary#the -roadmap

@babenzele Essa √© uma √≥tima not√≠cia. Eu devo ter sentido falta disso ūüėÖ

Onde podemos ficar atualizados com o desenvolvimento do Next.js 5? Estou integrando o auth0 no momento, mas seria ótimo ter um caminho / exemplo oficial do nextjs auth para seguir

Parece que Next.js precisa desesperadamente de um exemplo de autentica√ß√£o local oficial usando JWT / cookies / localStorage (ou uma combina√ß√£o deles, desde que seja seguro e protegido de XSS / CSRF) ... Passei v√°rias semanas tentando criar isso usando um servidor Express API separado com uma estrat√©gia local Passport.js. Tentei o JWT em um cookie / localStorage para solicita√ß√Ķes sem estado e tamb√©m tentei um cookie regular com o ID de sess√£o do middleware de sess√£o expressa nele, uma vez que finalmente desisti do JWT e da aus√™ncia de estado. Acabei tendo problemas em que sess√Ķes extras estavam sendo criadas no servidor Express API devido √† maneira como a sess√£o expressa funciona (tentei com saveUninitialized: false). Considerei mover o c√≥digo Express para server.js em meu aplicativo Next.js, mas eu realmente prefiro que seja um servidor separado. Tamb√©m tenho certeza de que minha implementa√ß√£o n√£o √© segura contra XSS / CSRF ou sequestro de cookies. Precisamos de um exemplo oficial que cubra as melhores pr√°ticas para autentica√ß√£o / login local, ou talvez um m√≥dulo oficial como parte do Next.js que ir√° lidar com as complexidades para n√≥s!

Enquanto aguardamos Next.js 5.x e outros exemplos, você pode dar uma olhada em https://nextjs-starter.now.sh, que ainda é mantido ativamente e usa Next.js com Express, Express Sessions, CSRF ( CRSF Tokens), XSS (cookies somente HTTP para tokens de sessão) e usa Passport JS para oferecer suporte a oAuth e e-mail.

Na verdade, estou no processo de refatoração do código de autenticação em um módulo, tornando realmente fácil adicionar autenticação a projetos Next.js de uma maneira fácil de usar. O módulo deve permitir que você o use facilmente com qualquer banco de dados de sua preferência, sem ter que copiar um monte de código do exemplo do Starter Project. Espero terminar com isso esta semana.

Para referência, o método "Double Submit Cookie" fornece uma maneira fácil de adicionar proteção CSRF se você estiver procurando por uma abordagem simples, mas segura.

O problema com o JWT no localStorage √© que ele sempre pode ser lido no JavaScript do lado do cliente, portanto, um vetor para sequestro de sess√£o via XSS, se voc√™ tiver conte√ļdo n√£o confi√°vel (por exemplo, conte√ļdo enviado pelo usu√°rio ou an√ļncios).

Se voc√™ usar cookies Apenas HTTP para tokens de sess√£o - ou algo como um JWT com um valor de token em Apenas HTTP (ou criptografar todo o JWT e descriptograf√°-lo usando um token Apenas HTTP no servidor) - ent√£o as sess√Ķes s√£o t√£o protegidas quanto podem ser. A ideia √© apenas que, idealmente, os tokens de sess√£o especificamente n√£o devem ser leg√≠veis por meio de JavaScript do lado do cliente.

√Č claro que muitos sites n√£o usam cookies HTTP somente porque √© uma dor para aplicativos de p√°gina √ļnica e invariavelmente envolve ter alguma l√≥gica de autentica√ß√£o no front end, mas ainda √© a abordagem ideal.

Outra opção ainda é https://github.com/nmaro/ooth, que é mantido ativamente, já vem em pacotes e está sendo usado em alguns aplicativos de produção.

@iaincollins Baixei o Next.js Starter Project e comecei a procurá-lo. Precisarei separar as partes importantes relacionadas à segurança (XSS / CSRF) e tentar integrá-las ao meu aplicativo ou esperar até que você conclua o módulo separado. Existe algum lugar onde eu possa acompanhar o desenvolvimento desse módulo?

Ol√° @ kelleg1 ,

O módulo separado agora está publicado como o módulo next-auth para torná-lo mais fácil de usar em outros projetos. Inclui um projeto de exemplo que mostra como usá-lo.

Para referência futura, o projeto nextjs-starter.now.sh agora também usa o next-auth, o que simplifica muito o código no projeto inicial - e agora é muito mais fácil adicionar suporte para novos provedores oAuth ou usá-lo com bancos de dados diferentes ( embora o exemplo ainda use Mongo DB).

Ainda é um pouco complicado, então, se você tiver um aplicativo existente, pode achar mais fácil de usar como referência, mas se assim for, espero que ajude

NB: Atualmente, o CSRF ainda est√° fortemente acoplado a ele. Ele usa lusca, ent√£o assume que res.locals._csrf est√° definido, mas diferentes bibliotecas CSRF usam diferentes vars privados.

Eu aprecio que ainda seja mais complicado de usar do que qualquer um gostaria, mas pelo menos agora o código de autenticação está finalmente separado em um módulo para que eu possa começar a refatorar. Espero torná-lo mais fácil de usar (com manipuladores padrão para bancos de dados diferentes e configuração mais fácil de oAuth) ao longo do tempo.

@iaincollins parece que a √ļnica depend√™ncia do next.js √© https://github.com/iaincollins/next-auth/blob/master/index.js#L342 ? Nesse caso, seria √≥timo tornar a lib next.js agn√≥stica.

@sedubois Concordo totalmente!

Embora essa seja provavelmente uma boa discuss√£o para os problemas de reposit√≥rio do GitHub, e n√£o aqui. ūüôā Se voc√™ gostaria de sugerir maneiras de melhor√°-lo, simplific√°-lo e torn√°-lo mais gen√©rico, adoraria colaborar.

(Ter algo que seja t√£o f√°cil de usar com o pr√≥ximo quanto poss√≠vel ainda √© um objetivo principal, mas n√£o vejo que precise ser exclusivo, mesmo que termine com as pr√≥ximas op√ß√Ķes espec√≠ficas focadas tamb√©m).

@timneutkens Parabéns pelo lançamento de nextjs 5. Em um futuro próximo, veremos a adição de um exemplo de autenticação local oficial adicionado à pasta de exemplos? Ou isso ainda está em andamento para um lançamento posterior?

Ooth agora tem uma documentação abrangente, incluindo os detalhes da autenticação next.js.

@jaredpalmer Gosto da sua abordagem, copiei partes da sua implementa√ß√£o. No entanto, o m√©todo getUser √© seguro? E se algu√©m alterar a string no armazenamento local manualmente, seria inteligente para o aplicativo confiar nisso? Faria mais sentido transform√°-lo em um m√©todo que decodifica a parte p√ļblica JWT do token todas as vezes e l√™ o estado do usu√°rio a partir da√≠? Dessa forma, podemos confiar neste estado mais devido √† natureza das coisas do JWT. qual e sua OPINIAO?

Você deve armazená-lo em um cookie. Eu escrevi que antes do Next tinha suporte para servidores personalizados.

@jaredpalmer Você pode me falar mais sobre isso? Devemos armazenar tudo em cookies em vez de armazenamento local? O seu HOC também seria diferente? Isso significa que agora podemos usar o método getInitialProps para renderizar sites protegidos do lado do servidor?

Apenas para avisar _se você está falando sobre armazenamento de dados confidenciais em armazenamento local / Web Storage_:

"Nunca armazene dados confidenciais usando o armazenamento da Web: o armazenamento da Web n√£o √© um armazenamento seguro. N√£o √©‚Äú mais seguro ‚ÄĚdo que os cookies porque n√£o √© transmitido pela rede. N√£o √© criptografado. N√£o h√° sinalizador Seguro ou somente HTTP, portanto, n√£o √© um local para manter a sess√£o ou outros tokens de seguran√ßa. "

Defina o token em um cookie ap√≥s o login. use cookie-js. Em seguida, use o analisador expresso de cookies no servidor para que voc√™ possa verificar se h√° req.headers.cookies.myToken ou equivalente. Em getInitialProps de um hoc, verifique se req existe e, em seguida, pegue o token de req.cookies, caso contr√°rio, obtenha-o no cliente em Cookies.get ('mytoken'). Neste ponto, voc√™ ter√° acesso ao seu token no cliente e no servidor. Ent√£o voc√™ deseja fazer um fetch / axios wrapper / inst√Ęncia e mescl√°-lo com o pr√≥ximo ctx em getInitialProps para que todas as suas p√°ginas tenham uma maneira de fazer solicita√ß√Ķes isom√≥rficas autenticadas. Voc√™ tamb√©m pode querer apenas colocar seu usu√°rio no hoc. Portanto, voc√™ n√£o precisa repetir isso em todos os lugares. Voc√™ pode fazer mais hocs se precisar para entidades comuns como withUser (withTeam (Page))

getUser é uma má ideia, você só deve armazenar o token.

@jaredpalmer Eu construí uma abordagem quase exatamente assim e tudo está funcionando bem. O problema que estou tentando resolver agora é como atualizar os tokens. A API com a qual estou trabalhando tem tokens de duração relativamente curta (2 horas) e estou tentando entender algum sistema para manter o usuário conectado enquanto usa o aplicativo.
Você tem alguma opinião sobre isso?

Voc√™ tamb√©m pode salvar uma solicita√ß√£o em cada transi√ß√£o de p√°gina, n√£o passando dados por meio de next.js para seu usu√°rio. Para fazer isso, voc√™ deve ler o token do cookie em server.js e tentar buscar o usu√°rio e pass√°-lo para o pr√≥ximo manipulador de solicita√ß√£o. No documento, obtenha-o dos adere√ßos e armazene-o em JSON em window.USER. Ent√£o, em seu hoc, voc√™ acabou de l√™-lo da janela quando estiver no terreno do cliente. Por √ļltimo, voc√™ deve usar axios com um interceptor de resposta que apaga imediatamente o seu cookie ao receber o c√≥digo 403 e recarrega a p√°gina

@pbrandone Embora repetitivo, a solu√ß√£o mais simples e previs√≠vel √© enviar seu token com cada solicita√ß√£o, recebendo um token rec√©m-atualizado no cabe√ßalho / corpo da resposta. Seu cliente atualiza seu valor conhecido em cada ciclo de solicita√ß√£o / resposta, efetivamente concedendo tokens de uso √ļnico que nunca ficam obsoletos e n√£o podem ser usados ‚Äč‚Äčindevidamente.

Normalmente, com esta abordagem, o /token/refresh s√≥ √© usado para o "despertar" inicial do aplicativo (pense em componentWillMount gancho para <App/> ), verificando se o √ļltimo token ainda √© v√°lido e utiliz√°vel.

Nunca tive que lidar com tokens de atualização, mas eu tentaria fazer isso em um interceptor axios. Teria que pensar mais sobre isso, mas em teoria você interceptaria um pedido incorreto e, em seguida, usaria o token de atualização para obter um novo token, definiria o cookie com o novo token e reproduziria a primeira solicitação com o novo token novamente. Os interceptores Axios são realmente poderosos porque permitem que você mantenha coisas como essa abstratas e fora da vista do código do produto. Você pode precisar escrever um interceptor de solicitação e resposta e / ou manter algum tipo de objeto / mapa com estado em andamento que pode ficar complicado. Espero que ajude

Ou faça o que Luke disse. Muito facil.

Se voc√™ quiser atualizar os tokens, precisar√° interceptar o cookie (se estiver usando cookies) por meio de uma configura√ß√£o de servidor personalizada. Eu fiz isso usando o expresso. Caso contr√°rio, voc√™ pode fazer tudo no lado do cliente usando tokens JWT. Como eu estava fazendo o meu por meio de cookies, tive 2 casos de uso - lidar com solicita√ß√Ķes de navega√ß√£o no lado do cliente e solicita√ß√Ķes de p√°gina no lado do servidor (sempre que algu√©m digitar manualmente um url ou acessar a atualiza√ß√£o da p√°gina). Mas basicamente eles s√£o o mesmo fluxo apenas executado de forma diferente, pois um √© do lado do cliente e o outro do lado do servidor. No lado do servidor, como usei o express, acabei de criar um middleware para processar o cookie, decodificar o JWT dentro dele e verificar a validade. Se ele tiver expirado, fa√ßa a solicita√ß√£o para obter um novo token e continue a passar o usu√°rio decodificado para reduxar no cliente. No cliente, tenho um wrapper HOC para links seguros que verifica constantemente o usu√°rio, cada vez que voc√™ navega em algum lugar do cliente. O HOC pegar√° seu cookie ou JWT, (no meu caso meu JWT est√° em um cookie) e verificar√° se ele ainda √© v√°lido rapidamente. Se n√£o for v√°lido, ele tentar√° obter um JWT / Cookie atualizado e continuar√°, caso contr√°rio, far√° o seu logout. Sim, mais complicado, mas tamb√©m mais seguro. Espero que ajude! Sinta-se √† vontade para fazer perguntas se estiver interessado - demorei um pouco para descobrir tudo. Eu pessoalmente me pergunto se as pessoas fazem login no Github ou FB etc - provavelmente ok para muitos casos, mas em alguns casos n√£o √© profissional. Eu ainda estou para ver um banco, sa√ļde, nenhuma das minhas contas que eu pago, etc. - fa√ßa login com minha conta do FB. Pode ser apenas uma quest√£o de tempo;)

Quanto à atualização de tokens de acesso;
Não tenho certeza se essa é uma maneira adequada de fazer isso, mas meus tokens de acesso duram muito pouco (um minuto ou mais). Para lidar com problemas de expiração de tokens do lado do cliente, usei essa abordagem;
Cada vez que uma página é carregada, ela verifica se o token expirou; em caso afirmativo, ele o atualiza. No entanto, se ainda for válido, ele chama o método que verifica quanto tempo até a expiração e define o tempo limite que atualizará o token de acesso na expiração. E então repete esse processo enquanto o visitante estiver no site.

callRefreshAuthenticationLater(){
    clearTimeout(this.accessTokenRefreshmentTimeout)
    this.accessTokenRefreshmentTimeout = setTimeout(() => {
      this.refreshAuthentication()
    }, this.authService.howMuchUntilExpiration(this.authService.getToken('access_token')))
  }

Isso retorna milissegundos até a expiração:

howMuchUntilExpiration(token){
    return normalizeTimestamp(jwtDecode(token).exp) - Date.now()
  }

Qualquer feedback sobre esta abordagem seria muito bem-vindo

@kunokdev - Acho que √© um bom come√ßo. Mudei uma fun√ß√£o semelhante que tive que calcular o tempo restante para uma fun√ß√£o que apenas retornou um booleano dependendo se estava expirado ou n√£o e isso tornou meu c√≥digo um pouco mais leg√≠vel e simples, al√©m de n√£o precisar me preocupar em zerar temporizadores. Ent√£o, eu apenas verifico se o usu√°rio expirou ou n√£o em algum tipo de solicita√ß√£o que requer autentica√ß√£o. Se eu tivesse um cron√īmetro de contagem regressiva ou algo parecido que fosse vis√≠vel para o cliente ou para depura√ß√£o, sua fun√ß√£o seria ideal. Esses s√£o meus 2 centavos ūüĎć

O exemplo de autenticação / login não deveria ser o mais básico possível? ou seja, armazenamento de memória e nenhum JWT ou coisas de token estranhas. Normalmente, quando você pensa em alguém "logado", significa que essa pessoa tem um cookie / sessão ativa.

Eu tenho um HOC de login trabalhando no lado do cliente e do servidor. Ele usa um JWT e um backend (pode ser node, django, qualquer que seja).

Confira e qualquer feedback é muito apreciado

https://github.com/hugotox/AppStarter

Código relevante aqui https://github.com/hugotox/AppStarter/blob/master/src/components/auth/login-required.js

@hugotox Eu gosto da ideia de usar Redux store para armazenar dados de autenticação, mas quando você chamar store.dispatch de getInitialProps várias vezes esteja pronto para efeitos colaterais indesejados, quando o componente decorado será renderizado mesmo se o processo de autenticação ainda não terminou. Vamos dar um exemplo de uso do seu código:

export default withRedux(initStore, mapStateToProps)(
   loginRequired([PUBLIC])(MyPage)
)

Em getInitialProps você chama verifyToken antes de verificationOk , então MyPage.mapStateToProps será chamado 2 vezes (se ouvir store.auth.user) e na primeira vez store.auth.user será nulo mesmo para uma página que requer usuário logado.

Ontem eu também lancei a primeira versão WIP do próprio starter kit Next.js, mas comecei com Docker, Flow e fast-redux: https://github.com/dogada/microchain

Eu uso imagens Docker dedicadas para servidor de API e webapp que podem ser executados em diferentes domínios, então ainda estou procurando uma solução de trabalho que permita fazer login de usuários reais, mas também emitir tokens de portador OAuth para clientes móveis, por exemplo.

@spencersmb excelentes elogios! Esta é exatamente a maneira que eu estava fazendo. Em termos de renderização do lado do servidor para uma URL na primeira visita (nunca logado), você está apenas interceptando-a, vendo que não há cookie e redirecionando para uma página do tipo pages / login.js, por exemplo?

@ james-ff Obrigado por postar isso, mesmo que pareça estar gritando no vazio.

Foi dito neste t√≥pico algumas vezes, mas todos aparentemente ainda est√£o ignorando que n√£o deveriam armazenar tokens de sess√£o no JWT com localStorage ou em cookies acess√≠veis em JavaScript e parecem tentar reinventar sess√Ķes e autentica√ß√£o de uma forma menos segura (e isso requer JS do lado do cliente). ūüôÉūü§¶ūüŹĽ‚Äć‚ôāÔłŹ

O autor deste post escreveu muito bem o que h√° de errado nisso em 2016, mas infelizmente as coisas n√£o parecem ter melhorado:

Infelizmente, parece que encontrei o limite superior do comprimento do artigo antes que as pessoas parassem de ler - muitos dos comentaristas no Reddit e no Hacker News continuaram sugerindo as mesmas "solu√ß√Ķes" repetidamente, ignorando completamente que elas j√° foram abordadas e consideradas impratic√°veis no pr√≥prio artigo.

No entanto, tanto o artigo original quanto o diagrama de acompanhamento s√£o muito bons.

@iaincollins JWTs e aplicativos / autentica√ß√£o sem sess√£o t√™m suas vantagens e muitas pessoas / empresas (incluindo o Google) ainda querem us√°-los. Depois de ler o caso contra JWTs , ainda acho que deveria haver dois exemplos / bibliotecas oficiais de next-auth, um usando sess√Ķes (como next-auth) e um usando JWTs, ou talvez apenas um que permita o uso de qualquer um deles. As vantagens, desvantagens e advert√™ncias devem ser explicadas claramente para cada um nas p√°ginas oficiais do tutorial Next.js e / ou na documenta√ß√£o do m√≥dulo em algum lugar. At√© que algu√©m invente um padr√£o / biblioteca melhor, provavelmente continuarei a usar nextjs-starter e next-auth, uma vez que s√£o os melhores que encontrei.

Eu só tenho observado isso casualmente, mas minha experiência com autenticação JS universal é armazenar um JWT em um cookie HttpOnly . Não há realmente nenhuma razão para usar localStorage quando você tem a opção de usar o lado do servidor do aplicativo para armazenar o cookie. Se você precisar acessar o JWT para chamadas de API de origem cruzada no navegador, poderá passar o JWT em um cenário do tipo __INITIAL_STATE__ (esteja ciente das vulnerabilidades XSS, mas pelo menos você não está "armazenando" do lado do cliente). Para acesso de mesma origem, o cookie será passado e para trás (assumindo que você está usando withCredentials para axios, ou credentials: 'include' para buscar), negando a necessidade de colocar o JWT em JS. . Você poderia usar um proxy no lado do servidor do aplicativo para retirar o JWT do cookie HttpOnly , _então_ fazer suas chamadas API de origem cruzada também. Você nega a chamada preflight nesse cenário também. Cada um com o seu, mas pessoalmente não acho que localStorage seja necessário para aplicativos universais.

@bjunc Sim, de todas as op√ß√Ķes de onde um JWT deve ser armazenado (localStorage x cookie HttpOnly x Redux ou o que for), posso estar errado, mas acho que a resposta deve ser basicamente sempre um cookie HttpOnly. Isso parece ter sido afirmado in√ļmeras vezes em v√°rios blogs e f√≥runs. (N√£o tenho certeza sobre tokens de atualiza√ß√£o - talvez eles devam ser armazenados em um cookie HttpOnly tamb√©m?) Eu acho que onde os JWTs s√£o armazenados deve ser uma quest√£o resolvida, al√©m do resto das vantagens / desvantagens dos JWTs.

Tentei fazer mais ou menos exatamente o que voc√™ disse em um projeto meu antes de come√ßar a adotar o nextjs-starter e o next-auth. J√° faz um tempo, mas se bem me lembro, acho que o problema que encontrei foi que meu servidor Express API no qual eu estava autenticando (que estava usando express-session) n√£o estava inicializando / buscando a sess√£o corretamente. Eu teria um comportamento estranho em que as sess√Ķes seriam inicializadas v√°rias vezes. Pretendo voltar a fazer mais ou menos o que voc√™ descreveu se eu puder consertar isso. Tamb√©m continuarei a trabalhar com nextjs-starter e next-auth, uma vez que as sess√Ķes eliminam muitas das outras preocupa√ß√Ķes que os JWTs colocam, como como invalidar tokens.

Novamente, um exemplo oficial (ou exemplos) seria √ļtil. Palavra-chave: oficial, o que significa que os autores do Next.js consideraram todas as possibilidades e incorporaram as melhores id√©ias e pr√°ticas. Idealmente, usando recursos modernos do ES6 / ES7 / ES8, como promises e async / await.

@ kelleg1 , parece que seus problemas est√£o relacionados √†s especificidades da cria√ß√£o de cookies. Por exemplo, voc√™ pode criar acidentalmente v√°rios cookies com o mesmo nome usando configura√ß√Ķes diferentes ( HttpOnly , dom√≠nio, caminho, expira√ß√£o, etc.); o que pode criar efeitos colaterais estranhos como voc√™ est√° descrevendo. Uma maneira de depurar isso √© usar as ferramentas de desenvolvimento Aplicativo-> Cookies. Se voc√™ vir um monte de cookies com o mesmo nome, isso pode indicar a dire√ß√£o certa.

De qualquer forma, n√£o estou na equipe principal, ent√£o n√£o posso ajudar com uma contribui√ß√£o "oficial" (e, na verdade, estou usando Nuxt.js, n√£o Next.js), mas os princ√≠pios s√£o os mesmos. Experimentei algumas maneiras diferentes de fazer isso (pesando os pr√≥s / contras de JWT, cookies, CSFR, websocket CSWSH, localStorage, etc.). Por fim, cheguei √† conclus√£o de que a natureza universal do Next / Nuxt se prestava bem ao uso de cookies HttpOnly JWT. Talvez outros cheguem a uma conclus√£o diferente, mas eu pessoalmente n√£o estou no campo de "oh Deus, n√£o use o JWT, voc√™ n√£o leu aquele artigo que diz que o JWT causa c√Ęncer !?".

@iaincollins, desculpe trazer isso de volta, mas todos os tutoriais na web usam localStorage para salvar o token e você está dizendo que é inseguro. Em caso afirmativo, onde devemos armazenar o token?

BISCOITOS! : D
usamos algo assim:

// auth.js
async signIn(res, info) {
    const { email, password } = info;
    const result = await this.service.signIn(email, password);
    if (!result) {
      res.status(HttpStatus.BAD_REQUEST).json({ success: false, message: 'Wrong email and/or password' });
      return;
    }
  const payload = {
    scope: 'appUser',
    userId: user.email,
    language: user.language,
    iat: moment().unix(),
    exp: moment().add(7, 'days').unix(),
    type: user.type,
    status: user.status
  };
    const token = jwt.sign(payload, ...);

    res.cookie('token', token, { domain: 'yourdomain.com', path: '/', secure: true, httpOnly: true, maxAge: 24 * 60 * 60 * 1000 * 7, signed: true });

    res.status(HttpStatus.OK).json({});
  }

// pages/index.js

class Index extends PureComponent {
  render() {
    return (
      <Layout title="home">
        <Home />
      </Layout>
    );
  }
}

Index.getInitialProps = async ({ req, res }) => {
  const auth = req ? getServerSideToken(req) : getClientSideToken();
  return { auth };
}
export default Index;

// utils/auth.js
const decode = ({ token }) => {
  const decoded = jwt.decode(token);
  const { userId, type = 'anonymous', status, language = 'en' } = decoded || {};
  return { user: { email: userId, type, status, language } };
};

export const getServerSideToken = (req) => {
  const { signedCookies } = req;

  if (!signedCookies) {
    return {};
  }
  try {
    return decode(signedCookies);
  } catch (parseError) {
    console.error(parseError, signedCookies);
    return {};
  }
};

export const getClientSideToken = () => {
  if (typeof window !== 'undefined') {
    const user = window.__USER__ || {};
    return { user };
  }
  return { user: {} };
};

// pages/_document.js
export default class extends Document {
  static async getInitialProps(ctx) {
    const props = await Document.getInitialProps(ctx);
    const info = getServerSideToken(ctx.req);
    return { ...props, ...info };
  }

  render() {
    const { user = {} } = this.props;
    const json = JSON.stringify(user);
    return (
      <html lang="en">
        <Head>
          <meta name="viewport" content="width=device-width, initial-scale=1" />
          <meta charSet="utf-8" />
          <link href="//fonts.googleapis.com/css?family=Kadwa:400,700|Work+Sans:100,300,600" rel="stylesheet" />
          <link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.2.14/semantic.min.css" />
          <link rel="stylesheet" href="/static/site.css" />
        </Head>
        <body>
          <Main />
          <script
            dangerouslySetInnerHTML={{ __html: `__USER__ = ${json};` }}
          />
          <NextScript />
        </body>
      </html>
    );
  }
}

// somewhere.js
import axios from 'axios';
axios.defaults.withCredentials = true;
axios.post(`${apiBaseUrl}/some/path`, data)...

// somemiddleware.js
      const { signedCookies = {} } = req;
      const { token = '' } = signedCookies;
      if (token) {
        try {
          const info = jwt.verify(token, ...);
          req.user = await this.getUser(info.userId);
          if (req.user) {
            next();
            return;
          }
        } catch (err) {
          console.error({ permissionError: err });
          return res.status(500).json({...});
        }
      }
      return res.status(403).json({...});

Um pouco confuso, mas muito seguro, pois o javascript do lado do cliente nunca vê um token e o cookie é httpSomente, seguro, assinado e enviado automaticamente por axios ou outro ...

Oi pessoal acabei de criar um exemplo de autenticação com cookies e redux. Veja aqui https://github.com/zeit/next.js/pull/4011

Espere, então onde esse problema foi parar? Nunca consegui encontrar um exemplo de autenticação Express no repositório oficial.

Vejo muitas conversas sobre cookies e sess√Ķes, mas como isso funciona para meu aplicativo m√≥vel nativo quando ele precisa acessar a API?

Isso pode ser feito, mas é para isso que serve o JWT: p

Acabei de fazer uma leitura detalhada de todo este tópico e me sinto compelido a resumir minhas descobertas.

Parece que h√° dois projetos iniciais vi√°veis ‚Äč‚Äčcom m√≥dulos de autentica√ß√£o s√≥lidos fatorados:

Excelente trabalho de @iaincollins e @nmaro !

Obrigado @curran :)

Documentei todas as altera√ß√Ķes de c√≥digo que fiz para eliminar os aspectos estranhos de nextjs-starter nesta solicita√ß√£o de pull https://github.com/iaincollins/nextjs-starter/pull/86

Isso pode estar se aproximando de um exemplo sólido de autenticação básica para o repositório Next.js.

Recentemente, tive uma necessidade de implementar o OAuth com o Office 365, então pensei em compartilhar um exemplo muito simples que apresentei aqui . Ele precisa de trabalho (e não está nem perto de ser tão desenvolvido quanto alguns dos exemplos acima), mas acho que poderia ser generalizado eventualmente para usar vários clientes OAuth também. Ele utiliza vários dos exemplos já mostrados no repositório de exemplos Next.js, bem como o encadeamento de rotas protegidas aqui . Em qualquer caso, apenas pensei em compartilhar, caso alguém quisesse um exemplo rápido de como (talvez) fazer isso com a Microsoft.

Para qualquer pessoa interessada em uma autenticação tokenizada JWT simples que funcione no lado do cliente e do servidor, recebi ajuda no bate-papo do Spectrum e decidi compartilhar com todos vocês. Qualquer feedback é sempre apreciado.

https://github.com/bgold0/nextjs-auth-skeleton

Oi, pessoal!
Aqui est√° outro exemplo de autentica√ß√£o com next.js que criei alguns meses atr√°s, talvez algu√©m ache √ļtil:

https://github.com/alan2207/nextjs-jwt-authentication

Ooth 2.0 foi lançado com novos e melhores documentos

Ooth é um sistema de gerenciamento de identidade de usuário criado para node.js (com next.js em mente).

Estratégias atualmente suportadas:

  • Principal: nome de usu√°rio / senha (incl. Verificar e-mail, esqueci o pw etc.), convidado, facebook, google
  • Secund√°rio: sess√Ķes baseadas em cookies, JWTs

Confira este exemplo ao vivo que coloca tudo junto com next.js ( código-fonte ).

Muitos dos exemplos de autentica√ß√£o aqui (e na pasta de exemplos) retornam a sess√£o do usu√°rio / token / etc de getInitialProps . Pelo que entendi, quando a p√°gina √© renderizada no lado do servidor, isso significa que as informa√ß√Ķes da sess√£o do usu√°rio ser√£o enviadas como parte da resposta da p√°gina HTML (como parte de NEXT_DATA ) para o navegador.

Vejo dois problemas de segurança com este padrão quando getInitialProps é executado no lado do servidor:
1) A sess√£o do usu√°rio √© transmitida pela rede do servidor para o navegador. Se alguma dessas solicita√ß√Ķes estiver usando http:// e n√£o https:// , o token do usu√°rio, etc., seria exposto na rede em texto simples.

2) A sessão do usuário é retornada do servidor para o navegador como parte da página HTML (em uma tag de script NEXT_DATA ). Ter o token / etc do usuário diretamente na página HTML parece arriscado, especialmente depois que a página é analisada, renderizada pelo navegador e outros scripts de terceiros podem agora estar em execução.

Essas quest√Ķes j√° foram tratadas? Existem atenua√ß√Ķes para essas amea√ßas?

√Č por isso que uso cookies. Veja meu exemplo aqui https://github.com/hugotox/nextjs-starter/blob/master/pages/_app.js

Finalmente! Aqui você pode encontrar um exemplo de autenticação next.js totalmente dockerizado com os seguintes contêineres:

  • next.js
  • microsservi√ßo de autentica√ß√£o (ooth)
  • api (graphql)
  • armazenamento de sess√£o (redis)
  • pequeno proxy reverso

Tudo é reunido com docker-compose.

Nota r√°pida sobre JWTs. Os JWTs t√™m a vantagem de ser sem estado, bons para dispositivos m√≥veis e bons se voc√™ precisar passar credenciais de um dom√≠nio para outro. A principal desvantagem √© que eles exp√Ķem o navegador ao XSS. Para este exemplo, optei por uma solu√ß√£o baseada em sess√Ķes de cookies puras. Ainda consegui dividir as coisas em microsservi√ßos gra√ßas ao proxy reverso (todos os microsservi√ßos rodam no mesmo dom√≠nio) e ao armazenamento de sess√£o compartilhada.

https://github.com/nmaro/staart/tree/master/examples/staart
O exemplo ao vivo é, como de costume: https://staart.nmr.io

Acho que √© prudente esclarecer, o uso do JWT n√£o "exp√Ķe" intrinsecamente voc√™ ao XSS. Em vez disso, se o seu site tiver uma vulnerabilidade XSS (n√£o devido ao pr√≥prio JWT), um JWT pode estar comprometido (junto com qualquer outra informa√ß√£o acess√≠vel por script); enquanto os cookies httpOnly n√£o estar√£o acess√≠veis. Esque√ßa que voc√™ pode usar um JWT como o valor de um cookie httpOnly !

Solu√ß√Ķes somente de cookies podem funcionar bem para comunica√ß√£o no mesmo dom√≠nio, mas se voc√™ tiver uma API sem interface (por exemplo, example.com chamando api.example.com ), ent√£o essa n√£o √© realmente uma solu√ß√£o, a menos que voc√™ queira usar o proxy do navegador solicita√ß√Ķes de example.com a api.example.com fazendo suas chamadas de API para example.com e encaminh√°-las com o cookie anexado √† solicita√ß√£o (que vem com seu pr√≥prio conjunto de pr√≥s / contras) .

Pessoalmente, sinto que os contras do JWT s√£o amplamente exagerados e s√£o facilmente mitigados por meio de uma s√©rie de prote√ß√Ķes comumente implementadas. N√£o menos importante, uma lista negra de tokens referenciando a declara√ß√£o jti (por exemplo, UUID da vers√£o 4) no caso de o token ter sido comprometido antes da expira√ß√£o.

Ei @bjunc sim, obrigado pelo esclarecimento. Correto, o JWT por si s√≥ n√£o o exp√Ķe ao XSS. Com rela√ß√£o √†s suas outras observa√ß√Ķes, gostaria de acrescentar que cada uma delas tem suas armadilhas.

Esqueça que você pode usar um JWT como o valor de um cookie httpOnly!

Sim, gostaria apenas de acrescentar que isso remove a √ļnica vantagem do JWT de transferir credenciais entre dom√≠nios.

uma lista negra de tokens

Isso, e a outra prática comum de um token de atualização, remove a outra vantagem do JWT de ser realmente sem estado.

Este é o meu entendimento da situação:

  • Se voc√™ precisar de autentica√ß√£o em v√°rios locais, use JWT <- mas, se poss√≠vel, evite devido √† seguran√ßa
  • Se voc√™ precisar se autenticar em qualquer cliente que n√£o seja um navegador e n√£o tenha o problema de XSS (por exemplo, um desktop ou aplicativo m√≥vel), use JWT
  • Caso contr√°rio, use sess√Ķes baseadas em cookies, porque uma solu√ß√£o baseada em JWT ser√° menos segura (XSS) ou n√£o ser√° realmente sem estado (listas negras), ou exigir√° que voc√™ use um proxy para manter tudo sob o mesmo dom√≠nio de qualquer maneira.

Eu escrevi um artigo do Medium sobre Next.js Authentication / User accounts.
√Č um tutorial extenso e meu braindump de quase dois anos de desenvolvimento de tempo livre e pensamento (meu primeiro coment√°rio sobre esta quest√£o √© de fevereiro de 2017).

https://medium.com/the-ideal-system/user-accounts-with-next-js-an-extensive-tutorial-6831cdaed16b

Voc√™ continua correlacionando o JWT com ser menos seguro. O JWT n√£o torna o seu site menos seguro. N√£o √© em si uma vulnerabilidade XSS. Se voc√™ tiver um exploit XSS, voc√™ ter√° os mesmos problemas de qualquer maneira. Mesmo com um cookie httpOnly , o invasor pode n√£o ser capaz de ler o valor do cookie, mas n√£o importa porque eles podem executar c√≥digo arbitr√°rio - como solicita√ß√Ķes XHR que passariam automaticamente os cookies de sess√£o (essencialmente agindo como um ataque CSRF). Se sua API √© de dom√≠nio cruzado e voc√™ est√° fazendo solicita√ß√Ķes de navegador para servidor, ent√£o o JWT est√° em algum lugar no c√≥digo de qualquer maneira (seja no estado inicial ou localStorage). Se voc√™ usa o Axios, pode at√© ter definido padr√Ķes globais, onde o invasor precisa apenas fazer uma solicita√ß√£o do Axios e nem mesmo se preocupar com a autentica√ß√£o.

Al√©m disso, voc√™ n√£o pode realmente falar sobre XSS sem falar tamb√©m sobre CSRF; onde os cookies de autentica√ß√£o s√£o especificamente direcionados. Mesmo com uma configura√ß√£o de proxy reverso, um ataque CSRF permitiria ao invasor executar solicita√ß√Ķes autenticadas em sua API.

A prop√≥sito, s√≥ porque voc√™ colocou o JWT em um cookie (por exemplo, saber se o usu√°rio est√° conectado), n√£o significa que voc√™ est√° impedido de usar o valor do cookie (por exemplo, um JWT) para servidor de dom√≠nio cruzado para Acesso ao servidor API no carregamento da p√°gina (que tamb√©m funciona para o cen√°rio de proxy reverso). Voc√™ tamb√©m n√£o est√° ou est√° impedido de passar o JWT no estado inicial para solicita√ß√Ķes de navegador para servidor de API. Eles n√£o s√£o mutuamente exclusivos.

Como um aparte, acho a ideia de JWT "sem estado" superestimada e limitada na aplicação para a maioria dos casos de uso. Por exemplo:

  • Permiss√Ķes baseadas em recursos / din√Ęmicas (por exemplo, n√£o apenas " can edit Post ", mas " can edit Post:1634 ").
  • E se a conta do usu√°rio foi bloqueada / exclu√≠da?
  • N√£o pagou sua assinatura mensal; qual funcionalidade de aceleradores?
  • Colocou o token na lista negra (conforme acima)?

Voc√™ n√£o est√° embutindo tudo isso no JWT, o que significa que voc√™ precisa mergulhar na camada de dom√≠nio (ou seja, banco de dados) para descobrir. Voc√™ acabou de carregar o recurso, ent√£o pode muito bem coloc√°-lo onde o resto do aplicativo pode acess√°-lo, e agora voc√™ tem o estado. Acho muito bobo pensar que tudo o que voc√™ precisa saber sobre o assunto estaria inclu√≠do no token; ao mesmo tempo que o mant√©m an√īnimo e leve. Sem divagar muito, h√° um argumento para solicita√ß√Ķes "sem estado" na comunica√ß√£o entre servi√ßos, mas mesmo isso eu acho impratic√°vel (pelo menos no que se refere ao conceito de colocar o que voc√™ precisa saber sobre o assunto no JWT). .

Outras estratégias de autenticação disponíveis entretanto (novas em negrito):

  • Local (nome de usu√°rio / e-mail / senha)
  • Facebook
  • Google
  • H√≥spede
  • Patreon
  • Twitter
  • Authy (Twilio) - sem senha via SMS

@jaredpalmer você escreveu
Como o php, a unidade at√īmica do Next √© a p√°gina. Um dos recursos mais legais √© que ele carrega lentamente cada p√°gina apenas quando solicitado. Com autentica√ß√£o apenas do lado do cliente, mas com renderiza√ß√£o do servidor, o js para aquela p√°gina protegida √© de fato baixado pelo navegador. No futuro, quando o Next adicionar fluxos de trabalho do servidor, voc√™ poder√° bloquear a renderiza√ß√£o e redirecionar no servidor para evitar isso completamente. Isso exigir√° cookies, sess√Ķes e armazenamentos de sess√£o AFAIK, mas esse √© apenas o custo de fazer aplicativos h√≠bridos como esses.

Estamos 2 anos depois. Existe um fluxo de trabalho do servidor para evitar o carregamento de js para p√°ginas protegidas?
@timneutkens talvez
Como posso impedir totalmente o acesso ao conte√ļdo protegido?

@lishine Você tem um ServerResponse no getInitialProps de sua página - você pode facilmente redirecionar alguém sem privilégios.

Existe um exemplo de auth com redux?

Existe um exemplo de auth com redux?

Você pode tentar este exemplo que está usando redux e verificar se funciona para você ...
Você pode encontrá-lo em algum lugar neste tópico, mas caso você não consiga encontrá-lo, aqui está:
https://github.com/alan2207/nextjs-jwt-authentication

Acho que esse é um problema mais complicado ao usar os resultados da chamada da API do lado do servidor getInitialProps, porque o Virtual DOM usa resultados antigos após a ação LOGOUT-LOGIN. Estou pensando em solução

_EDITADO_
e aqui est√° minha resposta com redux-observ√°vel

| Lado | Auth | TODO |
| --- | --- | --- |
| Servidor | true | Buscar dados iniciais (com proxy de cookie de solicitação).
| Servidor | false | Mostra a p√°gina de login e busca dados depois de logado. |
| Cliente | true | Buscar dados iniciais. |
| Cliente | false | Mostra a página de login e busca dados após o login. (Isso acontece apenas quando a sessão expirou na mudança de página para página) |

  static async getInitialProps({ store, query: { rowsPerPage, pageIndex }, req, auth }) {
    store.dispatch(TemporaryStoryActions.initPageState());

    const isAuthenticated = () => req ? req.isAuthenticated()
      : store.getState().auth.isAuthenticated;

    if (isAuthenticated()) {
      // fetch initial data
      const TemporaryStoryApiProxy = withCookieProxy(req, TemporaryStoryApi);
      await TemporaryStoryApiProxy.fetchTemporaryStories({
        rowsPerPage: rowsPerPage || 15,
        pageIndex: pageIndex || 0,                                                                                                                                  }).then(json => {
        store.dispatch(TemporaryStoryActions.loadTemporaryStories(
          json.rowsPerPage, json.pageIndex, json.count, json.rows));
      }).catch(error => {
        if (error.response && error.response.status === 403) {
          store.dispatch(AuthActions.initState(false, null));
          return;
        }
        throw error;
      });
    }

    if (!isAuthenticated()) {
      // => if client side fetch failed with 403, isAuthenticated() turns off to false
      // register logined action for client side login succeeded
      const reloadAction = TemporaryStoryActions.fetchTemporaryStories({
        rowsPerPage: rowsPerPage || 15,
        pageIndex: pageIndex || 0,
      });
      store.dispatch(AuthActions.addLoginedAction(reloadAction));
    }

    return {
      ...store.getState(),
    }                                                                                                                                                           }                                                                                             }
export const withLogin = Page => class SecurePage extends React.Component {
  static async getInitialProps (ctx) {
    if (ctx.req && ctx.store) {
      // server side
      const isAuthenticated = ctx.req.isAuthenticated();
      const { user } = ctx.req;
      ctx.store.dispatch(AuthActions.initState(isAuthenticated, user));
    }
    return Page.getInitialProps && await Page.getInitialProps(ctx)
  }

  render () {
    const { auth } = this.props;
    return auth.isAuthenticated ? <Page {...this.props} /> : <LoginPage />
  }                                                                                                                                                           }
// when [front-end server] => [api server]
// on Server Side Rendering,
// needs to proxy Cookies which sent to Next.js page request
export const withCookieProxy = (req, targetApi) => {
  if (!req) {
    return targetApi;
  }
  targetApi.client.interceptors.request.use(config => {
    const cookieString = Object.keys(req.cookies).map(key => `${key}=${req.cookies[key]}`).join('; ');
    const headers = {
      ...(config.headers || {}),
      Cookie: cookieString,
    };
    return {
      ...config,
      headers: headers,
    };
  }, error => {
    return Promise.reject(error);
  });
  return targetApi;
};
const loginEpic = (action$, state$) => action$.pipe(
  ofType(AuthActionTypes.login),
  mergeMap(action => {
    const email = action.payload.email;
    const password = action.payload.password;
    return from(AuthApi.login(email, password))
      .mergeMap(json => {
        const user = json.user;
        const loginedActions = state$.value.auth.loginedActions;
        const successActions = [
          AuthActions.removeAllLoginedActions(),
          ...loginedActions,
          AuthActions.loginSuccess(user.id, user.name, user.last_login_date),
        ];
        return from(successActions);
      }).pipe(catchError(error => {
        return of$(AuthActions.loginFail(error));
      }));
  }));

Parece complicado quando algo simples serve, como:

export const withAuthSync = WrappedComponent => class extends Component {
  componentDidMount() {
    window.addEventListener('storage', this.syncLogout);
  }

  componentWillUnmount() {
    window.removeEventListener('storage', this.syncLogout);
    window.localStorage.removeItem('logout');
  }

    syncLogout = (event) => {
      if (event.key === 'logout') {
        console.log('logged out from storage!');
        window.location.reload();
      }
    };

    render() {
      return <WrappedComponent {...this.props} />;
    }
};

Este exemplo foi mesclado como parte do Next.js 8
https://github.com/zeit/next.js/tree/canary/examples/with-cookie-auth

@timneutkens obrigado pelo link.

olhando para https://github.com/zeit/next.js/blob/canary/examples/with-cookie-auth/www/utils/auth.js#L26 -L34 ... n√£o deveria haver algum tipo de verificar depois que auth() foi chamado?

Testar o exemplo sem um cookie faz com que Profile.getInitialProps() seja chamado, enquanto eu pensei que o redirecionamento aconteceria antes mesmo de tentar obter mais "adereços iniciais" ...

Fiz um exemplo aqui que tem pré-renderização + autenticação do lado do servidor com apollo

https://github.com/HorizonShadow/apollo-next-now-test

Lembre-se de que as diretrizes de seguran√ßa do OWASP n√£o recomendam o armazenamento do token JWT no armazenamento local, ou seja, "Um √ļnico Cross Site Scripting pode ser usado para roubar todos os dados nesses objetos, portanto, novamente, √© recomendado n√£o armazenar informa√ß√Ķes confidenciais no armazenamento local."

Aqui est√° Auth0: onde armazenar tokens e Tom Abbott: onde armazenar seus JWTs - Cookies vs armazenamento da Web HTML5 .

Aqui est√° um exemplo com servidor proxy Nuxt.js + Express.js + backend Django. Onde o servidor Express √© usado para proxy de solicita√ß√£o de autentica√ß√£o para o back-end real e est√° lidando com prote√ß√£o CSRF ao usar o token JWT armazenado em um cookie (imp√Ķe algumas restri√ß√Ķes no comprimento do token / quanta informa√ß√£o pode ser armazenada no token JWT): https: / /github.com/danjac/nuxt-python-secure-example

@timneutkens Eu preciso de alguns documentos sobre como enviar token do cookie ūüć™ para o middleware redux personalizado SSR. Estou recebendo os cookies dentro de _app.js. Mas como devo pass√°-lo para customApimiddleware. Onde escrevi solicita√ß√Ķes de busca. Obrigado

Eu escrevi um artigo do Medium sobre Next.js Authentication / User accounts.
√Č um tutorial extenso e meu braindump de quase dois anos de desenvolvimento de tempo livre e pensamento (meu primeiro coment√°rio sobre esta quest√£o √© de fevereiro de 2017).

https://medium.com/the-ideal-system/user-accounts-with-next-js-an-extensive-tutorial-6831cdaed16b

Acho que este √© um dos melhores tutoriais para lidar com a autentica√ß√£o em um aplicativo nextj.js. J√° vi coisas como armazenar tokens em localStorage (XSS), armazenar tokens em cookies (sem manipular CSRF) e at√© mesmo armazenar tokens em cookies do navegador (vulner√°veis ‚Äč‚Äča XSS e CSRF).

Eu realmente gosto da sua solu√ß√£o com o proxy reverso e compartilhar as informa√ß√Ķes da sess√£o entre diferentes servi√ßos. Eu realmente gostaria de n√£o criar um servidor personalizado para o aplicativo next.js, mas acho que √© a maneira mais direta de lidar com sess√Ķes e evitar csrf (e talvez adicionar o proxy reverso). Posso at√© acabar criando um projeto monolith (tanto para renderizar o aplicativo quanto para lidar com opera√ß√Ķes de banco de dados, etc.).

Eu vi que algumas pessoas (incluindo ZEIT) mant√™m as APIs sem estado e permitem que o aplicativo next.js cuide da sess√£o. Ele passa os tokens para APIs. Mas ir com as sess√Ķes apenas torna as coisas um pouco mais apertadas e menos complicadas.

Seria realmente melhor ter um exemplo de autenticação completo para next.js. Com coisas como autenticação para APIs externas, manter a sessão no aplicativo next.js, compartilhar a sessão entre serviços ou passar tokens para eles e talvez até mesmo atualizar os tokens se eles estiverem expirados. (Muitas pessoas escrevem muito sobre JWTs e apenas os usam em seus tutoriais, mas na maioria das vezes nem os expiram ou nem mesmo os atualizam.)

De qualquer forma, você escreveu um dos tutoriais mais completos sobre o assunto. Então, obrigado!

Eu realmente espero que haja exemplos e documentação muito mais completos e claros.

Seria realmente melhor ter um exemplo de autenticação completo para next.js. Com coisas como autenticação para APIs externas, manter a sessão no aplicativo next.js, compartilhar a sessão entre serviços ou passar tokens para eles e talvez até mesmo atualizar os tokens se eles estiverem expirados. (Muitas pessoas escrevem muito sobre JWTs e apenas os usam em seus tutoriais, mas na maioria das vezes nem os expiram ou nem mesmo os atualizam.)

Eu também não sei qual abordagem escolher.
Muito obrigado pelo link para o artigo.
Atualmente, qual das implementa√ß√Ķes voc√™ escolheu?
Você encontrou um exemplo de autorização abrangente para a próxima v9.3 +?

Vale a pena conferir a nova abordagem baseada em cookies do Auth0
(Claro que isso √© para um provedor de identidade espec√≠fico, mas a abordagem pode ser √ļtil para ver)
https://github.com/auth0/nextjs-auth0

  • Muito legal que voc√™ possa "proxy" de solicita√ß√Ķes de API por meio das rotas de API do nextjs (mesmo por meio de uma rota din√Ęmica)
  • Ent√£o voc√™ nunca ter√° que expor tokens de acesso etc para o lado do cliente (j√° que as rotas nextjs api s√≥ executam no lado do servidor), o lado do servidor pode obter tokens de acesso etc por meio da biblioteca auth0 e cookie com um segredo
  • Seu c√≥digo do lado do cliente chamaria suas rotas de api do nextjs, e as rotas de api executariam a solicita√ß√£o de api real

Tenha em mente que eles dizem que esta abordagem é "experimental" no ReadMe

Vale a pena conferir a nova abordagem baseada em cookies do Auth0
(Claro que isso √© para um provedor de identidade espec√≠fico, mas a abordagem pode ser √ļtil para ver)
https://github.com/auth0/nextjs-auth0

  • Muito legal que voc√™ possa "proxy" de solicita√ß√Ķes de API por meio das rotas de API do nextjs (mesmo por meio de uma rota din√Ęmica)
  • Ent√£o voc√™ nunca ter√° que expor tokens de acesso etc para o lado do cliente (j√° que as rotas nextjs api s√≥ executam no lado do servidor), o lado do servidor pode obter tokens de acesso etc por meio da biblioteca auth0 e cookie com um segredo
  • Seu c√≥digo do lado do cliente chamaria suas rotas de api do nextjs, e as rotas de api executariam a solicita√ß√£o de api real

Tenha em mente que eles dizem que esta abordagem é "experimental" no ReadMe

Este artigo √© muito √ļtil e cobre muitas arquiteturas diferentes.
https://auth0.com/blog/ultimate-guide-nextjs-authentication-auth0/

Usar rotas de API como proxy, fazer login / logout por meio de rotas de API, obter o token da API, configurá-lo como cookie HttpOnly é uma abordagem sólida, eu acho.
Uma preocupação pode ser CSRF, mas você pode facilmente criar alguma solução com o pacote csrf npm (não csurf , mas isso também pode funcionar).

@onderonur , obrigado pelo artigo auth0.
ou seja, no momento há um exemplo confiável ou mínimo de implementação em jwt puro com next.js?
Não quero fazer uma camada avançada com cookies e configurá-los. No aplicativo csr, simplesmente armazenamos o token em localstorage e o enviamos junto com a solicitação.

@onderonur , obrigado pelo artigo auth0.
ou seja, no momento há um exemplo confiável ou mínimo de implementação em jwt puro com next.js?
Não quero fazer uma camada avançada com cookies e configurá-los. No aplicativo csr, simplesmente armazenamos o token em localstorage e o enviamos junto com a solicitação.

Eu usei esse método para um de meus repositórios, mas ainda está em rascunho, então certifique-se de testá-los você mesmo :)
https://github.com/onderonur/post-gallery
Na verdade, a "camada de cookies" não é uma coisa avançada. Basta chamar o ponto de extremidade de login da API por meio de /api/login rota da API e, se a solicitação for bem-sucedida, defina o token em um cookie httpOnly .
Você pode verificar meu repo para a mesma implementação exata.

Uma outra opção é (se você quiser ter quase o mesmo fluxo da configuração do token no armazenamento local), você pode usar o pacote js-cookie npm, chamar seu ponto de extremidade de login com uma solicitação do lado do cliente e terminar se ele retornar um token, configure-o em um cookie. E quando você faz uma solicitação (por meio de um interceptor axios etc.), leia o valor do cookie e o passe para sua API como um cabeçalho de solicitação. Já vi muitos aplicativos (e até mesmo alguns populares) usando essa abordagem. Mas isso é um pouco inseguro. Porque você não pode definir cookies de httpOnly no navegador. Assim, o JavaScript será capaz de ler seu cookie de token. Assim, haverá vulnerabilidade XSS.

Agradecemos que este seja um t√≥pico antigo (e um t√≥pico de longa dura√ß√£o em geral), mas para aqueles que procuram refer√™ncias ou exemplos adicionais, come√ßamos o trabalho em NextAuth.js v2 recentemente. Menciono n√£o tanto como um plug - √© um projeto de c√≥digo aberto e um monte de gente ajudou nele - mas √© super simples de usar e o c√≥digo e abordagem podem ser √ļteis como uma refer√™ncia para as pessoas.

Para alguns antecedentes, como NextAuth v1, ele usa cookies que são assinados, prefixados e apenas HTTP, evitando as armadilhas de segurança comuns de usar tokens do lado do cliente.

NextAuth.js v2 suporta login com Apple, Google, Facebook, Twitter, GitHub, Auth0, Okta, Slack, Discord e outros provedores de OAuth (suporta 1.xe 2.x). Você pode usá-lo com MySQL, MariaDB, Postgres, MongoDB - ou nenhum banco de dados (apenas OAuth e JSON Web Tokens para uma solução 100% sem servidor).

O uso é muito simples, há um método estático universal chamado session() e um React Hook chamado useSession() você pode usar nos componentes do lado do cliente:

import { useSession } from 'next-auth/client'

export default () => {
  const [session, loading] = useSession()

  return <>
    {!loading && session && <p>Signed in as {session.user.name || session.user.email}.</p>}
    {!loading && !session && <p><a href="/api/auth/signin">Sign in here</a></p>}
  </>
}

Ele é construído para Next.js 9.xe Serverless, e não tem dependências como Express ou PassportJS. Inclui um provedor de autenticação que você pode usar em _app.js para adicionar automaticamente o estado de autenticação a todas as páginas; ele funciona para renderização do lado do cliente e do servidor.

Para obter mais informa√ß√Ķes, consulte next-auth.js.org ou confira next-auth @ beta no NPM

Ainda é um trabalho em andamento - ainda estamos aprimorando a documentação e o modelo de evento - com uma data de lançamento prevista para o início de meados de junho.

Agradecemos que este seja um t√≥pico antigo (e um t√≥pico de longa dura√ß√£o em geral), mas para aqueles que procuram refer√™ncias ou exemplos adicionais, come√ßamos o trabalho em NextAuth.js v2 recentemente. Menciono n√£o tanto como um plug - √© um projeto de c√≥digo aberto e um monte de gente ajudou nele - mas √© super simples de usar e o c√≥digo e abordagem podem ser √ļteis como uma refer√™ncia para as pessoas.

Para alguns antecedentes, como NextAuth v1, ele usa cookies que são assinados, prefixados e apenas HTTP, evitando as armadilhas de segurança comuns de usar tokens do lado do cliente.

NextAuth.js v2 suporta login com Apple, Google, Facebook, Twitter, GitHub, Auth0, Okta, Slack, Discord e outros provedores de OAuth (suporta 1.xe 2.x). Você pode usá-lo com MySQL, MariaDB, Postgres, MongoDB - ou nenhum banco de dados (apenas OAuth e JSON Web Tokens para uma solução 100% sem servidor).

O uso é muito simples, há um método estático universal chamado session() e um React Hook chamado useSession() você pode usar nos componentes do lado do cliente:

import { useSession } from 'next-auth/client'

export default () => {
  const [session, loading] = useSession()

  return <>
    {!loading && session && <p>Signed in as {session.user.name || session.user.email}.</p>}
    {!loading && !session && <p><a href="/api/auth/signin">Sign in here</a></p>}
  </>
}

Ele é construído para Next.js 9.xe Serverless, e não tem dependências como Express ou PassportJS. Inclui um provedor de autenticação que você pode usar em _app.js para adicionar automaticamente o estado de autenticação a todas as páginas; ele funciona para renderização do lado do cliente e do servidor.

Para obter mais informa√ß√Ķes, consulte next-auth.js.org ou confira next-auth @ beta no NPM

Ainda é um trabalho em andamento - ainda estamos aprimorando a documentação e o modelo de evento - com uma data de lançamento prevista para o início de meados de junho.

√ďtimo trabalho isso!
Isso pode ser usado apenas no lado do cliente? Por exemplo, eu tenho um aplicativo Rails API - e uso o próximo JS para o lado do cliente.

Esta p√°gina foi √ļtil?
0 / 5 - 0 avalia√ß√Ķes

Quest√Ķes relacionadas

rauchg picture rauchg  ¬∑  3Coment√°rios

wagerfield picture wagerfield  ¬∑  3Coment√°rios

havefive picture havefive  ¬∑  3Coment√°rios

knipferrc picture knipferrc  ¬∑  3Coment√°rios

pie6k picture pie6k  ¬∑  3Coment√°rios