Next.js: Login-/Authentifizierungsbeispiel hinzuf├╝gen

Erstellt am 29. Okt. 2016  ┬Ě  208Kommentare  ┬Ě  Quelle: vercel/next.js

Mit:

  • wiederverwendbarer Authentifizierungshelfer ├╝ber Seiten hinweg
  • Sitzungssynchronisierung zwischen Registerkarten
  • einfaches passwortloses E-Mail-Backend, gehostet auf now.sh

Ich denke, das wird vielen Neulingen sehr helfen.

p0

Hilfreichster Kommentar

So habe ich auth, die schwimmend arbeitet. Wie an anderer Stelle erw├Ąhnt, ist es nur clientseitig, was letztendlich nur die halbe Miete ist.

"Ziemlich sicher"

Wie bei PHP ist die atomare Einheit von Next die Seite. Eine der coolsten Funktionen ist, dass jede Seite nur dann geladen wird, wenn sie angefordert wird. Bei nur clientseitiger Authentifizierung, aber beim Server-Rendering wird das js f├╝r diese gesch├╝tzte Seite tats├Ąchlich vom Browser heruntergeladen. Wenn Next in Zukunft Server-Workflows hinzuf├╝gt, k├Ânnen Sie hoffentlich das Rendern und die Umleitung auf dem Server blockieren, um dies vollst├Ąndig zu verhindern. Dies erfordert Cookies, Sitzungen und AFAIK-Sitzungsspeicher, aber das sind nur die Kosten f├╝r solche Hybrid-Apps.

Auth-Beispiel

Angenommen, Sie haben eine JWT-gesicherte API mit zwei interessierenden Endpunkten: /token und /me . /token akzeptiert E-Mail-/Passwort-Anmeldeinformationen und gibt ein signiertes JWT ( id_token ) zur├╝ck, w├Ąhrend /me Profilinformationen zum JWT-authentifizierten Benutzer zur├╝ckgibt. Ich habe das folgende AuthService.js aus der Sperre von Auth0 angepasst (Entfernen des Ereignissenders, obwohl das nicht die schlechteste Idee ist). Es extrahiert fast das gesamte JWT-Token-Handling, sodass es auf der Anmeldeseite und auch in einer Komponente h├Âherer Ordnung verwendet werden kann (dazu sp├Ąter mehr).

// 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())
  }
}

Als n├Ąchstes folgt ein HOC, um den Schutz von Seiten zu vereinfachen. Um ein ungewolltes Aufblitzen sensibler Informationen zu verhindern, wird die Seite beim ersten Rendern Loading... server-rendern, w├Ąhrend React hochf├Ąhrt / das Token vom localStorage liest. Dies bedeutet, dass gesch├╝tzte Seiten kein SEO werden, was derzeit wahrscheinlich in Ordnung, aber definitiv nicht optimal ist.

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

Die Login-Seite kann den HOC in seiner jetzigen Form nicht verwenden, da der Login ├Âffentlich sein muss. Es erstellt also nur eine Instanz von AuthService direkt. Sie w├╝rden etwas ├ähnliches auch f├╝r eine Anmeldeseite tun.

// ./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

Inspiriert von Airbnbs Reaction-with-Styles begann ich auch mit der Arbeit an einer next-with-auth Bibliothek, die eine Funktion w├Ąre, die einen HOC zur├╝ckgibt, der auf Seiten verwendet werden soll. Ich habe auch mit dem Zusammenf├╝hren von AuthService und diesem HOC gespielt. Eine L├Âsung k├Ânnte darin bestehen, dass dieser HOC zus├Ątzlich zur Komponente eine Berechtigungsstufenfunktion als Argument akzeptiert, wie z. B. redux connect. Unabh├Ąngig davon w├╝rden Sie meiner Meinung nach next-with-auth wie folgt verwenden:

// ./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,
})

Das alles mit Redux zu machen schien unn├Âtig kompliziert, aber im Grunde k├Ânnen Sie dem Wiki-Beispiel folgen, aber AuthService in Aktionen verschieben (An- und Abmelden) und einen User Reducer haben. Sie k├Ânnen diese Aktionen jedoch nur auf dem Client aufrufen, da auf dem Server kein localStorage vorhanden ist, sodass Sie dies in Ihren Aktionen ├╝berpr├╝fen m├╝ssen. Letztendlich wird Redux Store sowieso auf die window gelegt. Sie k├Ânnen den Benutzer also einfach auf window anstatt den Kontext zu verwenden. Wenn Sie kein Redux wollen, k├Ânnen Sie auch react-broadcast ausprobieren.

Schlie├člich wird angenommen, dass next/server gem├Ą├č #25 versendet. next-with-auth k├Ânnte komplizierte LocalStorage- vs. Cookie-Zeug vom Entwickler mit Middleware + einem HOC abstrahieren. Es k├Ânnte auch die Token-Aktualisierung verarbeiten.

Alle 208 Kommentare

Vorschlag: Verwenden Sie Redux und JWT, um das Beispiel auszuf├╝hren

Ich arbeite an einem Beispiel daf├╝r. Habe derzeit Probleme damit, dass componentWillReceiveProps auf meiner High-Level-Komponente ausgel├Âst wird (wobei ich vorhabe zu ├╝berpr├╝fen, ob der Benutzer authentifiziert ist und andernfalls auf die Anmeldeseite umleiten)

So habe ich auth, die schwimmend arbeitet. Wie an anderer Stelle erw├Ąhnt, ist es nur clientseitig, was letztendlich nur die halbe Miete ist.

"Ziemlich sicher"

Wie bei PHP ist die atomare Einheit von Next die Seite. Eine der coolsten Funktionen ist, dass jede Seite nur dann geladen wird, wenn sie angefordert wird. Bei nur clientseitiger Authentifizierung, aber beim Server-Rendering wird das js f├╝r diese gesch├╝tzte Seite tats├Ąchlich vom Browser heruntergeladen. Wenn Next in Zukunft Server-Workflows hinzuf├╝gt, k├Ânnen Sie hoffentlich das Rendern und die Umleitung auf dem Server blockieren, um dies vollst├Ąndig zu verhindern. Dies erfordert Cookies, Sitzungen und AFAIK-Sitzungsspeicher, aber das sind nur die Kosten f├╝r solche Hybrid-Apps.

Auth-Beispiel

Angenommen, Sie haben eine JWT-gesicherte API mit zwei interessierenden Endpunkten: /token und /me . /token akzeptiert E-Mail-/Passwort-Anmeldeinformationen und gibt ein signiertes JWT ( id_token ) zur├╝ck, w├Ąhrend /me Profilinformationen zum JWT-authentifizierten Benutzer zur├╝ckgibt. Ich habe das folgende AuthService.js aus der Sperre von Auth0 angepasst (Entfernen des Ereignissenders, obwohl das nicht die schlechteste Idee ist). Es extrahiert fast das gesamte JWT-Token-Handling, sodass es auf der Anmeldeseite und auch in einer Komponente h├Âherer Ordnung verwendet werden kann (dazu sp├Ąter mehr).

// 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())
  }
}

Als n├Ąchstes folgt ein HOC, um den Schutz von Seiten zu vereinfachen. Um ein ungewolltes Aufblitzen sensibler Informationen zu verhindern, wird die Seite beim ersten Rendern Loading... server-rendern, w├Ąhrend React hochf├Ąhrt / das Token vom localStorage liest. Dies bedeutet, dass gesch├╝tzte Seiten kein SEO werden, was derzeit wahrscheinlich in Ordnung, aber definitiv nicht optimal ist.

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

Die Login-Seite kann den HOC in seiner jetzigen Form nicht verwenden, da der Login ├Âffentlich sein muss. Es erstellt also nur eine Instanz von AuthService direkt. Sie w├╝rden etwas ├ähnliches auch f├╝r eine Anmeldeseite tun.

// ./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

Inspiriert von Airbnbs Reaction-with-Styles begann ich auch mit der Arbeit an einer next-with-auth Bibliothek, die eine Funktion w├Ąre, die einen HOC zur├╝ckgibt, der auf Seiten verwendet werden soll. Ich habe auch mit dem Zusammenf├╝hren von AuthService und diesem HOC gespielt. Eine L├Âsung k├Ânnte darin bestehen, dass dieser HOC zus├Ątzlich zur Komponente eine Berechtigungsstufenfunktion als Argument akzeptiert, wie z. B. redux connect. Unabh├Ąngig davon w├╝rden Sie meiner Meinung nach next-with-auth wie folgt verwenden:

// ./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,
})

Das alles mit Redux zu machen schien unn├Âtig kompliziert, aber im Grunde k├Ânnen Sie dem Wiki-Beispiel folgen, aber AuthService in Aktionen verschieben (An- und Abmelden) und einen User Reducer haben. Sie k├Ânnen diese Aktionen jedoch nur auf dem Client aufrufen, da auf dem Server kein localStorage vorhanden ist, sodass Sie dies in Ihren Aktionen ├╝berpr├╝fen m├╝ssen. Letztendlich wird Redux Store sowieso auf die window gelegt. Sie k├Ânnen den Benutzer also einfach auf window anstatt den Kontext zu verwenden. Wenn Sie kein Redux wollen, k├Ânnen Sie auch react-broadcast ausprobieren.

Schlie├člich wird angenommen, dass next/server gem├Ą├č #25 versendet. next-with-auth k├Ânnte komplizierte LocalStorage- vs. Cookie-Zeug vom Entwickler mit Middleware + einem HOC abstrahieren. Es k├Ânnte auch die Token-Aktualisierung verarbeiten.

Aufgeregt, das auszuprobieren! Danke f├╝r die Barebones-Implementierung :)

@jaredpalmer Ich arbeite an etwas ├ähnlichem. Wie funktioniert Ihr AuthService , wenn eine Komponente serverseitig gerendert wird? Der Server ben├Âtigt Zugriff auf das JWT, kann es jedoch nicht aus dem lokalen Speicher lesen.

@amccloud Das tut es nicht. Das ist das ganze Problem. Der HOC rendert <div>Loading..</div> auf gesch├╝tzten Routen und muss den Token lesen und entscheiden, ob in componentDidMount umgeleitet werden soll oder nicht. Damit es wie gew├╝nscht funktioniert und serverseitig gerendert wird, ben├Âtigt Next #25 oder zumindest die M├Âglichkeit, ein Cookie mit dem Wert von JWT AFAIK zu setzen.

Ich habe cookie-js verwendet, um ein Cookie zu setzen, aber es ist ein bisschen ein Hack..
Die Sache ist: Wenn Sie kein Cookie senden, verlieren Sie alle Vorteile von nextjs und serverseitigem Rendering in authentifizierten Routen

@jaredpalmer das ist gro├čartig! Danke f├╝r die Bem├╝hung. Ich werde versuchen, Ihr Beispiel in den n├Ąchsten Tagen fertig zu implementieren (oder Ihnen dabei zu helfen, wenn Sie m├Âchten)

Jo! Ein Beispiel mit nextjs und auth0 habe ich hier ver├Âffentlicht: https://github.com/luisrudge/next.js-auth0
Es hat das Konzept eines Hauptlayouts und auch "sicherer Seiten", die nur geladen werden, wenn der Benutzer authentifiziert ist.
Lass mich wissen was du denkst

@luisrudge unglaublich. Ich klone und nehme einige Änderungen vor, aber sieht toll aus

Cool! Was denkst du, was fehlt? An welche Ver├Ąnderungen denken Sie?

Am Sonntag, den 6. November 2016 um 13:12 -0200 schrieb "Dan Zajdband" < [email protected] [email protected] >:

@luisrudgehttps ://github.com/luisrudge erstaunlich. Ich klone und nehme einige Änderungen vor, aber sieht toll aus

Sie erhalten dies, weil Sie erw├Ąhnt wurden.
Antworten Sie direkt auf diese E-Mail, zeigen Sie sie auf Gi tHub anhttps://github.com/zeit/next.js/issues/153#issuecomment -258687108, oder schalten Sie das AA5cE8NIsvQ_ITjc1gArTFgNXzEda4TSks5q7e5NgaJpZM4KkJmi.

1) Verwenden von standard f├╝r Linting (damit es mit allem ├╝bereinstimmt, mit dem wir als n├Ąchstes bauen)
2) Hinzuf├╝gen von Multi-Tab-Unterst├╝tzung angefordert von @rauchg
3) Der CSS-Teil kann vereinfacht werden

ich schicke dir eine pr :)

Was meinst du mit Multi-Tab-Unterst├╝tzung?

Am Sonntag, den 6. November 2016 um 13:16 -0200 schrieb "Dan Zajdband" < [email protected] [email protected] >:

1) Standard f├╝r Linting verwenden (damit es mit allem ├╝bereinstimmt, mit dem wir als n├Ąchstes bauen)
2) Hinzuf├╝gen von Multi-Tab-Support angefordert von @rauchghttps ://github.com/rauchg
3) Der CSS-Teil kann vereinfacht werden

ich schicke dir eine pr :)

Sie erhalten dies, weil Sie erw├Ąhnt wurden.
Antworten Sie auf diese E - Mail direkt, sehen sie auf Gi tHubhttps: //github.com/zeit/next.js/issues/153#issuecomment -258.687.373 oder stumm schalten die th readhttps: //github.com/notifications/unsubscribe-auth/ AA5cE1A6jq4KZc9_ynukTCI4mU-rdsNaks5q7e81gaJpZM4KkJmi.

Sie haben 2 offene Tabs, logout auf 1, loggt sich automatisch auf dem anderen aus

Ahh. Das ist supercool!

Am Sonntag, den 6. November 2016 um 13:21 -0200 schrieb "Dan Zajdband" < [email protected] [email protected] >:

Sie haben 2 offene Tabs, logout auf 1, loggt sich automatisch auf den anderen aus

Sie erhalten dies, weil Sie erw├Ąhnt wurden.
Antworten Sie auf diese E - Mail direkt, sehen sie auf Gi tHubhttps: //github.com/zeit/next.js/issues/153#issuecomment -258.687.707 oder stumm schalten die th readhttps: //github.com/notifications/unsubscribe-auth/ AA5cE9e2DA4_GgNQIVTMp0hx74G-6RmUks5q7fBfgaJpZM4KkJmi.

Hallo @luisrudge ich habe dir eine PR mit den Änderungen geschickt https://github.com/luisrudge/next.js-auth0/pull/2

vielen Dank daf├╝r <3

Das ist ├╝brigens das Ergebnis:

2016-11-06 11 14 31

@impronunciable @luisrudge Fantastische Umsetzung! Wenn Sie es ohne Auth0 verwenden m├Âchten, m├╝ssen Sie anscheinend nur die Dateien im Verzeichnis ./utils ├Ąndern, vielleicht sogar nur lock.js . Ich werde das demn├Ąchst ausprobieren. ├ťbrigens sieht das Multi-Tab super aus

@ugiacoman Ich habe mit der Implementierung eines kleinen Servers mit passwordless.net begonnen, lass es mich wissen, wenn du meinen Code als Ausgangspunkt haben m├Âchtest

@impronunciable Das w├Ąre toll! Eigentlich wollte ich etwas ├ähnliches mit den Digits von Twitter Fabric machen.

@improuncible Ich schlage vor, das Passwort less.net nicht zu verwenden, stattdessen k├Ânnen Sie einfach Passport-Local verwenden und den Benutzern einfach einen Link mit ihrer E-Mail und ihrem Token in der Abfragezeichenfolge senden.

Danke @impronunciable ÔŁĄ´ŞĆ

@ugiacoman ja, es ist ziemlich einfach, die auth0-Abh├Ąngigkeit zu entfernen. Ich habe es verwendet, weil ich keine separate API f├╝r die Authentifizierung haben wollte

@jaredpalmer Soweit ich wei├č, w├Ąre # 25 gro├čartig, aber blockiert es nicht? Ich meine, wir haben Zugriff auf das serverseitige req in getInitialProps also hindert nichts daran, cookie-parser darauf anzuwenden? Serverseitiges Authentifizierungs- und Sitzungsmanagement ist f├╝r mich alles neu

├ťbrigens, wenn man bedenkt, dass localStorage nicht serverseitig verwendet werden kann, sind Cookies die einzige M├Âglichkeit, serverseitige Sitzungen durchzuf├╝hren? Ich habe eine vage Erinnerung, es ist vielleicht nicht die sicherste? Aber gibt es noch eine andere M├Âglichkeit?

@sedubois

Der Cookie-Ansatz kann sehr sicher sein, wenn er richtig durchgef├╝hrt wird. Folgendes zu tun ist ziemlich trivial:

  • Verwenden Sie das httpOnly-Flag (verhindert den JavaScript-Zugriff auf das Cookie)
  • sicheres Flag verwenden (nur Cookie f├╝r https-Anfragen setzen)
  • Signierte Cookies (Quelle des Cookies ├╝berpr├╝fen)

Es gibt auch einen sehr erheblichen Latenzvorteil, wenn Sie direkt auf dem Server auf Authentifizierungsinformationen zugreifen k├Ânnen.

Wir sollten dieses Beispiel in examples/ Ich werde sehen, was mir einf├Ąllt

Ich habe es geschafft, react-cookie f├╝r isomorphe Cookies zu verwenden, indem ich nextjs wie folgt in einen benutzerdefinierten Express-Server einpacke:

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')
  })
})

Dies erm├Âglicht es mir, eine authentifizierte Anfrage von der Serverseite aus zu stellen. Dies behebt keines der Probleme der urspr├╝nglichen Aufz├Ąhlungszeichen, sondern l├Âste das Problem der Freigabe des Status zwischen Client und Server.

Aus dem POV von jemandem, der viel von diesem Zeug lernt. Ich denke, es w├Ąre am besten, wenn sich die Beispiele nicht auf Dienste von Drittanbietern wie auth0 verlassen. F├╝r Neulinge w├Ąre es vorteilhafter, ein Barebone-Beispiel mit Anmelde-/Anmeldeformularen und der Verwendung von Redux und JWT zu sehen.

Das Beispiel, das wir _bundle_ planen, basiert auf Open-Source-Node.js-Server-APIs

Ich habe einem Beispiel-Starterprojekt unter https://github.com/iaincollins/nextjs-starter ein Beispiel f├╝r eine E-Mail-basierte Authentifizierung hinzugef├╝gt

Es hat Sitzungsunterst├╝tzung (mit Express Sessions im Backend und der Browser-SessionStorage-API, um sie im Frontend zwischenzuspeichern), httpOnly Cookies, CSRF-Projektion, verwendet integriertes SMTP zum Senden von E-Mails, ein einfach zu ├Ąnderndes Backend, das standardm├Ą├čig auf SQL Lite eingestellt ist . Es ist keine Konfiguration erforderlich, um es auszuf├╝hren.

Das Projekt hat auch Layoutseiten, benutzerdefinierte Routen und enth├Ąlt das Uhrenbeispiel aus dem Wiki. Es ist nicht das schickste Beispiel f├╝r Authentifizierung, aber es k├Ânnte hilfreich sein f├╝r diejenigen, die einen einfachen Einstieg in ein einfaches Projekt suchen, das leicht zu verstehen und zu spielen ist.

Ich stimme @iamjacks zu, dass ein Beispiel mit JWT eine gute Idee zu sein scheint.

Ich freue mich, die Fehlerbehandlung zu verbessern und Funktionen wie eine einfache Profilseite hinzuzuf├╝gen, die Benutzer bearbeiten k├Ânnen, und Passport-Integration mit Beispielen f├╝r oAuth f├╝r Facebook, Google und Twitter, wenn dies f├╝r die Leute n├╝tzlich w├Ąre. Wenn Leute gute Ideen f├╝r bessere M├Âglichkeiten haben, Sitzungsinformationen f├╝r Komponenten zu verbreiten / verf├╝gbar zu machen, bin ich sehr daran interessiert.

Example screenshot showing what to expect

Das ist ziemlich unglaublich @iaincollins. Wir werden dies auf jeden Fall in den Versionshinweisen f├╝r 2.0 vorstellen :)

@rauchg Danke! :)

Ich denke, ich sollte explizit hinzuf├╝gen, dass in diesem Beispiel Sitzungen sowohl client- als auch serverbasiert sind - dh mit und ohne JavaScript arbeiten (und auf Systemen ohne sessionStorage), und dieselbe Sitzung wird von beiden geteilt.

Dies zu erreichen, wird in der Session-Komponente etwas kniffelig, die sich mit Variablen mit Namen wie req.connection._httpMessage.locals._csrf befasst, um das CSRF-Token aus den Serverheadern abzurufen - als das 'req'-Objekt, das in getInitialProps() an Seiten ├╝bergeben wird. ist seltsamerweise etwas anders als das in Express exponierte req-Objekt, da ich normalerweise ├╝ber req.locals._csrf darauf zugreifen w├╝rde (jedoch ist req.session in beiden gleich).

localStorage ist nicht sicher. was ist der beste Weg, um es sicherer zu machen. jeder kann localStorage-Daten stehlen und wieder in seinen Browser laden und als Opferbenutzer protokolliert werden!!

@Chathula das stimmt nicht. Dieses Argument ist falsch.
Wenn jemand physisch Zugriff auf den Browser hat, kann er alles tun.

Das gilt auch f├╝r Kekse.

Die Verwendung von localStorage f├╝r die Authentifizierung ist ziemlich sicher, da wir Cookies-basierte Sicherheitsprobleme beseitigen k├Ânnten.
Aber auf der anderen Seite betrifft es SSR.

@arunoda Ich habe ein Login mit Laravel API und Next.js Client erstellt. Ich speichere authUser access_token in localStorage. ├ťberpr├╝fen Sie dann, ob der Benutzer angemeldet ist oder nicht, indem Sie sich authentifizieren. aber es ist nicht sicher. wenn jemand die localStorage-Daten gestohlen hat. er/sie kann es benutzen.

wenn jemand die localStorage-Daten gestohlen hat.

Wie? Grunds├Ątzlich sollte er/sie physisch Zugriff auf den Browser haben. Dann k├Ânnte diese Person alles tun.
Darum sollten wir uns also keine Sorgen machen.

K├Ânnen wir keine Verschl├╝sselung verwenden, um es viel sicherer zu machen?

@Chathula, das geht vom Thema ab. Es ist nicht gerade relevant f├╝r Next.js und wir wollen uns daran orientieren, wie Web-Sachen normalerweise funktionieren.

@Chathula vielleicht er├Âffnen .

@arunoda hahaha!! Danke f├╝r die Information! :D

@Chathula Ich bespreche es gerne in einer Ausgabe des Starterprojekts, wenn Sie spezielle Bedenken haben.

Ich m├Âchte alle Missverst├Ąndnisse korrigieren, um zu vermeiden, dass die Leute unn├Âtig beunruhigt werden.

Die Web-Storage-API (dh localStorage und sessionStorage) ist - wie Cookies ohne gesetztes httpOnly - durch Same Origin Policy (Protokoll, Hostname, Portnummer) eingeschr├Ąnkt, es stimmt nicht, dass "jeder [es] stehlen kann"; aber ja, wenn jemand in der Lage ist, ├╝ber eine Cross-Site-Scripting-Sicherheitsl├╝cke in Ihrer Anwendung beliebiges JavaScript auf Ihrer Site auszuf├╝hren, dann kann er auch auf den Store zugreifen, daher sollten Sie keine Sitzungskennungen darin speichern.

Aus diesem Grund werden Sie sehen, dass das Sitzungstoken selbst nicht in localStorage/sessionStorage gespeichert und in JavaScript nicht lesbar ist, sondern nur ├╝ber ein HTTP Only-Cookie ├╝bertragen wird (weshalb die Sitzungsklasse XMLHttpRequest() statt fetch() verwendet - wie in der Klassendokumentation erkl├Ąrt).

Dies bedeutet, dass selbst wenn jemand in der Lage ist, eine Cross-Site-Scripting-Sicherheitsl├╝cke in Ihrer Anwendung auszunutzen und beliebiges JavaScript in Ihrer Web-App auszuf├╝hren, er dennoch kein Sitzungstoken eines Benutzers lesen oder exportieren kann.

Dies ist vielleicht eine wichtige Unterscheidung, die es wert ist, in der Dokumentation ber├╝cksichtigt zu werden.

Hinweis: Eine zus├Ątzliche Verschl├╝sselung der Benutzerdaten ist hier nicht hilfreich, da die App immer in der Lage sein muss, die Daten zu lesen, damit sie gerendert werden k├Ânnen (Sie m├╝ssten also auch einen Beschreibungsschl├╝ssel in der App speichern, der die Verschl├╝sselung wiedergeben w├╝rde Benutzerdaten ziemlich strittig).

_UPDATE: In den letzten ein oder zwei Wochen wurde das Beispiel ├╝berarbeitet, um localStorage ├╝ber sessionStorage zu verwenden, da sessionStorage nicht zwischen Registerkarten geteilt wird und nicht sensible Daten auf diese Weise die Anzahl unn├Âtiger Authentifizierungspr├╝fungen reduziert und den Sitzungsstatus zwischen den Registerkarten konsistent h├Ąlt._

Vielleicht n├╝tzlich f├╝r einige Leute, die ich beim Experimentieren mit dieser Beispiel-App erstellt habe:

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

Unterst├╝tzt von diesem Spielzeug-Backend:

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

Hier eingesetzt:

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

Backend hier:

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

@M├Âglichkeiten Danke Mike! Ebenso wie die Bereitstellung eines separaten Microservices, der eine nette Art und Weise zeigt, sichere Seiten zu handhaben, von denen ich dachte, dass sie ein gutes Pragma sein k├Ânnten und von denen sie sich inspirieren lassen k├Ânnten. Ich habe einige Ideen, die im next.js-with-auth-Repository auftauchen werden.

Nach einigem Nachdenken w├╝rde ich meine Bem├╝hungen wahrscheinlich nicht als gro├čartiges Beispiel betrachten. Ich w├╝rde wahrscheinlich dazu wechseln, dass die Anmeldung/Anmeldung den Web 1.0-Stil vollst├Ąndig ├╝bermittelt, damit wir auf dem Server ein reines HTTP-Cookie erstellen k├Ânnen (wodurch die Zug├Ąnglichkeit zum JWT ├╝ber XSS beseitigt wird) und dann das Benutzerobjekt stattdessen an req anh├Ąngen k├Ânnen als das gesamte Token. Dies l├Ąsst die M├Âglichkeit von CSRF-Schwachstellen, aber ich denke, dies ist einfacher zu mindern als XSS (nein?). Ein sch├Âner Nebeneffekt davon ist, dass die Client-App dann einen nahezu identischen Ablauf f├╝r die Anmeldung ├╝ber einen Eid-Dienst verwenden kann.

Im Nachhinein sehe ich auch, dass ich die "Middleware" (und daher die Notwendigkeit eines benutzerdefinierten Servers) vermeiden konnte, indem ich das Cookie im Page HoCs getInitialProps parse.

@possibilities Da die 'geheime' Seite nur eine Seite ist und von Webpack geb├╝ndelt wird, w├╝rde sie nicht an den Browser geliefert, wenn ich zu /geheim gehe?

Ja, ich nehme an, das sollte verdrahtet sein, um eine serverseitige Umleitung durchzuf├╝hren.

├ťbrigens, ich wurde von meinem urspr├╝nglichen Projekt abgelenkt, mich mit github anzumelden. Der Ablauf ist ├Ąhnlich, mit mehr Sorgfalt auf die Sicherheit (n├Ąmlich kein Geheimnis auf dem Client preiszugeben, um zu vermeiden, dass Oauth-Token ├╝ber XSS offengelegt werden). Es ist in eine richtige App eingebunden, aber wenn es Interesse gibt, k├Ânnte ich es in etwas aufteilen, das f├╝r den Oauth-Flow im Allgemeinen n├╝tzlich sein k├Ânnte.

@possibilities Ich denke, es w├Ąre eine gro├čartige Hilfe, wenn es eine PR mit einem minimalen (aber ordentlichen) Beispiel mit Authentifizierung geben k├Ânnte ­čÖé Ich arbeite an Authentifizierung in meiner App (https://github.com/relatenow/ beziehen), aber es ist derzeit nur clientseitig (localStorage).

@sedubois Ich habe einen https://github.com/zeit/next.js/pull/646, aber wir werden den Authentifizierungsserver woanders hin verschieben

wie w├Ąre es mit graphql?

Apollo gibt ein Beispiel f├╝r die graphql-Authentifizierung:

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

Hier authentifizieren wir eine graphql-Anfrage, die jedoch f├╝r unseren Fall angepasst werden k├Ânnte.

Au├čerdem kann graphql Implementierung und Logik abstrahieren. Es k├Ânnte mit passwordless, auth0 oder allem anderen, was wir bevorzugen, verwendet werden.

@impronunciable FYI mit Ihrem Beispiel wei├č ich noch nicht, wie ich mit Sitzungen @iaincollins in meiner App anzupassen.

Meine Anforderungen sind:

  • sicher
  • Authentifizierung auf der Serverseite, dann auf der Clientseite
  • unterst├╝tzt sowohl Facebook als auch Login/Passwort
  • Authentifizierungsanbieter sollten leicht ge├Ąndert werden
  • Benutzer in Graphcool erstellen
  • nachfolgende GraphQL-Anfragen an Graphcool authentifizieren

Falls es jemandem hilft, hier ist meine App mit serverseitiger Authentifizierung ­čÖé

Die Authentifizierung sollte vom Next.js-Server getrennt werden, aber ich warte darauf, dass jemand anderes dazu Inspiration gibt ... Au├čerdem bin ich mir nicht sicher, ob sie richtig gegen CSRF gesch├╝tzt ist.

Das habe ich gemacht:

  • Wenn sich der Benutzer anmeldet, setzt clientseitiges Javascript ein Cookie im Browser, das das Authentifizierungs-Tr├Ągertoken enth├Ąlt
  • bei authentifizierten Anfragen liest der serverseitige Code (next.js) das Bearer-Token in den Headern der Anfrage des Browsers und verwendet es, um den API-Server im Auftrag des Clients zu kontaktieren

Dies ist anf├Ąllig f├╝r XSS- und CSRF-Angriffe (auch wenn Reaction viel dazu beitr├Ągt, dies zu verhindern), aber es ist einfach und funktioniert mit SSR.

Nur um die Anfragen zu erg├Ąnzen

graph.cool + apollo + jwt + auth0 + next.js, die ersten 4 Teile davon sind bereits fertig auf https://github.com/graphcool-examples/react-apollo-auth0-example

@balupton Was passiert in Ihrem Beispiel, wenn das Token abl├Ąuft, w├Ąhrend der Benutzer noch verbunden ist, ist die Sitzung gerade vorbei oder wird sie irgendwie erneuert?

@nmaro wei├č nicht, nicht von mir geschrieben - am besten da dr├╝ben nachfragen

F├╝r meine eigene App habe ich auth mit next.js und auth0, dann mit einem zeit/micro-API-Server, der die Bearer-Token ├╝berpr├╝ft.

Sollte irgendwann im Februar als Open Source verf├╝gbar sein.

Nach der gleichen Philosophie, die next.js verfolgt hat (tun Sie eine Sache und machen Sie es gut), habe ich das Skelett eines erweiterbaren Benutzerkontensystems f├╝r Knoten entwickelt. Siehe die Philosophie hier: https://medium.com/the-ideal-system/ooth-user-accounts-for-node-js-93cfcd28ed1a#.97kyfg4xg

Das Github-Projekt ist hier: https://github.com/nmaro/ooth/

Das Ziel ist ein erweiterbarer, unabh├Ąngiger Authentifizierungs- und Benutzerverwaltungsdienst, der sich ideal f├╝r die Verwendung als separater Microservice eignet, eine Anwendungsstruktur, die sehr gut mit node.js harmonieren w├╝rde.

Ein Beispiel mit E-Mail+Passwort-Authentifizierung finden Sie hier: https://github.com/nmaro/ooth/tree/master/examples/ooth
F├╝r Facebook und Google Auth gibt es bereits Pakete (ooth-facebook und ooth-google), die auf Basis von Passport-Facebook bzw. Passport-Google einfach zu implementieren sein sollen.

Ich werde so schnell wie m├Âglich ein next.js-Integrationsbeispiel ver├Âffentlichen. Beteiligen Sie sich gerne an der Diskussion und tragen Sie dazu bei.

Entschuldigung f├╝r den Stecker, aber es ist zum Wohle der Allgemeinheit - ich glaube wirklich, dass es noch keine gute L├Âsung f├╝r Node gibt, und dies ist genau das richtige Publikum von Leuten, die so etwas vielleicht wollen. Frieden

In der Zwischenzeit... hier ist ein Beispiel f├╝r eine graphql-API, die nur f├╝r Schreiboperationen eine Authentifizierung mit einem JWT-Token erfordert. F├╝hlen Sie sich frei, es mit Ihrer bevorzugten Authentifizierungsmethode zu verwenden :)

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

Ich habe https://nextjs-starter.now.sh aktualisiert, um oAuth-Unterst├╝tzung hinzuzuf├╝gen.

screen shot 2017-02-10 at 05 03 19

  • Es verwendet Passport f├╝r oAuth, zusammen mit Express-Sessions (wie zuvor).
  • Es gibt Unterst├╝tzung f├╝r Facebook, Google und Twitter+ oAuth und es ist einfach, weitere hinzuzuf├╝gen (siehe AUTHENTICATION.md und /auth-passport.js ).
  • Es verwendet das universelle Client/Server-Sitzungssystem (mit CSRF-Token, XSS-Schutz ├╝ber HTTP Only-Cookies, die ORM-Schicht, die Mongo, SQL-DBs, Redshift usw. unterst├╝tzt) als E-Mail-Anmeldung.
  • Kann berichten, dass die Erfahrung mit der Konfiguration von oAuth auf Entwicklerportalen genauso schrecklich ist wie immer (seltsame Fehler passieren und es ist schwer zu debuggen).

Die Natur von oAuth - db + Sessions + Passport und Fehlerbehandlung m├╝ssen eng zusammenarbeiten - und von Sitzungen, die sowohl Client als auch Server funktionieren m├╝ssen und wie dies mit universellem Rendering funktioniert - bedeutet ein bisschen viel zu versuchen und auf einmal umzugehen, wenn Sie versuchen herauszufinden, was vor sich geht, aber die Clientlogik hat keine oAuth-spezifische Konfiguration, sodass sie nicht zu chaotisch ist.

Ich w├╝rde gerne nur die Authentifizierung in ein separates Beispiel aufteilen, obwohl ich vermute, dass es nicht viel kleiner w├Ąre. Wenn jemand anderes m├Âchte, super. Ich werde dem Beispiel wahrscheinlich irgendwann etwas mehr hinzuf├╝gen (wie eine Kontoverwaltungsseite). Wahrscheinlich w├Ąre es gut, mehr auf die Dokumentation zu verlinken.

Erstaunliche Arbeit! Wenn Sie die Authentifizierung aufteilen und zum next.js-Repository hinzuf├╝gen k├Ânnten, w├Ąre das gro├čartig :heart:

Ich kann das ├╝brigens auch

Ich werde in den n├Ąchsten 2 Wochen oder so keine Zeit haben, also wenn jemand m├Âchte, w├Ąre das gro├čartig.

Ich w├╝rde es gerne umgestalten und sehen, ob es auf nur ein Modul reduziert werden k├Ânnte (das einfache Komponenten wie Anmeldeschaltfl├Ąchen und Anmeldeformulare zum Einbetten bereitstellt) und mich von dem wirklich sch├Ânen fr├╝heren clientseitigen Beispiel inspirieren lassen von @impronunciable.

Update: Eigentlich gehe ich weg, weshalb ich nicht kann, aber wenn ich zur├╝ck bin, schaue ich mir das gerne an!

Ich habe die Kurzanleitung auth0/react mit einigen Änderungen befolgt, aber wenn ich lock.show() anrufe, beschweren sich die App-Beschwerden:

Nicht abgefangener Fehler: addComponentAsRefTo(...): Nur ein ReactOwner kann Refs haben. M├Âglicherweise f├╝gen Sie einer Komponente eine Referenz hinzu, die nicht in der Methode render einer Komponente erstellt wurde, oder Sie haben mehrere Kopien von React geladen

@iaincollins @timneutkens bez├╝glich Ihres Beispiels, bitte korrigieren Sie mich, wenn ich falsch

Im Beispiel wird ein httpOnly-Cookie verwendet, um ein Sitzungstoken zu speichern, das es vor JavaScript-Injiection-Angriffen (XSS) sicher macht. Dann macht es sich die M├╝he, ein csrf-Token im lokalen Speicher ablegen zu lassen, um auch vor CSRF-Angriffen zu sch├╝tzen.

Es liegt die Annahme zugrunde, dass diese Kombination von Techniken die Dinge sicher macht, was den Benutzer/Entwickler in die Irre f├╝hren k├Ânnte. Ein Angreifer kann immer noch Javascript in die Seite (XSS) einschleusen, das csrf-Token lesen und es verwenden, um authentifizierte (Cookie-)Anfragen an die API auszuf├╝hren. Ist in der Readme erw├Ąhnenswert?

Hallo @davibe

Leider gibt es derzeit keinen technisch besseren Ansatz als einen Sitzungscookie und ein separates rotierendes CSRF-Token, also muss ich wohl sagen, dass ich mit dem Modell im Gro├čen und Ganzen zufrieden bin, da es nicht wirklich eine andere M├Âglichkeit gibt (auch wenn die tats├Ąchliche Umsetzung immer noch verbessert werden k├Ânnte).

Wir k├Ânnten Browser-Fingerdruck hinzuf├╝gen, vielleicht k├Ânnte das Session-Token h├Ąufiger rotieren (ich vergesse, ob das gerade automatisch ist), das CSRF-Token k├Ânnte ein Header anstelle von Param sein, die Cookies sollten wirklich nur SSL in der Produktion sein und wir k├Ânnten hinzuf├╝gen ein Ablaufdatum f├╝r die Anmelde-Token, aber AFAICS gibt es in Bezug auf das Sicherheitsmodell ziemlich begrenzten Spielraum f├╝r Verbesserungen und nichts, was wirklich weiteren Schutz bietet, falls jemand in der Lage ist, beliebigen Code in eine App einzuschleusen; aber bitte z├Âgern Sie nicht, diese Dinge als Probleme f├╝r Verbesserungen im Repo anzusprechen.

Wenn es Optionen zum ├ändern des Kontostatus g├Ąbe (die es derzeit nicht gibt), k├Ânnten wir vor der Ausf├╝hrung ein CAPTCHA verwenden, um ├änderungen auf dem Server ohne Erlaubnis zu erschweren, aber im Beispiel k├Ânnen sich Benutzer nur anmelden und aus, so dass das derzeit au├čerhalb des Geltungsbereichs liegt.

Die lokale Speicherung von Sitzungstoken w├╝rde es deutlich weniger sicher machen und gegen die beabsichtigte Verwendung in der Spezifikation versto├čen, daher bin ich pers├Ânlich nicht daf├╝r - obwohl ich es zu sch├Ątzen wei├č, dass es die Dinge vereinfachen w├╝rde, da es keine CSRF-Projektion hat, aber die Leute wahrscheinlich Ich brauche kein Beispiel daf├╝r, da es sehr einfach w├Ąre - ich habe nur versucht, eines bereitzustellen, weil es so umst├Ąndlich ist. :-)

Ich bin voll und ganz bei Ihnen, auch ich hasse es, wie notwendigerweise umst├Ąndlich es ist, und habe den Versuch, es in ein Modul zu verwandeln, nicht aufgegeben.

Hmm.. ich verstehe.
Dieses Problem war f├╝r mich sehr hilfreich, danke.

Dies ist der Standpunkt von Auth0 https://auth0.com/blog/cookies-vs-tokens-definitive-guide/
Sie schlagen grunds├Ątzlich vor, Cookies zu vermeiden, aber das w├╝rde SSR beim ersten Laden der Seite auslassen, denke ich.

Hallo allerseits!

Ich arbeite auch an der Authentifizierung mit next.js und die Kommentare aus dieser Ausgabe, insbesondere @davibe + das Repo von @iaincollins und die PR von @timneutkens waren eine enorme Hilfe.

Meine L├Âsung macht folgendes:

  • Nach erfolgreicher Anmeldung speichert mein Redux Reducer den Token und die Benutzerdaten mit Hilfe von response-cookie in einem
  • Jede Seite/Komponente, die diese Informationen ben├Âtigt, wird in eine Komponente h├Âherer Ordnung ├Ąhnlich wie @timneutkens with-session.js eingeschlossen . Wenn SSR, ist das Token in ctx.req.headers.cookie verf├╝gbar, andernfalls nimm es einfach aus dem Browser-Dokument (verwende die React-Cookie-Lademethode).
  • Sobald ich das Token habe, kann ich es bei jeder Anfrage in den Kopfzeilen Bearer / Authorization setzen.

Es hilft, dass ich meinen eigenen JWT-Token-Authentifizierungs-Microservice in einem Docker-Container ausgef├╝hrt habe.
Vielleicht w├Ąre es einfacher, einen einfachen JWT-Dienst als Teil des with-auth-Beispiels bereitzustellen? So vermeiden Sie, die server.js zu hacken und m├Âglicherweise die Vorteile von next.js-integriertem Hot-Reloading, SSR und Routing zu verlieren?

Ich bin mir auch nicht sicher, ob dieser Ansatz in Bezug auf CSRF / XSS sicher ist. Alle Kommentare sind willkommen.

Danke an euch alle f├╝r die tolle Arbeit, die ihr bisher geleistet habt. Ich bin ein gro├čer Fan von diesem Projekt!

@jcsmesquita Ich arbeite an einer neuen Version des Beispiels, bei der alles von Next.js getrennt ist, ├Ąhnlich wie die Authentifizierung bei zeit.co implementiert ist.

Dies scheint n├╝tzlich zu sein: https://hub.docker.com/r/rabbotio/nap/~/dockerfile/

@subsumo Danke f├╝r die Erw├Ąhnung, FYI: NAP geh├Ârt mir, die Authentifizierung ├╝ber das Web basiert auf @iaincollins nextjs-starter und reagiert auf die native Client-Anmeldung mit Token.

@timneutkens erm├Âglicht Ihnen die L├Âsung, an der Sie arbeiten, die Authentifizierung bei einem separaten Dienst?

Ich habe mir den aktuellen Auth-Beispiel-Pull-Request https://github.com/zeit/next.js/pull/1141 angeschaut
Es scheint mir, dass es nur die Authentifizierung gegen├╝ber dem next.js-Server erm├Âglicht, jedoch nicht isomorph gegen├╝ber einem separaten Dienst.

Angenommen, Sie m├Âchten den next.js-Server und die eigentliche App-API (zB REST oder GraphQL) trennen, dann m├Âchten Sie, dass sich Client und Server gegen├╝ber der API authentifizieren k├Ânnen. Ich glaube nicht, dass dir diese L├Âsung wirklich weiterhilft.

Ich dachte an eine Str├Âmung.

Entit├Ąten:

  • Kunde (C)
  • Next.js-Server (S)
  • API (A)

Ziel ist es, 3 Cookie-basierte Sitzungen einzurichten:

  1. CS
  2. CA
  3. SA

Sitzung 1) dient dazu, dass der Client den Server erkennt, und 2) 3) dienen dazu, dass sowohl der Client als auch der Server ihre jeweiligen Sitzungen verwenden k├Ânnen, um unabh├Ąngig auf die API zuzugreifen.

Das ist der Fluss:

  1. CS ist einfach, keine Authentifizierung erforderlich
  2. CA erfolgt mit Authentifizierung (zB mit Benutzername/Passwort). Zus├Ątzlich wird ein JWT bereitgestellt
  3. Der Client stellt dem Server JWT zur Verf├╝gung und verwirft es dann
  4. SA wird mit JWT durchgef├╝hrt, das dann verworfen wird

Was ist deine Meinung? Gibt es einen einfacheren Weg? Sollten wir stattdessen einfach die API mit dem next.js-Server gekoppelt halten, damit nur eine Sitzung (CS) ben├Âtigt wird?

@rauchg Ich

@timneutkens erm├Âglicht Ihnen die L├Âsung, an der Sie arbeiten, die Authentifizierung bei einem separaten Dienst?

Das ist die Idee, ja. War damit besch├Ąftigt, andere Dinge auf Next.js zu reparieren. Werde so schnell wie m├Âglich darauf zur├╝ckkommen.

Ich habe github-auth-spezifische Teile meiner App in ein ziemlich verdauliches Beispiel aufgeteilt. k├Ânnte f├╝r einige interessant sein und w├╝rde mich ├╝ber Feedback zum Code oder Flow freuen :

UPDATE: Ich habe die Beispiel-App in einen wiederverwendbaren Satz von Komponenten umgestaltet, die in die n├Ąchsten Apps "hineingeworfen" werden k├Ânnen

Follow-up: Ich habe eine Integration mit Ooth und einer GraphQL-API geschrieben.

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

Es basiert auf bestehenden Ans├Ątzen, dh Authentifizierung gegen├╝ber dem next.js-Server, dh es wird davon ausgegangen, dass die API und der Authentifizierungsserver alle im selben Prozess laufen, sodass nur eine Sitzung erstellt werden muss. Der Vorteil: Es kann prinzipiell Credentials f├╝r / erweiterbar auf praktisch jede Passport.js-Strategie speichern.

@timneutkens irgendwelche Fortschritte an dieser Front?

Ich habe meine Github-Authentifizierungs-Beispiel-App in einen wiederverwendbaren Satz von Dekoratoren und Seitenkomponenten umgestaltet, um die n├Ąchsten Apps ÔÇ×github auth inÔÇť abzulegen. Code- und Funktions-Feedback willkommen. https://github.com/possibilities/next-github-auth

Ich _glaube_, dass es interessant sein k├Ânnte, die Boards hier festzunageln und dies dann f├╝r die n├Ąchsten zu einem allgemeineren Auth-Framework weiterzuentwickeln.

@timneutkens
Entschuldigung, dass ich Sie anpinge, aber haben Sie diesbez├╝glich Fortschritte gemacht? Ich bin v├Âllig verloren, wie ich die Authentifizierung mit next.js richtig einrichten soll.

@kolpav Ich habe etwas daran gearbeitet, derzeit ├╝berschwemmt mit anderem Zeug ­čśą Das steht auf jeden Fall ziemlich weit oben auf meiner Priorit├Ątenliste f├╝r Next ­čśä

Ein klarer, gut dokumentierter und sicherer Weg zur Authentifizierung mit einer next.js-App ist entscheidend f├╝r den Erfolg als Framework.

Ich kann mich nicht erinnern, wann ich das letzte Mal ein Web ohne Authentifizierung erstellt habe.
Wie die meisten Leute, die ich mir vorstelle, m├Âchte ich auch gesicherte Anrufe an meine gesicherten Ruhedaten t├Ątigen, daher scheint JWT die naheliegende L├Âsung zu sein.

Aber es gibt so viele Diskussionen zwischen den Themen und PR's, ich bin mir nicht sicher, wo ich anfangen soll!

@timneutkens
Cool ­čĹŹ Ich denke, es wird f├╝r andere sehr wertvoll sein.

@camstuart @kolpav Es gibt einige gute, funktionierende Beispiele oben, einschlie├člich der Unterst├╝tzung von oAuth und E-Mail-basierter Authentifizierung, die sowohl JWT- als auch HTTP-Cookies von den Mitwirkenden @jaredpalmer , @luisrudge , @impronunciable , @possibilities und mir verwendet.

Um einige Links hervorzuheben, funktioniert das Auschecken:

(Das Beispiel f├╝r die Mikroauthentifizierung war gut, aber ich denke, es muss aktualisiert werden.)

Es gibt Spielraum f├╝r weitere Verbesserungen, zu denen weitere Kommentatoren oben Stellung genommen haben ÔÇô einschlie├člich einer Sitzungsspeicherkomponente und Aufteilung der Serverlogik; und ein Beispiel, das die Dinge, an denen Tim gearbeitet hat, noch weiter vereinfacht.

Einfachheit f├╝r die Authentifizierung ist ein schwieriges Gebiet f├╝r Universal-Apps, aber Sie sollten in der Lage sein, die obigen Beispiele zum Laufen zu bringen - oder einfach die Demos direkt auszuprobieren - und sehen, wie sie ohne allzu viel Aufhebens funktionieren.

@iaincollins Das sind tolle Beispiele. Aber wie kann ich (zum Beispiel) Starter-Projekt verwenden? Also wenn ich meine App bauen m├Âchte. Ich muss dieses Repo klonen? Oder muss ich Code aus dem Starterprojekt St├╝ck f├╝r St├╝ck in meinen eigenen Code "kopieren und einf├╝gen"?

Wenn das Starterprojekt aktualisiert wird - was soll ich tun?

@iaincollins
Sch├Âne Beispiele, besonders deine.
Trotzdem w├╝rde ich gerne ein Auth-Beispiel mit zeit-G├╝tesiegel darauf sehen ­čśä alle Augen w├╝rden in eine Richtung zeigen, damit Fehler oder Irrt├╝mer nicht unbemerkt bleiben. Im Moment habe ich meine eigene Arbeitsberechtigung, bin mir aber nicht sicher, wie sicher sie ist.

Zugegeben @kolpav , Ihre eigene Sicherheit zu rollen ist eine knifflige Angelegenheit. Am besten den Experten ├╝berlassen

Ich habe daf├╝r einen Stack erstellt, der die Authentifizierung mit GraphQL problemlos verarbeiten kann: https://github.com/thebillkidy/MERGE-Stack

@salmazov Ich habe einen n├╝tzlichen Weg gefunden, um zu beginnen und zu verstehen, was in einem Beispiel oder Starterprojekt vor sich geht, herausziehe , die nicht relevant sind, bis nur noch der Code f├╝r die Funktionalit├Ąt ├╝brig bleibt Sie implementieren m├Âchten; und dann zu versuchen, genau diese Funktionalit├Ąt auf ein anderes Projekt zu portieren.

@kolpav @camstuart Dieser Thread enth├Ąlt eine wirklich ausf├╝hrliche Diskussion verschiedener Sicherheitsmodelle, einschlie├člich der Entlarvung einiger h├Ąufiger Missverst├Ąndnisse und Kompromisse. Ich m├Âchte insbesondere die Punkte zu HTTP Only-Cookies und CSRF-Tokens beachten (und den zus├Ątzlichen Schutz, den sie gegen├╝ber XSS und CSRF gegen├╝ber der Verwendung von JWT und/oder der Webspeicher-API f├╝r Sitzungstoken bieten). Es lohnt sich wirklich zu lesen.

@iaincollins Wolltest du etwas verlinken? :L├Ącheln:

Hallo Leute :)

Ich habe eine Frage, ich habe als n├Ąchstes gelesen, dass die Token f├╝r die Authentifizierung mit jwt nicht von localstorage abgerufen werden k├Ânnen.

Wenn ich einen Server zum Rendern rendern rendern im Glossar erkl├Ąrt habe einfach die erste Ladung meiner Seite mit weiter. Und ich habe einen anderen Server f├╝r meine API. Diese erhalten den Benutzer/Pass vom Client und geben ein jwt. In welchen F├Ąllen muss ich den Token in den Server bekommen??

Warum ben├Âtige ich Token im Renderserver (als n├Ąchstes)?

Wenn der Client das Token nicht an den API-Server sendet, gibt die API die Daten nicht weiter und der Benutzer kann keine privaten Informationen abrufen. Ich verstehe nicht, warum ich das Token an den Renderserver senden muss.

@kamilml

Dies k├Ânnte helfen. Im Allgemeinen haben Sie zwei M├Âglichkeiten:

  1. Next server JWT geben (evtl. per Cookie). Dadurch kann der Next-Server im Auftrag des Clients API-Aufrufe t├Ątigen. Sie m├Âchten dies, wenn Ihnen das vollst├Ąndige serverseitige Rendering wichtig ist.

  2. Speichern Sie JWT im lokalen Speicher des Clients und geben Sie dem Next-Server keinen Zugriff darauf. In diesem Fall k├Ânnen Sie einfach die serverseitigen API-Aufrufe umgehen und das vollst├Ąndige Rendern verschieben, bis das Laden der Clientseite abgeschlossen ist.

Entschuldigung f├╝r die Wiederer├Âffnung, aber ich dachte, ich w├╝rde meine 2 Cent zu diesem Thread hinzuf├╝gen und wie sich meine anf├Ąngliche F&E in diesem Bereich entwickelt. Weniger Codebeispiele, mehr High-Level-Flow.

Erstens ist der Gro├čteil unserer App bereits in Symfony 3 (PHP) integriert und verwendet Vue f├╝r ein hybrides Erlebnis. Der Server rendert eine Wrapper-Seite und weist __INITIAL_STATE__ App-Daten zu, damit die App sie abholen kann. Dies f├╝hrte zu einer Entscheidung zwischen dem Rendern von Marketingseiten in Symfony (f├╝r SEO) und der Wahl von UX/UI gegen├╝ber SEO in anderen Bereichen, indem Daten ├╝ber JS abgerufen und ein SPA-├Ąhnliches Gef├╝hl vermittelt wird. Erw├Ąhnenswert ist auch, dass nicht alle Seiten bin├Ąr ├Âffentlich/privat sind (wie ich in einigen Beispielen gesehen habe). Einige Seiten sind standardm├Ą├čig ├Âffentlich und werden bei Authentifizierung anders gerendert. Wir erwogen, f├╝r Teile der Site ein SPA zu verwenden, aber in vielerlei Hinsicht war es eine schlechtere UX/UI (langsameres TTI, Fortschrittsbalken usw.). Au├čerdem l├Âst das das SEO-Problem nicht, es sei denn, wir f├╝hren FOUC ein und rendern Text zweimal (einmal ├╝ber Symfony, noch einmal als JS-Komponenten) usw.

Geben Sie SSR / Universal-JS ein...

In meinem Fall habe ich die PHPSESSID Logik nachgeahmt, indem ich ein HttpOnly UJSSESSID Cookie erstellt habe (den Namen erfunden) und den Wert auf den des Benutzers gesetzt habe JWT. Die Symfony-App gibt dies bei jeder Seitenanfrage weiter, w├Ąhrend der Benutzer auf der Site navigiert. Wenn der Benutzer die UJS-Seiten aufruft, erh├Ąlt die Serverseite dieser Apps die Cookies in der Anfrage (gem├Ą├č dem eingebauten Verhalten des Browsers). Wenn das UJSSESSID Cookie gesetzt ist, ruft die App die API auf, um die Benutzerinformationen abzurufen (z. B. /api/v1/users/me mit ├ťbergabe des Tokens ├╝ber den Authentication Header). Der Rest der Aufrufe erfolgt ├╝ber die API unter Verwendung desselben Tokens. Der Symfony-Logout-Mechanismus l├Âscht das UJSSESSID Cookie. Wenn die UJS-App das n├Ąchste Mal geladen wird, rendert sie die Seiten im anonymen Benutzermodus. Zu Ihrer Information, das Routing von Symfony- und UJS-Seiten erfolgt ├╝ber Apache ProxyPass . LocalStorage wird nicht verwendet.

Das Endergebnis ist eine nahtlose UX, bei der sich der Benutzer auf einigen PHP-Seiten mit clientseitigem JS und auf einigen UJS-Seiten befindet. Dies erm├Âglicht uns, A/B-Tests durchzuf├╝hren und die Site iterativ zu aktualisieren ÔÇô nicht jeder kann bei Null anfangen :)

W├Ąhrend dies aufgrund der symbiotischen PHP/UJS etwas komplizierter ist, kann das gleiche Prinzip in einer vollst├Ąndigen UJS-L├Âsung mit einer API- oder Node.js-Server-Middleware (z. B. Express, Adonis usw.) verwendet werden. Anstatt das UJSSESSID Cookie ├╝ber eine PHP-Seitenanforderung ( HttpOnly Flag) zu setzen, lassen Sie den Benutzer sich ├╝ber Ihr SPA/UJS anmelden und setzen das Cookie dort. Was Sie NICHT tun sollten, ist Ihre App zu verwenden, um das JWT zu entschl├╝sseln oder Anrufe von Drittanbietern zu t├Ątigen, f├╝r die ein client_secret erforderlich ist. Verwenden Sie dazu eine Middleware, die auf dem Server verbleibt.

Hoffe das hilft jemandem. Andere Beispiele, die ich gesehen habe, waren mir ein wenig zu Petrischale.

@jaredpalmer Hey, danke f├╝r diese Implementierung, ich habe es versucht, habe einfach deinen gesamten Code kopiert und deine Dashboard.js durch meine index.js ersetzt, die wie folgt aussieht:

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

export default withAuth(index)

und in withAuth hoc habe ich es ge├Ąndert, um auf die Anmeldeseite umzuleiten.
Aber bevor es auf die Anmeldeseite umleitet, blinkt der Inhalt der Indexseite noch ein wenig. :S

Wie ist der Status dieses Problems? ­čśç

Das ist etwas ├╝berw├Ąltigend f├╝r neue Leute, die sich die ganze Diskussion durchlesen. Ich habe mich entschieden, die sehr einfache Authentifizierung hier zu implementieren. Nur 2 Seiten (Index, Login) und ein benutzerdefinierter Server
https://github.com/trandainhan/next.js-example-authentication-with-jwt

Grunds├Ątzlich haben wir eine Authentifizierungs-Middleware im Server, um das Token im Header jeder Anfrage zu ├╝berpr├╝fen. Der jwt-Token wird in Cookies gespeichert. Ich finde das ist sehr einfach, geradlinig und funktioniert sehr gut.

@trandainhan K├Ânnten Sie einen POST-Endpunkt hinzuf├╝gen, der ein geheimes Token verwendet, um CSRF-Angriffe zu verhindern?

@sbking Aktualisierter Quellcode mit einem Beispiel-Endpunkt, der durch CSRF-Angriffe gesch├╝tzt ist

Ist das einsatzbereit ­čśČ?

Hat jemand Authentifizierung mit redux-auth-wrapper versucht?

Hallo zusammen! In den letzten Monaten habe ich erstellt und jetzt verfeinert

Es verf├╝gt ├╝ber:

  • Registrierung mit E-Mail und Passwort
  • Login mit E-Mail oder Benutzername und Passwort
  • Kontoseite, auf der Sie Ihren Benutzernamen festlegen, Ihr Passwort ├Ąndern und eine Best├Ątigungs-E-Mail erneut senden k├Ânnen
  • Passwort vergessen/Passwort zur├╝cksetzen Seiten
  • E-Mail-Seite best├Ątigen
  • Eine grundlegende GraphQL-API, die mit einer MongoDB verkn├╝pft ist (1 Datei, kann leicht entfernt werden)
  • Minimaler Boilerplate (so viel Logik wie m├Âglich ist in Bibliotheken gekapselt)

Sehen Sie sich hier eine Live-Demo an: http://staart.nmr.io/

Ich habe es haupts├Ąchlich f├╝r mich f├╝r Rapid Prototyping gemacht, um schnell mit einer Anwendung mit einem einfachen, funktionierenden Kontensystem zu beginnen, das nicht auf externe Dienste angewiesen ist. Ich bin mit den Ergebnissen recht zufrieden. Ich beabsichtige, diese Bibliotheken weiterhin zu verwenden und zu warten, also probieren Sie es aus, wenn Sie der Meinung sind, dass ein etabliertes Kontensystem + eine Benutzeroberfl├Ąche f├╝r den Knoten noch fehlt.

@trandainhan Danke, das ist ein wirklich gro├čartiges Beispiel und f├╝r viele Leute viel einfacher und w├╝rde in vielen Szenarien funktionieren.

Ich werde mir ├╝berlegen, ob / wie ich die aktuelle Logik in nextjs-starter anpassen kann, um stattdessen so etwas sicher zu verwenden, w├Ąhrend ich immer noch mit der Express-Sitzungslogik f├╝r reale Anwendungsf├Ąlle kompatibel bin (wie die Verwendung von Dinge wie Google oAuth APIs, bei denen ich den Server ben├Âtige, um die bei der ersten Anmeldung gew├Ąhrten Token aufzubewahren und zu verfolgen).

Ich habe noch nicht herausgefunden, ob das m├Âglich ist, aber es w├Ąre f├╝r die Leute viel einfacher, wenn es so w├Ąre.

Wenn nicht, ist es zumindest einen netten Beitrag wert, um den Leuten die verschiedenen Optionen zu erkl├Ąren.

@trandainhan : Wenn ich <Link href="/">Home</Link> in login.js hinzuf├╝ge und dann auf den generierten Link klicke, kann ich auf die index.js zugreifen, ohne eingeloggt zu sein. Wie w├╝rden Sie vorschlagen, dies in Ihrem Beispiel zu beheben?

@iaincollins Ich sehe die meisten L├Âsungen hier, die sich gegen einen Oauth-Dienst authentifizieren. Gibt es eine gute L├Âsung f├╝r die Authentifizierung bei einer API, die auf JWT basiert?

@paulwehner Ich denke, das passiert, weil @trandainhan nur das serverseitige

@carlos-peru Unter der Haube verwendet Link tats├Ąchlich next/router, um einen neuen Pfad in den Browserverlauf zu schieben. Scheint, als ob die meisten Dinge vom Browser gehandhabt werden, hier gibt es nichts f├╝r eine Middleware auf der Serverseite zu tun. Bisher kann ich nur daran denken, eine eigene Link-Komponente zu erstellen und andere Dinge zu tun, wenn wir die URL ├Ąndern.

@carlos-peru Sie k├Ânnen jederzeit einen benutzerdefinierten Server verwenden, um die volle Kontrolle ├╝ber das Routing zu haben.

Danke @trandainhan und @kolpav! Ich muss ein besseres Verst├Ąndnis haben, nachdem ich einige Zeit ├╝ber das Wochenende verbracht habe. Es ist mir auch gelungen, eine L├Âsung zu implementieren, die auf HOC basiert und das jwt-Token auf einem Cookie h├Ąlt, sodass sowohl der Server als auch der Client die API nutzen k├Ânnen.

@nmaro Ich habe ein Backend mit JWT-Authentifizierung f├╝r eine Website in next.js und eine App (react-native).

So. Ich denke im n├Ąchsten Modell: Der Client erh├Ąlt einen Facebook-Token (Der Benutzer akzeptiert das Facebook-Login) und dann sendet der Client den Token an das Backend, um den Benutzer-Token zu ├╝berpr├╝fen und zu validieren (passport-facebook-token im Node-js-Backend) . Wenn das Token in Ordnung ist, sendet das Back-End dann das im Back-End generierte JWT an den Client.

Das Problem? Ihr Tool kann den Schl├╝ssel von Facebook und Google beziehen? Ich verwende hello.js, ist aber nicht mit next.js kompatibel und die ganze Welt verwendet Pass-Facebook. Ich denke, es ist ein gro├čer Fehler, da der API-Server mit dem Webclient und der mobilen App kompatibel sein muss.

Dankesch├Ân

PS: Ich kann in deinem Slack-Channel keine Einladung erhalten.

@hmontes hier - eine Einladung zum Slack-Channel f├╝r das ooth- Projekt (Benutzerkonten f├╝r Node, insbesondere next.js) gerne mitmachen. Ooth verwendet Passport-Facebook-Token (nicht Passport-Facebook) und Passport-Google-ID-Token, die meiner Meinung nach Ihr Problem l├Âsen.

@nmaro Ich m├Âchte dir bei deinem Projekt helfen. Ich habe auch ein Backend mit Graphql mit Passport-Facebok und Passport-Google-ID-Token !!!

Aber. Kennen Sie ein kompatibles Paket zum Verbinden des Facebook/Google-Clients in next.js?

Auf der Client-Seite k├Ânntest du ein ├Ąhnliches Muster verwenden, wie ich es hier verwendet habe: 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
(anstelle von oothClient.authenticate senden Sie einfach eine Post-Anfrage an Ihre Authentifizierungsroute).

@timneutkens w├Ąre eine PR mit einem minimalen With-Ooth-Beispiel willkommen?

@nmaro in Ihrem Beispiel. Warum verwenden Sie componentDidMount anstelle von componentWillMount?

Ich erstelle eine HoC-Komponente (Anbieter) f├╝r die Google-Anmeldung.

Wird ComponentWillMount nur auf dem Client aufgerufen? Dann sollte es gut sein.

Okay. Vielen Dank f├╝r Ihre Beispiele. Endlich kann ich Auth mit Social Media implementieren.

Letzte Frage. Ich habe ein access_token und ein refresh_token erstellt und m├Âchte localStorage einf├╝gen, um die Daten zu speichern.

Wo kann ich das in next.js einf├╝gen, um die Anmeldung beim Aktualisieren der Seite zu ├╝berpr├╝fen? In create-react-app habe ich das in index.js eingef├╝gt

...
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}>
....

Dankesch├Ân

Bei ooth speichere ich die Facebook-Token nicht, ich verwende sie nur einmal mit Passport und erstelle dann eine normale Cookie-basierte Benutzersitzung.

Ah. Okay. Ich verwende JWT anstelle von Sitzungen. Also sende ich access_token an das Backend, es pr├╝ft, ob das Token im Dienst g├╝ltig ist (google, facebook), dann ob der Benutzer in meiner App existiert und schicke mir ein JWT zur├╝ck.

Dankesch├Ân :)

Ich sollte hinzuf├╝gen, dass es gef├Ąhrlich ist, JWTs in localstorage zu speichern (wegen XSS), besser als Cookies zu senden, wenn sich alles auf einem Server / einer Dom├Ąne befindet, damit der JavaScript-Code des Clients das JWT nicht abrufen kann, aber der Browser sendet die JWT automatisch als Cookies. JWTs sind knifflig (siehe lange Diskussionen oben), deshalb verwende ich in Ooth Sessions.

Ich verwende ein JWT nur, wenn ooth als externer Authentifizierungs-Microservice verwendet wird (da Cookies nur auf derselben Dom├Ąne funktionieren), und selbst dann verwende ich es genau einmal, um dann eine Sitzung mit dem Server zu erstellen, also wird es nirgendwo auf dem Client gespeichert .

Um die JWT-Sicherheit zu erh├Âhen, k├Ânnen Sie ein Aktualisierungstoken (von oauth2 entnommen) verwenden.

Kann eine mobile App mit Cookies umgehen?

@nmaro Okey. Ich verstehe dich. Entschuldigung f├╝r meinen Fehler.

Haben Sie ein Tutorial oder einen Code, um das JWT-Token in einem Cookie zu speichern? Ich suche https://github.com/zeit/next.js/blob/master/examples/with-firebase-authentication (Mein Authentifizierungssystem ist mit graphql)

Nein, tut mir leid, das habe ich nie gemacht.

@hmontes @nmaro
Ich habe das f├╝r mich selbst geschrieben, kann aber helfen:
https://github.com/malixsys/mobazoo

Hey @malixsys, danke f├╝rs Teilen. Etwas, das ich aus Ihrem Code nicht verstehe: Es scheint, als w├╝rden Sie API_BASE_URL auf etwas Externes konfigurieren, richtig? Wenn Sie sich bei dieser API authentifizieren, w├╝rde sie wahrscheinlich eine Cookie-basierte Sitzung starten, oder? Aber wie ├╝bertragen Sie dieses Cookie dann auf den next.js-Server, vorausgesetzt, der next.js-Server befindet sich in einer anderen Dom├Ąne?

Ah nein, wie ich sehe, setzen Sie /auth/signin im gleichen Prozess. Ok, dann ist es im Grunde der gleiche Ansatz, den ich f├╝r ooth mit next.js / start verwendet habe.

Eigentlich nein, ich bin immer noch verwirrt: In /auth/signin gibt man ein JWT zur├╝ck, aber man macht auf der Client-Seite nie etwas damit. Sp├Ąter "getUserFromCookie", aber ich sehe nicht, wo Sie das Cookie setzen.

@nmaro Ich wollte nur, dass zun├Ąchst ein grundlegendes Login mit Universal funktioniert. Ich habe vorerst sowohl ein jwt als auch ein Cookie gesetzt. Das Cookie wird verwendet, um universell zu tun. Ich muss das jwt noch in einem anderen Axios-Aufruf in diesem Repo verwenden. Ich mache in einem privaten Fork, wo API_BASE_URL auf eine andere Domain zeigt...
Es steht alles auf meiner TODO-Liste, mit PWA.
Bitte z├Âgern Sie nicht, ein Problem zu er├Âffnen oder mich hier anzupingen...

@nmaro- Cookie wird hier in saveUser() : https://github.com/malixsys/mobazoo/blob/master/utils/auth.js

Ich wei├č, dass dieses Problem geschlossen ist, aber ich m├Âchte meine L├Âsung zeigen.
https://next-auth.now.sh/
Ich denke, es ist ein bisschen ├Ąhnlich wie die Website von zeit.co

9. April

Ich habe etwas daran gearbeitet, derzeit ├╝berschwemmt mit anderem Zeug ­čśą Das steht auf jeden Fall ziemlich weit oben auf meiner Priorit├Ątenliste f├╝r Next

22. September #2974

Wir planen, bald ein offizielles Auth-Beispiel zu ver├Âffentlichen. K├Ânnten Sie dies als separates Repository ver├Âffentlichen? Thaaaanks!

@timneutkens

Hallo, Entschuldigung, dass ich Sie erneut dar├╝ber ├Ąrgern muss, aber k├Ânnten Sie uns bitte mitteilen, wie der Status des offiziellen Authentifizierungsbeispiels ist? Es ist definitiv etwas, was ich gerne sehen w├╝rde und nach der Anzahl der Kommentare in dieser Ausgabe auch andere zu urteilen. Wie hoch ist es also auf der Priorit├Ątenliste und sollten wir uns Hoffnungen machen? ­čśä

Hallo @kolpav , sie haben dies offiziell als auf der Roadmap f├╝r Next.js 5 angek├╝ndigt.

Schlie├člich f├╝gen wir einige stark nachgefragte Beispiele (wie Benutzerauthentifizierung), verbesserte Dokumentation f├╝r Next.js-Interna und kleinere Funktionen und Bugfixes hinzu.

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

@babenzele Das sind tolle Neuigkeiten. Das muss ich ├╝bersehen haben

Wo k├Ânnen wir ├╝ber die Entwicklung von Next.js 5 auf dem Laufenden bleiben? Ich integriere derzeit auth0, w├Ąre aber toll, wenn ich einen offiziellen nextjs-Authentifizierungspfad / ein Beispiel h├Ątte, dem du folgen k├Ânntest

Es scheint, dass Next.js dringend ein offizielles lokales Authentifizierungsbeispiel mit JWT/cookies/localStorage (oder einer Kombination davon, solange es sicher und vor XSS/CSRF gesch├╝tzt ist) ben├Âtigt ... Ich habe mehrere Wochen damit verbracht, dies zu versuchen Mit einem separaten Express-API-Server mit einer lokalen Passport.js-Strategie k├Ânnen Sie dies erreichen. Ich habe JWT in einem Cookie/localStorage f├╝r zustandslose Anfragen ausprobiert, und ich habe auch ein regul├Ąres Cookie mit der Sitzungs-ID der Express-Session-Middleware ausprobiert, als ich JWT und die Zustandslosigkeit endg├╝ltig aufgegeben habe. Ich bin auf Probleme gesto├čen, bei denen aufgrund der Funktionsweise von Express-Session zus├Ątzliche Sitzungen auf dem Express-API-Server erstellt wurden (versucht mit saveUninitialized: false). Ich habe ├╝berlegt, den Express-Code in meiner Next.js-App in server.js zu verschieben, aber ich h├Ątte es wirklich lieber, wenn es ein separater Server w├Ąre. Ich bin mir auch ziemlich sicher, dass meine Implementierung nicht sicher vor XSS/CSRF oder Cookie-Hijacking ist. Wir brauchen ein offizielles Beispiel, das Best Practices f├╝r die lokale Authentifizierung/Anmeldung abdeckt, oder vielleicht ein offizielles Modul als Teil von Next.js, das die Komplexit├Ąt f├╝r uns ├╝bernimmt!

W├Ąhrend wir auf Next.js 5.x und weitere Beispiele warten, m├Âchten Sie vielleicht einen Blick auf https://nextjs-starter.now.sh werfen, das immer noch aktiv gepflegt wird und Next.js mit Express, Express Sessions, CSRF ( CRSF-Token), XSS (nur HTTP-Cookies f├╝r Sitzungstoken) und verwendet Passport JS zur Unterst├╝tzung von oAuth und E-Mail.

Ich bin gerade dabei, den Authentifizierungscode in ein Modul umzuwandeln, was es wirklich einfach macht, Next.js-Projekten auf einfache Weise eine Authentifizierung hinzuzuf├╝gen. Das Modul sollte es Ihnen erm├Âglichen, es problemlos mit jeder beliebigen Datenbank zu verwenden, ohne eine Menge Code aus dem Starter-Projektbeispiel kopieren zu m├╝ssen. Ich hoffe, dass ich diese Woche damit fertig bin.

Als Referenz bietet die Methode "Double Submit Cookie" eine einfache M├Âglichkeit, den CSRF-Schutz hinzuzuf├╝gen, wenn Sie nach einem einfachen, aber sicheren Ansatz suchen.

Das Problem mit JWT in localStorage ist, dass es immer von clientseitigem JavaScript gelesen werden kann, also einem Vektor f├╝r Session-Hijacking ├╝ber XSS, wenn Sie nicht vertrauensw├╝rdigen Inhalt haben (zB von Benutzern eingereichte Inhalte oder Anzeigen).

Wenn Sie HTTP Only-Cookies f├╝r Sitzungstoken verwenden ÔÇô oder so etwas wie ein JWT mit einem Tokenwert in einem HTTP Only (oder das gesamte JWT verschl├╝sseln und mit einem HTTP Only-Token auf dem Server entschl├╝sseln) ÔÇô dann sind Sitzungen so gesch├╝tzt wie m├Âglich Sein. Die Idee ist nur, dass Sitzungstoken idealerweise nicht ├╝ber clientseitiges JavaScript gelesen werden k├Ânnen.

Nat├╝rlich verwenden viele Websites keine HTTP Only-Cookies, da dies f├╝r Single Page Apps m├╝hsam ist und ausnahmslos eine Authentifizierungslogik im Frontend erfordert, aber es ist immer noch der ideale Ansatz.

Eine andere Option ist immer noch https://github.com/nmaro/ooth, die aktiv gepflegt wird, bereits in Paketen vorliegt und in einigen Produktions-Apps verwendet wird.

@iaincollins Ich habe das Next.js-

Hallo @kelleg1 ,

Das separate Modul wird jetzt als next-auth- Modul ver├Âffentlicht, um die Verwendung in anderen Projekten zu erleichtern. Es enth├Ąlt ein Beispielprojekt, das zeigt, wie es verwendet wird.

Als weitere Referenz verwendet das nextjs-starter.now.sh- Projekt jetzt auch die next-auth, was den Code im Starter-Projekt stark vereinfacht - und es ist jetzt viel einfacher, Unterst├╝tzung f├╝r neue oAuth-Anbieter hinzuzuf├╝gen oder mit anderen Datenbanken zu verwenden ( obwohl das Beispiel immer noch Mongo DB verwendet).

Es ist jedoch immer noch etwas kompliziert, wenn Sie also eine vorhandene App haben, ist es m├Âglicherweise einfacher, sie als Referenz zu verwenden, aber wenn ja, hoffe ich, dass es hilft

NB: CSRF ist derzeit noch ziemlich eng daran gekoppelt. Es verwendet lusca, nimmt also an, dass res.locals._csrf gesetzt ist, aber verschiedene CSRF-Bibliotheken verwenden unterschiedliche private Vars.

Ich wei├č, dass die Verwendung immer noch komplizierter ist, als es jedem lieb ist, aber zumindest ist der Authentifizierungscode jetzt endlich in ein Modul unterteilt, damit ich mit der Umgestaltung beginnen kann. Ich hoffe, es im Laufe der Zeit einfacher zu verwenden (mit Standardhandlern f├╝r verschiedene Datenbanken und einfacherer Konfiguration von oAuth).

@iaincollins es sieht so aus, als ob die einzige Abh├Ąngigkeit von next.js https://github.com/iaincollins/next-auth/blob/master/index.js#L342 ist ? Wenn ja, w├Ąre es gro├čartig, die lib next.js-agnostisch zu machen.

@sedubois Stimme voll und ganz zu!

Obwohl dies wahrscheinlich eine gute Diskussion f├╝r die GitHub-Repo-Probleme ist und nicht hier. ­čÖé Wenn Sie Verbesserungs-, Vereinfachungs- und allgemeinere Verbesserungsm├Âglichkeiten vorschlagen m├Âchten, w├╝rden Sie gerne zusammenarbeiten.

(Es ist immer noch ein prim├Ąres Ziel, etwas so einfach wie m├Âglich mit next zu verwenden, aber ich sehe nicht, dass es exklusiv sein muss, selbst wenn es am Ende auch mit den n├Ąchsten spezifischen fokussierten Optionen endet.)

@timneutkens Herzlichen Gl├╝ckwunsch zur Ver├Âffentlichung von nextjs 5. Wird in naher Zukunft ein offizielles lokales Authentifizierungsbeispiel zum Beispielordner hinzugef├╝gt? Oder ist das noch in Arbeit f├╝r eine sp├Ątere Ver├Âffentlichung?

Ooth verf├╝gt jetzt ├╝ber eine umfassende Dokumentation, einschlie├člich der Besonderheiten der next.js-Authentifizierung .

@jaredpalmer Ich mag deinen Ansatz, ich habe Teile deiner Implementierung kopiert. getUser Methode

Sie sollten es in einem Cookie speichern. Ich habe das geschrieben, bevor Next benutzerdefinierte Server unterst├╝tzte.

@jaredpalmer Kannst du mir mehr dar├╝ber erz├Ąhlen? Sollten wir alles in Cookies und nicht in lokaler Speicherung speichern? W├Ąre Ihr HOC auch anders? Bedeutet das, dass wir jetzt die Methode getInitialProps f├╝r das serverseitige Rendern gesch├╝tzter Websites verwenden k├Ânnen?

Nur ein Hinweis, _wenn Sie von der Speicherung sensibler Daten im lokalen Speicher / Webspeicher sprechen_:

"Speichern Sie niemals sensible Daten mit Web Storage: Web Storage ist kein sicherer Speicher. Es ist nicht ÔÇ×sichererÔÇť als Cookies, da es nicht ├╝ber das Kabel ├╝bertragen wird. Es ist nicht verschl├╝sselt. Es gibt kein sicheres oder nur HTTP-Flag, also dies ist kein Ort, um Sitzungs- oder andere Sicherheitstoken aufzubewahren."

Setzen Sie das Token nach der Anmeldung in einem Cookie. Cookie-js verwenden. Verwenden Sie dann den Express-Cookie-Parser auf dem Server, damit Sie nach get req.headers.cookies.myToken oder gleichwertig suchen k├Ânnen. ├ťberpr├╝fen Sie in getInitialProps eines hoc, ob req existiert, und holen Sie sich dann das Token aus req.cookies, andernfalls holen Sie es auf dem Client von Cookies.get('mytoken'). An diesem Punkt haben Sie Zugriff auf Ihr Token auf dem Client und Server. Dann m├Âchten Sie einen fetch/axios-Wrapper/eine Instanz erstellen und sie mit der ctx von next in getInitialProps zusammenf├╝hren, damit alle Ihre Seiten eine M├Âglichkeit haben, authentifizierte isomorphe Anfragen zu stellen. Sie k├Ânnen Ihren Benutzer auch nur in den Hoc bringen. Das m├╝ssen Sie also nicht ├╝berall wiederholen. Sie k├Ânnen dann bei Bedarf weitere Hocs f├╝r allgemeine Entit├Ąten wie withUser(withTeam(Page)) erstellen.

getUser ist eine schlechte Idee, Sie sollten nur das Token speichern.

@jaredpalmer Ich habe einen Ansatz fast genau so gebaut und alles funktioniert gut. Das Problem, das ich jetzt zu l├Âsen versuche, ist die Aktualisierung der Token. Die API, mit der ich arbeite, hat relativ kurzlebige Token (2 Stunden) und ich versuche, mich mit einem System zu besch├Ąftigen, damit der Benutzer w├Ąhrend der Verwendung der App angemeldet bleibt.
Hast du dazu einen Input?

Sie k├Ânnen auch bei jedem Seitenwechsel eine Anfrage speichern, indem Sie keine Daten f├╝r Ihren Benutzer durch next.js weiterleiten. Dazu w├╝rden Sie das Token aus dem Cookie in server.js lesen und versuchen, den Benutzer abzurufen und diesen an den Request-Handler des n├Ąchsten weiterzuleiten. Holen Sie es im Dokument von props und speichern Sie es in JSON auf wie window.USER. Dann lesen Sie es in Ihrem hoc einfach aus dem Fenster, wenn Sie sich im Client-Land befinden. Schlie├člich sollten Sie axios mit einem Response-Interceptor verwenden, der Ihr Cookie nach Erhalt des 403-Codes sofort l├Âscht und die Seite neu l├Ądt

@pbrandone Auch wenn es sich wiederholt, besteht die einfachste und vorhersehbarste L├Âsung darin, Ihr Token bei jeder Anfrage zu senden und ein neu aktualisiertes Token im Header/Textk├Ârper der Antwort zu erhalten. Ihr Client aktualisiert seinen bekannten Wert bei jedem Anfrage-/Antwort-Zyklus und gew├Ąhrt effektiv Einweg-Token, die nie veraltet sind und nicht missbraucht werden k├Ânnen.

Normalerweise wird bei diesem Ansatz /token/refresh nur f├╝r das anf├Ąngliche "Aufwachen" der Anwendung verwendet (denken Sie an componentWillMount Hook f├╝r <App/> ), um zu pr├╝fen, ob die zuletzt gespeicherte Token ist noch g├╝ltig und verwendbar.

Ich musste mich nie mit Refresh-Token befassen, aber ich w├╝rde versuchen, es in einem Axios-Abfangj├Ąger zu tun. M├╝sste mehr dar├╝ber nachdenken, aber theoretisch w├╝rden Sie eine schlechte Anforderung abfangen, dann mit dem Refresh-Token ein neues Token abrufen, das Cookie mit dem neuen Token setzen und die erste Anfrage mit dem neuen Token erneut abspielen. Axios-Interceptors sind wirklich m├Ąchtig, weil sie es Ihnen erm├Âglichen, solche Dinge abstrahiert und aus dem Blickfeld Ihres Produktcodes zu halten. M├Âglicherweise m├╝ssen Sie einen Request- und Response-Interceptor schreiben und/oder eine Art zustandsbehaftetes Objekt/eine Karte in Bearbeitung halten, die haarig werden k├Ânnte. Hoffentlich hilft das

Oder tun Sie, was Luke gesagt hat. Viel einfacher.

Wenn Sie Token aktualisieren m├Âchten, m├╝ssen Sie das Cookie (wenn Sie Cookies verwenden) ├╝ber eine benutzerdefinierte Servereinrichtung abfangen. Ich habe dies mit Express gemacht. Andernfalls k├Ânnen Sie dies alles clientseitig mit JWT-Token tun. Da ich meine ├╝ber Cookies gemacht habe, hatte ich 2 Anwendungsf├Ąlle - die Handhabung von Navigationsanfragen auf der Clientseite und Seitenanfragen auf der Serverseite (immer wenn jemand manuell eine URL eingibt oder auf die Seitenaktualisierung klickt.) Aber im Grunde sind sie der gleiche Ablauf wird nur anders ausgef├╝hrt, da einer clientseitig und einer serverseitig ist. Auf der Serverseite habe ich, seit ich Express verwendet habe, gerade eine Middleware erstellt, um das Cookie zu verarbeiten, das darin enthaltene JWT zu entschl├╝sseln und den Ablauf zu ├╝berpr├╝fen. Wenn es abgelaufen ist, stellen Sie eine Anforderung zum Abrufen eines neuen Tokens und ├╝bergeben Sie den decodierten Benutzer weiterhin an Redux auf dem Client. Auf dem Client habe ich einen HOC-Wrapper f├╝r sichere Links, der st├Ąndig nach dem Benutzer sucht, jedes Mal, wenn Sie irgendwo auf dem Client navigieren. Das HOC holt sich Ihr Cookie oder JWT (in meinem Fall ist mein JWT in einem Cookie) und pr├╝ft schnell, ob es noch g├╝ltig ist. Wenn es nicht g├╝ltig ist, versucht es, ein aktualisiertes JWT/Cookie zu erhalten, und f├Ąhrt fort, andernfalls werden Sie abgemeldet. Ja komplizierter, aber auch sicherer. Ich hoffe, das hilft! Bei Interesse gerne Fragen stellen - ich habe eine Weile gebraucht, um alles herauszufinden. Ich pers├Ânlich frage mich, ob sich Leute mit Github oder FB usw. anmelden - wahrscheinlich f├╝r viele F├Ąlle in Ordnung, aber in einigen F├Ąllen ist es einfach nicht professionell. Ich habe noch keine Bank, das Gesundheitswesen, meine Rechnungen usw. gesehen - melde mich mit meinem FB-Konto an. K├Ânnte aber nur eine Frage der Zeit sein ;)

Was das Aktualisieren von Zugriffstoken betrifft;
Ich bin mir nicht sicher, ob dies der richtige Weg ist, aber meine Zugriffstoken sind sehr kurzlebig (etwa eine Minute). Um mit clientseitigen Token-Ablaufproblemen umzugehen, habe ich diesen Ansatz gew├Ąhlt;
Jedes Mal, wenn eine Seite geladen wird, ├╝berpr├╝ft sie, ob das Token abgelaufen ist, und aktualisiert es in diesem Fall. Wenn es jedoch noch g├╝ltig ist, ruft es eine Methode auf, die ├╝berpr├╝ft, wie viel Zeit bis zum Ablauf vergeht, und ein Zeitlimit festlegt, das das Zugriffstoken nach Ablauf aktualisiert. Und dann wiederholt dieser Vorgang, solange der Besucher auf der Website ist.

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

Dies gibt Millisekunden bis zum Ablauf zur├╝ck:

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

Jedes Feedback zu diesem Ansatz w├Ąre sehr willkommen

@kunokdev - Ich denke, das ist ein guter Anfang. Ich habe eine ├Ąhnliche Funktion, bei der ich die verbleibende Zeit berechnen musste, in eine Funktion verschoben, die nur einen booleschen Wert zur├╝ckgegeben hat, je nachdem, ob sie abgelaufen war oder nicht, und das machte meinen Code etwas lesbarer und einfacher und ich musste mich nicht um das Zur├╝cksetzen von Timern k├╝mmern. Dann ├╝berpr├╝fe ich einfach, ob der Benutzer abgelaufen ist oder nicht bei einer Anfrage, die eine Authentifizierung erfordert. Wenn ich einen Countdown-Timer oder ├Ąhnliches h├Ątte, der f├╝r den Client oder das Debuggen sichtbar w├Ąre, w├Ąre Ihre Funktion ideal. Das sind meine 2 Cent

Sollte das Authentifizierungs-/Login-Beispiel nicht das einfachste sein, das m├Âglich ist? dh Speicher und kein JWT oder seltsame Token-Dinge. Wenn Sie an jemanden denken, der sich "angemeldet" hat, bedeutet dies normalerweise, dass er ein Cookie/eine aktive Sitzung hat.

Ich habe ein Login HOC, das Client- und Serverseite arbeitet. Es verwendet ein JWT und ein Backend (kann Knoten, Django, was auch immer sein).

Schau es dir an und jedes Feedback ist sehr willkommen

https://github.com/hugotox/AppStarter

Relevanter Code hier https://github.com/hugotox/AppStarter/blob/master/src/components/auth/login-required.js

@hugotox Ich mag die Idee, Redux Store zum Speichern von Authentifizierungsdaten zu verwenden, aber wenn Sie store.dispatch von getInitialProps mehrmals aufrufen, seien Sie bereit f├╝r unerw├╝nschte Nebeneffekte, wenn die dekorierte Komponente gerendert wird, auch wenn der Authentifizierungsprozess ist noch nicht fertig. Nehmen wir ein Anwendungsbeispiel aus Ihrem Code:

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

In getInitialProps rufen Sie verifyToken vor verificationOk , also wird MyPage.mapStateToProps 2 Mal aufgerufen (wenn es auf store.auth.user wartet) und zum ersten Mal store.auth.user wird auch f├╝r eine Seite null sein, die einen angemeldeten Benutzer erfordert.

Gestern habe ich auch die erste WIP-Version des eigenen Next.js-basierten Starterkits ver├Âffentlicht, aber ich habe mit Docker, Flow und fast-redux angefangen: https://github.com/dogada/microchain

Ich verwende dort dedizierte Docker-Images f├╝r API-Server und Webapp, die auf verschiedenen Dom├Ąnen ausgef├╝hrt werden k├Ânnen, daher suche ich immer noch nach einer funktionierenden L├Âsung, die es erm├Âglicht, echte Benutzer anzumelden, aber auch OAuth-Bearer-Token zum Beispiel f├╝r mobile Clients auszugeben.

@spencersmb ausgezeichneter

@james-ff Danke, dass du das gepostet hast, auch wenn es sich anf├╝hlt, als w├╝rde man ins Leere schreien.

Es wurde in diesem Thread ein paar Mal gesagt, aber alle ignorieren anscheinend immer noch, dass sie Session-Tokens nicht in JWT mit localStorage oder in JavaScript-zug├Ąnglichen Cookies speichern sollten, und scheint die Absicht zu haben, Sessions und Authentifizierung auf weniger sichere Weise neu zu erfinden (und das erfordert clientseitiges JS). ´ŞĆ

Der Autor dieses Beitrags hat 2016 gro├čartig aufgeschrieben, was daran falsch ist, aber leider scheinen sich die Dinge nicht verbessert zu haben:

Leider scheint es, dass ich die Obergrenze der Artikell├Ąnge gefunden habe, bevor die Leute aufh├Âren zu lesen - viele der Kommentatoren von Reddit und Hacker News schlugen immer wieder die gleichen "L├Âsungen" vor und ignorierten v├Âllig, dass sie bereits angesprochen und f├╝r unpraktisch befunden wurden im Artikel selbst.

Sowohl der Originalartikel als auch das Nachfolgediagramm sind jedoch ziemlich gro├čartig.

@iaincollins JWTs und sitzungslose Apps/Authentifizierung haben ihre Vorteile und viele Leute/Unternehmen (einschlie├člich Google) m├Âchten sie immer noch verwenden. Nachdem ich den Fall gegen JWTs gelesen

Ich habe dies nur beil├Ąufig im Auge behalten, aber meine Erfahrung mit der universellen JS-Authentifizierung ist, ein JWT in einem HttpOnly Cookie zu speichern. Es gibt wirklich keinen Grund, localStorage wenn Sie die M├Âglichkeit haben, die Serverseite der App zu verwenden, um das Cookie zu speichern. Wenn Sie Zugriff auf das JWT f├╝r ursprungs├╝bergreifende API-Aufrufe im Browser ben├Âtigen, k├Ânnen Sie das JWT in einem Szenario vom Typ __INITIAL_STATE__ (beachten Sie XSS-Schwachstellen, aber zumindest "speichern" Sie nicht es clientseitig). F├╝r den gleichen Ursprungszugriff wird das Cookie hin und her ├╝bergeben (vorausgesetzt, Sie verwenden withCredentials f├╝r Axios oder credentials: 'include' f├╝r den Abruf), sodass das JWT ├╝berhaupt nicht in JS abgelegt werden muss . Sie k├Ânnten einen Proxy auf der Serverseite der App verwenden, um das JWT aus dem HttpOnly Cookie zu holen, _dann_ auch Ihre ursprungs├╝bergreifenden API-Aufrufe ausf├╝hren. Auch in diesem Szenario negieren Sie den Preflight-Aufruf. Jedem das seine, aber ich pers├Ânlich glaube nicht, dass localStorage f├╝r universelle Apps ben├Âtigt wird.

@bjunc Ja, von allen Optionen, wo ein JWT gespeichert werden soll (localStorage vs. HttpOnly-Cookie vs. Redux oder was auch immer), k├Ânnte ich mich irren, aber ich denke, die Antwort sollte grunds├Ątzlich immer ein HttpOnly-Cookie sein. Dies scheint in zahlreichen Blogs und Foren unz├Ąhlige Male gesagt worden zu sein. (Ich bin mir bei Aktualisierungstoken nicht sicher - vielleicht sollten sie auch in einem HttpOnly-Cookie gespeichert werden?) Ich denke, wo JWTs gespeichert werden, sollte eine gel├Âste Angelegenheit sein, die sich von den ├╝brigen Vor- und Nachteilen von JWTs unterscheidet.

Ich habe versucht, mehr oder weniger genau das zu tun, was Sie in einem meiner Projekte gesagt haben, bevor ich anfing, nextjs-starter und next-auth zu ├╝bernehmen. Es ist schon eine Weile her, aber wenn ich mich richtig erinnere, denke ich, dass das Problem, auf das ich gesto├čen bin, darin bestand, dass mein Express-API-Server, gegen den ich mich authentifizierte (der Express-Session verwendete), die Sitzung nicht korrekt initialisierte/abholte. Ich w├╝rde ein seltsames Verhalten bekommen, wenn Sitzungen mehrmals initialisiert wurden. Ich beabsichtige, mehr oder weniger das zu tun, was Sie beschrieben haben, wenn ich das beheben kann. Ich werde auch weiterhin mit nextjs-starter und next-auth arbeiten, da Sessions viele der anderen Bedenken, die JWTs aufwerfen, beseitigen, z. B. wie Token ung├╝ltig gemacht werden k├Ânnen.

Auch hier w├Ąre ein offizielles Beispiel (oder Beispiele) hilfreich. Stichwort: offiziell, d.h. die Autoren von Next.js haben alle M├Âglichkeiten abgewogen und die besten Ideen und Praktiken darin einflie├čen lassen. Idealerweise mit modernen ES6/ES7/ES8-Features wie Promises und Async/Await.

@kelleg1 es h├Ârt sich so an, als ob Ihre Probleme mit den Besonderheiten der Cookie-Erstellung zusammenh├Ąngen. Sie k├Ânnen beispielsweise versehentlich mehrere Cookies mit demselben Namen erstellen, indem Sie unterschiedliche Einstellungen verwenden ( HttpOnly , Dom├Ąne, Pfad, Ablaufdatum usw.); was zu seltsamen Nebenwirkungen f├╝hren kann, wie Sie es beschreiben. Eine M├Âglichkeit, dies zu debuggen, besteht darin, die Entwicklungstools Application->Cookies zu verwenden. Wenn Sie eine Reihe von Cookies mit demselben Namen sehen, weist dies m├Âglicherweise in die richtige Richtung.

Wie auch immer, ich geh├Âre nicht zum Kernteam, daher kann ich mit einem "offiziellen" Beitrag nicht helfen (und tats├Ąchlich verwende ich Nuxt.js, nicht Next.js), aber die Prinzipien sind die gleichen. Ich habe mit ein paar verschiedenen Methoden experimentiert (Abw├Ągen der Vor- und Nachteile von JWT, Cookies, CSFR, Websocket CSWSH, localStorage usw.). Letztendlich kam ich zu dem Schluss, dass sich die universelle Natur von Next/Nuxt gut f├╝r die Verwendung von HttpOnly JWT-Cookies eignet. Vielleicht w├╝rden andere zu einem anderen Schluss kommen, aber ich pers├Ânlich bin nicht im Lager von "Oh Gott, benutze kein JWT, hast du nicht den Artikel gelesen, der sagt, dass JWT Krebs verursacht!?".

@iaincollins Entschuldigung, dass ich dies noch einmal zur├╝ckbringen muss, aber jedes einzelne Tutorial im Web verwendet localStorage, um das Token zu speichern, und Sie sagen, dass es unsicher ist. Wenn ja, wo sollen wir das Token aufbewahren?

KEKSE! :D
wir verwenden so etwas:

// 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({...});

Ein wenig klobig, aber ziemlich sicher, da Javascript auf Client-Seite nie ein Token sieht und Cookie nur httpOnly ist, sicher, signiert und automatisch von axios oder einem anderen...

Hallo zusammen, habe gerade ein Authentifizierungsbeispiel mit Cookies und Redux erstellt. Siehe hier https://github.com/zeit/next.js/pull/4011

Warten Sie, wo ist dieses Problem gelandet? Ich konnte im offiziellen Repo nie ein Express-Authentifizierungsbeispiel finden.

Ich sehe viel von Cookies und Sitzungen, aber wie funktioniert das f├╝r meine native mobile App, wenn sie die API erreichen muss?

Es kann getan werden, aber daf├╝r ist JWT da :p

Ich habe gerade den gesamten Thread ausf├╝hrlich gelesen und f├╝hle mich gezwungen, meine Ergebnisse zusammenzufassen.

Es scheint, dass es zwei praktikable Starterprojekte gibt, bei denen solide Authentifizierungsmodule ausgeklammert sind:

Ausgezeichnete Arbeit von @iaincollins und @nmaro !

Danke @curran :)

Ich habe alle Code├Ąnderungen, die ich zum Entfernen der ├╝berfl├╝ssigen Aspekte von nextjs-starter vorgenommen habe, in diesem Pull Request dokumentiert https://github.com/iaincollins/nextjs-starter/pull/86

Dies k├Ânnte einem soliden Barebone-Authentifizierungsbeispiel f├╝r das Next.js-Repository n├Ąher kommen.

Ich hatte vor kurzem die Anforderung, OAuth mit Office 365 zu implementieren, also dachte ich, ich w├╝rde ein sehr einfaches Beispiel teilen, das ich hier zusammengew├╝rfelt hier beschriebene Thread f├╝r gesch├╝tzte Routen. Auf jeden Fall dachte ich mir, ich w├╝rde es mitteilen, falls jemand ein kurzes Beispiel daf├╝r haben m├Âchte, wie dies (vielleicht) mit Microsoft gemacht wird.

F├╝r alle, die an einer einfachen JWT-tokenisierten Authentifizierung interessiert sind, die client- und serverseitig funktioniert, habe ich im Spectrum-Chat Hilfe geholt und dachte, ich w├╝rde sie mit Ihnen allen teilen. Jedes Feedback ist immer willkommen.

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

Hallo Leute!
Hier ist ein weiteres Beispiel f├╝r die Authentifizierung mit next.js, das ich vor ein paar Monaten erstellt habe, vielleicht findet es jemand n├╝tzlich:

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

Ooth 2.0 ist raus mit neuen und besseren Dokumenten

Ooth ist ein Benutzeridentit├Ątsverwaltungssystem , das f├╝r node.js (mit Blick auf next.js) entwickelt wurde.

Derzeit unterst├╝tzte Strategien:

  • Prim├Ąr: Benutzername/Passwort (inkl. E-Mail best├Ątigen, Pw vergessen etc.), Gast, Facebook, Google
  • Sekund├Ąr: Cookie-basierte Sitzungen, JWTs

Schauen Sie sich dieses Live-Beispiel an , das alles mit next.js ( Quellcode ) zusammenfasst.

Viele der Auth-Beispiele hier (und im Beispielordner) geben den Benutzer session/token/etc von getInitialProps . Soweit ich wei├č, bedeutet dies, dass die Benutzersitzungsinformationen beim Rendern der Seite serverseitig als Teil der HTML-Seitenantwort (als Teil von NEXT_DATA ) an den Browser gesendet werden.

Ich sehe bei diesem Muster zwei Sicherheitsprobleme, wenn getInitialProps serverseitig ausgef├╝hrt wird:
1) Die Benutzersitzung wird ├╝ber das Netzwerk vom Server zum Browser ├╝bertragen. Wenn solche Anfragen http:// und nicht https:// , wird das Token des Benutzers usw. im Klartext ├╝ber das Netzwerk verf├╝gbar gemacht.

2) Die Benutzersitzung wird als Teil der HTML-Seite vom Server an den Browser zur├╝ckgegeben (in einem NEXT_DATA Skript-Tag). Es erscheint riskant, das Token/usw. des Benutzers direkt auf der HTML-Seite zu platzieren, insbesondere wenn die Seite geparst und vom Browser gerendert wurde und andere Skripte von Drittanbietern jetzt m├Âglicherweise ausgef├╝hrt werden.

Sind das bereits angesprochene Themen? Gibt es Gegenma├čnahmen f├╝r diese Bedrohungen?

Deshalb verwende ich Cookies. Siehe mein Beispiel hier https://github.com/hugotox/nextjs-starter/blob/master/pages/_app.js

Schlie├člich! Hier finden Sie ein vollst├Ąndig dockerisiertes next.js-Authentifizierungsbeispiel mit den folgenden Containern:

  • next.js
  • Authentifizierungs-Microservice (ooth)
  • API (Graphql)
  • Sitzungsspeicher (redis)
  • kleiner Reverse-Proxy

Alles wird mit docker-compose zusammengezogen.

Kurze Anmerkung zu JWTs. JWTs haben den Vorteil, dass sie zustandslos, gut f├╝r Mobilger├Ąte und gut geeignet sind, wenn Sie Anmeldeinformationen von einer Dom├Ąne an die andere weitergeben m├╝ssen. Der Hauptnachteil ist, dass sie den Browser XSS aussetzen. F├╝r dieses Beispiel habe ich mich f├╝r eine reine Cookie-Session-basierte L├Âsung entschieden. Dank des Reverse-Proxys (alle Microservices laufen unter derselben Dom├Ąne) und des gemeinsamen Sitzungsspeichers habe ich es immer noch geschafft, die Dinge in Microservices aufzuteilen.

https://github.com/nmaro/staart/tree/master/examples/staart
Das Live-Beispiel ist wie gewohnt: https://staart.nmr.io

Ich denke, es ist ratsam, klarzustellen, dass Sie durch die Verwendung von JWT nicht von Natur aus XSS "ausgesetzt" werden. Wenn Ihre Site eine XSS-Sicherheitsl├╝cke aufweist (nicht aufgrund von JWT selbst), k├Ânnte ein JWT kompromittiert werden (zusammen mit allen anderen Skript-zug├Ąnglichen Informationen); wohingegen httpOnly Cookies nicht zug├Ąnglich sind. Vergessen Sie nicht, dass Sie ein JWT als Wert eines httpOnly Cookies verwenden k├Ânnen!

Nur Cookie-L├Âsungen k├Ânnen f├╝r die Kommunikation ├╝ber dieselbe Domain gut funktionieren, aber wenn Sie eine Headless-API haben (z. B. example.com die api.example.com aufruft), ist das keine wirkliche L├Âsung, es sei denn, Sie m├Âchten einen Proxy-Browser verwenden Anfragen von example.com an api.example.com indem Sie Ihre API-Aufrufe an example.com und sie mit dem an die Anfrage angeh├Ąngten Cookie weiterleiten (das mit seinen eigenen Vor- und Nachteilen verbunden ist). .

Ich pers├Ânlich halte die Nachteile von JWT f├╝r ├╝bertrieben und lassen sich durch eine Reihe von h├Ąufig implementierten Schutzma├čnahmen ziemlich leicht abmildern. Nicht zuletzt eine Token-Blacklist mit Verweis auf den jti Anspruch (zB Version4 UUID) f├╝r den Fall, dass der Token vor Ablauf kompromittiert wurde.

Hey @bjunc ja danke f├╝r die Klarstellung. Richtig, JWT setzt Sie nicht selbst XSS aus. Zu Ihren anderen Beobachtungen m├Âchte ich hinzuf├╝gen, dass sie alle ihre T├╝cken haben.

Denken Sie daran, dass Sie ein JWT als Wert eines httpOnly-Cookies verwenden k├Ânnen!

Ja, m├Âchte nur hinzuf├╝gen, dass dadurch der einzige Vorteil von JWT beseitigt wird, Anmeldeinformationen zwischen Dom├Ąnen zu ├╝bertragen.

eine Token-Blacklist

Dies und die andere g├Ąngige Praxis eines Aktualisierungstokens beseitigen den anderen Vorteil von JWT, wirklich zustandslos zu sein.

Das ist mein Verst├Ąndnis der Situation:

  • Wenn Sie eine standort├╝bergreifende Authentifizierung
  • Wenn Sie sich von einem Client aus authentifizieren m├╝ssen, der kein Browser ist und das XSS-Problem nicht hat (z. B. eine Desktop- oder mobile App), verwenden Sie JWT
  • Verwenden Sie andernfalls Cookie-basierte Sitzungen, da eine JWT-basierte L├Âsung entweder weniger sicher (XSS) oder nicht wirklich zustandslos (Blacklists) ist oder Sie einen Proxy verwenden m├╝ssen, um sowieso alles unter derselben Dom├Ąne zu halten.

Ich habe einen Medium-Artikel ├╝ber Next.js-Authentifizierung/Benutzerkonten geschrieben.
Es ist ein umfangreiches Tutorial und mein Braindump aus fast zwei Jahren Freizeitentwicklung und -denken (mein erster Kommentar zu dieser Ausgabe stammt vom Februar 2017).

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

Sie korrelieren JWT immer wieder damit, dass es weniger sicher ist. JWT macht Ihre Site nicht weniger sicher. Es ist an und f├╝r sich keine XSS-Sicherheitsl├╝cke. Wenn Sie einen XSS-Exploit haben, sind Sie trotzdem in gleichen Schwierigkeiten. Selbst mit einem httpOnly Cookie kann der Angreifer den Cookie-Wert m├Âglicherweise nicht lesen, aber das spielt keine Rolle, da er beliebigen Code ausf├╝hren kann ÔÇô wie XHR-Anfragen, die die Sitzungscookies automatisch passieren w├╝rden (im Wesentlichen als ein CSRF-Angriff). Wenn Ihre API dom├Ąnen├╝bergreifend ist und Sie Browser-zu-Server-Anforderungen stellen, befindet sich das JWT sowieso irgendwo im Code (sei es im Anfangszustand oder localStorage). Wenn Sie Axios verwenden, haben Sie m├Âglicherweise sogar globale Standardeinstellungen festgelegt, bei denen der Angreifer nur eine Axios-Anfrage stellen muss und sich nicht einmal um die Authentifizierung k├╝mmern muss.

Au├čerdem kann man nicht wirklich ├╝ber XSS sprechen, ohne auch ├╝ber CSRF zu sprechen; wo Auth-Cookies speziell ausgerichtet sind. Selbst mit einem Reverse-Proxy-Setup w├╝rde ein CSRF-Angriff dem Angreifer erm├Âglichen, authentifizierte Anfragen f├╝r Ihre API auszuf├╝hren.

├ťbrigens, nur weil Sie das JWT in einem Cookie ablegen (zum Beispiel wissen, ob der Benutzer angemeldet ist), bedeutet das nicht, dass Sie den Cookie-Wert (z. API-Serverzugriff beim Laden der Seite (der auch f├╝r das Reverse-Proxy-Szenario funktioniert). Sie sind auch nicht daran gehindert, das JWT im Anfangszustand f├╝r Browser-zu-API-Server-Anfragen zu ├╝bergeben. Sie schlie├čen sich nicht gegenseitig aus.

Abgesehen davon finde ich die Idee des "zustandslosen" JWT sowohl ├╝berbewertet als auch in der Anwendung f├╝r die meisten Anwendungsf├Ąlle eingeschr├Ąnkt. Zum Beispiel:

  • Ressourcenbasierte / dynamische Berechtigungen (zB nicht nur " can edit Post ", sondern eher " can edit Post:1634 ").
  • Was ist, wenn das Konto des Benutzers gesperrt / gel├Âscht wurde?
  • Sie haben ihr monatliches Abonnement nicht bezahlt; welche drosselt die funktion?
  • Das Token auf die schwarze Liste gesetzt (wie oben)?

Sie backen nicht all das in das JWT, was bedeutet, dass Sie in die Dom├Ąnenschicht (dh die Datenbank) eintauchen m├╝ssen, um dies herauszufinden. Sie haben die Ressource gerade geladen, k├Ânnen sie also genauso gut dort platzieren, wo der Rest der App darauf zugreifen kann, und jetzt haben Sie den Status. Ich finde es wirklich albern zu glauben, dass alles, was Sie ├╝ber das Thema wissen m├╝ssen, in das Token eingebrannt wird; w├Ąhrend es gleichzeitig meistens anonym und leichtgewichtig bleibt. Ohne zu viel abzuschweifen, gibt es ein Argument f├╝r "zustandslose" Anfragen in der Kommunikation zwischen Diensten, aber selbst das finde ich unpraktisch (zumindest was das Konzept betrifft, alles, was Sie ├╝ber das Thema wissen m├╝ssen, in das JWT zu ├╝bertragen). .

Inzwischen verf├╝gbare Ooth-Authentifizierungsstrategien (neu in Fettdruck):

  • Lokal (Benutzername/E-Mail/Passwort)
  • Facebook
  • Google
  • Gast
  • Patreon
  • Twitter
  • Authy (Twilio) - passwortlos per SMS

@jaredpalmer du hast geschrieben
Wie bei PHP ist die atomare Einheit von Next die Seite. Eine der coolsten Funktionen ist, dass jede Seite nur dann geladen wird, wenn sie angefordert wird. Bei nur clientseitiger Authentifizierung, aber beim Server-Rendering wird das js f├╝r diese gesch├╝tzte Seite tats├Ąchlich vom Browser heruntergeladen. Wenn Next in Zukunft Server-Workflows hinzuf├╝gt, k├Ânnen Sie hoffentlich das Rendern und die Umleitung auf dem Server blockieren, um dies vollst├Ąndig zu verhindern. Dies erfordert Cookies, Sitzungen und AFAIK-Sitzungsspeicher, aber das sind nur die Kosten f├╝r solche Hybrid-Apps.

Wir sind 2 Jahre sp├Ąter. Gibt es einen Server-Workflow, um das Laden von js f├╝r gesch├╝tzte Seiten zu verhindern?
@timneutkens vielleicht gesch├╝tzte Inhalte in eine andere Zone stellen?
Wie w├╝rde ich den Zugriff auf gesch├╝tzte Inhalte vollst├Ąndig verhindern?

@lishine Du hast eine ServerResponse im getInitialProps deiner Seite - du kannst ganz einfach jemanden umleiten, der nicht privilegiert ist.

Gibt es ein Beispiel f├╝r Authentifizierung mit Redux?

Gibt es ein Beispiel f├╝r Authentifizierung mit Redux?

Sie k├Ânnen dieses Beispiel ausprobieren, das Redux verwendet, und pr├╝fen, ob es f├╝r Sie funktioniert ...
Sie finden es irgendwo in diesem Thema, aber falls Sie es nicht finden k├Ânnen, hier ist es:
https://github.com/alan2207/nextjs-jwt-authentication

Ich denke, dies ist ein komplizierteres Problem, wenn die Ergebnisse des serverseitigen API-Aufrufs getInitialProps verwendet werden, da Virtual DOM alte Ergebnisse nach der LOGOUT-LOGIN-Aktion verwendet. Ich denke ├╝ber eine L├Âsung nach

_BEARBEITET_
und hier ist meine Antwort mit redux-observable

|Seite|Auth|TODO|
|---|---|---|
|Server|true|Anfangsdaten abrufen (mit Anforderungs-Cookie-Proxy).|
|Server|false|Anmeldeseite anzeigen und Daten nach der Anmeldung abrufen.|
|Client|true|Anfangsdaten abrufen.|
|Client|false|Anmeldeseite anzeigen und Daten nach der Anmeldung abrufen. (Dies geschieht nur, wenn die Sitzung beim Verschieben von Seite zu Seite abgelaufen ist)|

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

Scheint kompliziert zu sein, wenn etwas Einfaches ausreicht, etwa wie:

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} />;
    }
};

Dieses Beispiel wurde als Teil von Next.js 8 zusammengef├╝hrt
https://github.com/zeit/next.js/tree/canary/examples/with-cookie-auth

@timneutkens danke f├╝r den Link.

siehe https://github.com/zeit/next.js/blob/canary/examples/with-cookie-auth/www/utils/auth.js#L26 -L34 checken, nachdem auth() aufgerufen wurde?

Das Testen des Beispiels ohne Cookie f├╝hrt dazu, dass Profile.getInitialProps() aufgerufen wird, w├Ąhrend ich dachte, die Umleitung w├╝rde erfolgen, bevor ├╝berhaupt versucht wird, mehr "Anfangsprops" zu erhalten ...

Ich habe hier ein Beispiel gemacht, das serverseitiges Pre-Rendering + Authentifizierung mit apollo hat

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

Bitte beachten Sie, dass die OWASP-Sicherheitsrichtlinien davon abraten, JWT-Token im lokalen Speicher zu speichern, dh "Ein einzelnes Cross Site Scripting kann verwendet werden, um alle Daten in diesen Objekten zu stehlen, daher wird erneut empfohlen, keine sensiblen Informationen im lokalen Speicher zu speichern."

Hier ist Auth0: Wo Tokens gespeichert werden und Tom Abbott: Wo Sie Ihre JWTs speichern ÔÇô Cookies vs HTML5 Web Storage .

Hier ist ein Beispiel mit Nuxt.js + Express.js-Proxyserver + Django-Backend. Wo der Express-Server f├╝r die Proxy-Authentifizierungsanfrage an das eigentliche Backend verwendet wird und den CSRF-Schutz handhabt, wenn das JWT-Token in einem Cookie gespeichert wird (beschr├Ąnkt die L├Ąnge des Tokens / wie viele Informationen im JWT-Token gespeichert werden k├Ânnen): https:/ /github.com/danjac/nuxt-python-secure-example

@timneutkens Ich ben├Âtige einige Dokumente zum Senden von Token von Cookie ­čŹ¬ an benutzerdefinierte SSR-Redux-Middleware. Ich bekomme die Cookies in _app.js . Aber wie soll ich es an customApimiddleware ├╝bergeben. Wo habe ich Abrufanfragen geschrieben. Vielen Dank

Ich habe einen Medium-Artikel ├╝ber Next.js-Authentifizierung/Benutzerkonten geschrieben.
Es ist ein umfangreiches Tutorial und mein Braindump aus fast zwei Jahren Freizeitentwicklung und -denken (mein erster Kommentar zu dieser Ausgabe stammt vom Februar 2017).

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

Ich denke, dies ist eines der besten Tutorials zum Umgang mit der Authentifizierung in einer nextj.js-App. Ich habe Dinge wie das Speichern von Token in localStorage (XSS), das Speichern von Token in Cookies (ohne Umgang mit CSRF) und sogar das Speichern von Token in Cookies vom Browser (sowohl XSS als auch CSRF anf├Ąllig) gesehen.

Ich mag Ihre L├Âsung mit dem Reverse-Proxy und dem Teilen der Sitzungsinformationen zwischen verschiedenen Diensten sehr. Ich m├Âchte wirklich keinen benutzerdefinierten Server f├╝r die next.js-App erstellen, aber ich denke, dies ist der einfachste Weg, um sowohl Sitzungen zu verarbeiten als auch csrf zu verhindern (und m├Âglicherweise den Reverse-Proxy hinzuzuf├╝gen). Am Ende kann ich sogar ein Monolith-Projekt erstellen (sowohl zum Rendern der App als auch zum Behandeln von DB-Operationen usw.).

Ich habe gesehen, dass einige Leute (einschlie├člich ZEIT) die APIs zustandslos halten und die next.js-App die Sitzung verarbeiten lassen. Es ├╝bergibt die Token an APIs. Aber mit Sitzungen zu gehen macht die Dinge nur ein bisschen enger und weniger kompliziert.

Es w├Ąre wirklich besser, ein vollst├Ąndiges Authentifizierungsbeispiel f├╝r next.js zu haben. Mit Dingen wie der Authentifizierung f├╝r externe APIs, der Beibehaltung der Sitzung in der next.js-App, der gemeinsamen Nutzung von Sitzungen zwischen Diensten oder der ├ťbergabe von Token an sie und m├Âglicherweise sogar der Aktualisierung der Token, wenn sie abgelaufen sind. (Viele Leute schreiben viel ├╝ber JWTs und verwenden sie nur in ihren Tutorials, aber sie lassen sie meistens nicht einmal ablaufen oder aktualisieren sie nicht einmal.)

Wie auch immer, Sie haben eines der umfassendsten Tutorials zu diesem Thema geschrieben. So danke!

Ich hoffe wirklich, dass es viel vollst├Ąndigere und klarere Beispiele und Dokumentationen geben wird.

Es w├Ąre wirklich besser, ein vollst├Ąndiges Authentifizierungsbeispiel f├╝r next.js zu haben. Mit Dingen wie der Authentifizierung f├╝r externe APIs, der Beibehaltung der Sitzung in der next.js-App, der gemeinsamen Nutzung von Sitzungen zwischen Diensten oder der ├ťbergabe von Token an sie und m├Âglicherweise sogar der Aktualisierung der Token, wenn sie abgelaufen sind. (Viele Leute schreiben viel ├╝ber JWTs und verwenden sie nur in ihren Tutorials, aber sie lassen sie meistens nicht einmal ablaufen oder aktualisieren sie nicht einmal.)

Auch ich bin ratlos, welchen Ansatz ich w├Ąhlen soll.
vielen Dank f├╝r den Link zum Artikel.
Auf welche der Implementierungen haben Sie sich derzeit festgelegt?
Haben Sie ein umfassendes Autorisierungsbeispiel f├╝r next v9.3+ gefunden?

Es lohnt sich, den neuen Cookie-basierten Ansatz von Auth0 auszuprobieren
(Nat├╝rlich gilt dies f├╝r einen bestimmten Identit├Ątsanbieter, aber der Ansatz k├Ânnte n├╝tzlich sein.)
https://github.com/auth0/nextjs-auth0

  • Wirklich cool, dass Sie API-Anfragen ├╝ber die API-Routen von nextjs "proxy" k├Ânnen (sogar ├╝ber eine dynamische Route)
  • Dann m├╝ssen Sie der Clientseite nie Zugriffstoken usw. offenlegen (da nextjs-API-Routen nur die Serverseite ausf├╝hren), kann die Serverseite Zugriffstoken usw. ├╝ber die auth0-Bibliothek und das Cookie mit einem Geheimnis erhalten
  • Ihr clientseitiger Code w├╝rde Ihre nextjs-API-Routen aufrufen, und die API-Routen w├╝rden dann die echte API-Anfrage ausf├╝hren

Denken Sie daran, dass dieser Ansatz in der ReadMe-Datei "experimentell" ist

Es lohnt sich, den neuen Cookie-basierten Ansatz von Auth0 auszuprobieren
(Nat├╝rlich gilt dies f├╝r einen bestimmten Identit├Ątsanbieter, aber der Ansatz k├Ânnte n├╝tzlich sein.)
https://github.com/auth0/nextjs-auth0

  • Wirklich cool, dass Sie API-Anfragen ├╝ber die API-Routen von nextjs "proxy" k├Ânnen (sogar ├╝ber eine dynamische Route)
  • Dann m├╝ssen Sie der Clientseite nie Zugriffstoken usw. offenlegen (da nextjs-API-Routen nur die Serverseite ausf├╝hren), kann die Serverseite Zugriffstoken usw. ├╝ber die auth0-Bibliothek und das Cookie mit einem Geheimnis erhalten
  • Ihr clientseitiger Code w├╝rde Ihre nextjs-API-Routen aufrufen, und die API-Routen w├╝rden dann die echte API-Anfrage ausf├╝hren

Denken Sie daran, dass dieser Ansatz in der ReadMe-Datei "experimentell" ist

Dieser Artikel ist sehr hilfreich und deckt viele verschiedene Architekturen ab.
https://auth0.com/blog/ultimate-guide-nextjs-authentication-auth0/

Die Verwendung von API-Routen als Proxy, An- und Abmeldung ├╝ber API-Routen, das Abrufen des Tokens von der API und das Festlegen als HttpOnly-Cookie ist meiner Meinung nach ein solider Ansatz.
Ein Problem k├Ânnte CSRF sein, aber Sie k├Ânnen leicht eine L├Âsung mit dem csrf npm-Paket erstellen (nicht csurf , aber das k├Ânnte auch funktionieren).

@onderonur , danke f├╝r den auth0-Artikel.
das hei├čt, gibt es derzeit mit next.js ein zuverl├Ąssiges oder zumindest minimales Beispiel f├╝r die Implementierung auf reinem jwt?
Ich m├Âchte keine erweiterte Ebene mit Cookies erstellen und sie einrichten. In der csr-Anwendung haben wir das Token einfach in localstorage gespeichert und zusammen mit der Anfrage gesendet.

@onderonur , danke f├╝r den auth0-Artikel.
das hei├čt, gibt es derzeit mit next.js ein zuverl├Ąssiges oder zumindest minimales Beispiel f├╝r die Implementierung auf reinem jwt?
Ich m├Âchte keine erweiterte Ebene mit Cookies erstellen und sie einrichten. In der csr-Anwendung haben wir das Token einfach in localstorage gespeichert und zusammen mit der Anfrage gesendet.

Ich habe diese Methode f├╝r eines meiner Repos verwendet, aber sie ist noch im Entwurf, also teste sie selbst :)
https://github.com/onderonur/post-gallery
Eigentlich ist die "Cookie-Schicht" keine fortgeschrittene Sache. Rufen Sie einfach den Anmeldeendpunkt Ihrer API ├╝ber die API-Route /api/login , und wenn die Anfrage erfolgreich ist, legen Sie das Token in einem httpOnly Cookie fest.
Sie k├Ânnen mein Repository f├╝r die exakt gleiche Implementierung ├╝berpr├╝fen.

Eine andere Option ist (wenn Sie fast den gleichen Ablauf haben m├Âchten wie das Setzen des Tokens im lokalen Speicher), k├Ânnen Sie das js-cookie npm-Paket verwenden, Ihren Anmeldeendpunkt mit einer clientseitigen Anfrage aufrufen und beenden, wenn es zur├╝ckkehrt ein Token, setzen Sie es in ein Cookie. Und wenn Sie eine Anfrage stellen (├╝ber einen Axios-Interceptor usw.), lesen Sie den Cookie-Wert und ├╝bergeben Sie ihn als Anfrage-Header an Ihre API. Ich habe viele (und sogar einige beliebte) Anwendungen gesehen, die diesen Ansatz verwenden. Aber das ist ein bisschen unsicher. Weil Sie im Browser keine httpOnly Cookies setzen k├Ânnen. JavaScript kann also Ihr Token-Cookie lesen. Daher wird es eine XSS-Sicherheitsl├╝cke geben.

Sch├Ątzen Sie, dass dies ein alter Thread (und im Allgemeinen ein lang andauerndes Thema) ist, aber f├╝r diejenigen, die nach zus├Ątzlichen Referenzen oder Beispielen suchen, haben wir k├╝rzlich die Arbeit an NextAuth.js v2 aufgenommen. Ich erw├Ąhne es nicht einmal als Plug-In ÔÇô es ist ein Open-Source-Projekt und eine Menge Leute haben dabei geholfen ÔÇô aber es ist super einfach zu bedienen und der Code und der Ansatz k├Ânnten als Referenz f├╝r die Leute n├╝tzlich sein.

F├╝r einige Hintergr├╝nde, wie NextAuth v1, verwendet es Cookies, die signiert sind, mit einem Pr├Ąfix versehen sind und nur HTTP verwenden, um die ├╝blichen Sicherheitsfallen bei der Verwendung von clientseitigen Token zu vermeiden.

NextAuth.js v2 unterst├╝tzt die Anmeldung bei Apple, Google, Facebook, Twitter, GitHub, Auth0, Okta, Slack, Discord und anderen OAuth-Anbietern (es unterst├╝tzt sowohl 1.x als auch 2.x). Sie k├Ânnen es mit MySQL, MariaDB, Postgres, MongoDB verwenden - oder ohne Datenbank (nur OAuth und JSON Web Tokens f├╝r eine 100% serverlose L├Âsung).

Die Verwendung ist sehr einfach, es gibt eine universelle statische Methode namens session() und einen React Hook namens useSession() Sie in Komponenten clientseitig verwenden k├Ânnen:

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>}
  </>
}

Es wurde f├╝r Next.js 9.x und Serverless entwickelt und hat keine Abh├Ąngigkeiten wie Express oder PassportJS. Es enth├Ąlt einen Authentifizierungsanbieter, den Sie in _app.js , um allen Seiten automatisch den Authentifizierungsstatus hinzuzuf├╝gen. Es funktioniert sowohl f├╝r das client- als auch f├╝r das serverseitige Rendering.

Weitere Informationen finden Sie unter next-auth.js.org oder in [email protected] auf NPM

Es ist noch in Arbeit - wir polieren noch die Dokumentation und das Event-Modell - mit einem angestrebten Release-Datum von ~Anfang~ Mitte Juni.

Sch├Ątzen Sie, dass dies ein alter Thread (und im Allgemeinen ein lang andauerndes Thema) ist, aber f├╝r diejenigen, die nach zus├Ątzlichen Referenzen oder Beispielen suchen, haben wir k├╝rzlich die Arbeit an NextAuth.js v2 aufgenommen. Ich erw├Ąhne es nicht einmal als Plug-In ÔÇô es ist ein Open-Source-Projekt und eine Menge Leute haben dabei geholfen ÔÇô aber es ist super einfach zu bedienen und der Code und der Ansatz k├Ânnten als Referenz f├╝r die Leute n├╝tzlich sein.

F├╝r einige Hintergr├╝nde, wie NextAuth v1, verwendet es Cookies, die signiert sind, mit einem Pr├Ąfix versehen sind und nur HTTP verwenden, um die ├╝blichen Sicherheitsfallen bei der Verwendung von clientseitigen Token zu vermeiden.

NextAuth.js v2 unterst├╝tzt die Anmeldung bei Apple, Google, Facebook, Twitter, GitHub, Auth0, Okta, Slack, Discord und anderen OAuth-Anbietern (es unterst├╝tzt sowohl 1.x als auch 2.x). Sie k├Ânnen es mit MySQL, MariaDB, Postgres, MongoDB verwenden - oder ohne Datenbank (nur OAuth und JSON Web Tokens f├╝r eine 100% serverlose L├Âsung).

Die Verwendung ist sehr einfach, es gibt eine universelle statische Methode namens session() und einen React Hook namens useSession() Sie in Komponenten clientseitig verwenden k├Ânnen:

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>}
  </>
}

Es wurde f├╝r Next.js 9.x und Serverless entwickelt und hat keine Abh├Ąngigkeiten wie Express oder PassportJS. Es enth├Ąlt einen Authentifizierungsanbieter, den Sie in _app.js , um allen Seiten automatisch den Authentifizierungsstatus hinzuzuf├╝gen. Es funktioniert sowohl f├╝r das client- als auch f├╝r das serverseitige Rendering.

Weitere Informationen finden Sie unter next-auth.js.org oder in [email protected] auf NPM

Es ist noch in Arbeit - wir polieren noch die Dokumentation und das Event-Modell - mit einem angestrebten Release-Datum von ~Anfang~ Mitte Juni.

Tolle Arbeit das!
Kann dies auf der Client-Seite allein verwendet werden? Ich habe zum Beispiel eine Rails-API-App - und verwende next JS f├╝r die Clientseite.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen