Next.js: Tambahkan contoh login / otentikasi

Dibuat pada 29 Okt 2016  ·  208Komentar  ·  Sumber: vercel/next.js

Dengan:

  • pembantu otentikasi yang dapat digunakan kembali di seluruh halaman
  • sinkronisasi sesi antar tab
  • backend email sederhana tanpa kata sandi yang dihosting di now.sh

Saya pikir ini akan sangat membantu banyak pendatang baru.

p0

Komentar yang paling membantu

Jadi saya memiliki auth yang bekerja dengan baik. Seperti disebutkan di tempat lain, itu hanya sisi klien, yang pada akhirnya hanya setengah dari pertempuran.

"Cukup aman"

Seperti php, unit atom Next adalah halaman. Salah satu fitur paling keren adalah ia malas memuat setiap halaman hanya jika diminta. Dengan hanya autentikasi sisi klien tetapi dengan rendering server, js untuk halaman yang dilindungi itu sebenarnya diunduh oleh browser. Di masa mendatang saat Next menambahkan alur kerja server, Anda diharapkan dapat memblokir render dan redirect di server untuk mencegah hal ini sepenuhnya. Ini akan membutuhkan cookie, sesi, dan penyimpanan sesi AFAIK, tetapi itu hanya biaya untuk melakukan aplikasi hibrida seperti ini.

Contoh Otentikasi

Asumsikan Anda memiliki JWT-secured API dengan dua titik akhir yang menarik: /token dan /me . /token menerima kredensial email/kata sandi dan mengembalikan JWT yang ditandatangani ( id_token ) sementara /me mengembalikan informasi profil yang terkait dengan pengguna yang diautentikasi JWT. Saya mengadaptasi AuthService.js berikut dari kunci Auth0 (menghapus emitor acara, meskipun itu bukan ide terburuk). Ini mengekstrak hampir semua penanganan token JWT sehingga dapat digunakan pada halaman login dan juga di Komponen Tingkat Tinggi (lebih lanjut tentang itu nanti).

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

Selanjutnya adalah HOC untuk membuat halaman perlindungan menjadi lebih sederhana. Untuk mencegah kilatan informasi sensitif yang tidak diinginkan, halaman akan merender Loading... pada server-render pertama saat reaksi mem-boot/membaca token dari localStorage. Ini berarti bahwa halaman yang dilindungi tidak akan SEO, yang mungkin baik-baik saja seperti sekarang, tetapi jelas tidak optimal.

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

Halaman login tidak dapat menggunakan HOC seperti sekarang, karena Login harus bersifat publik. Jadi itu hanya membuat instance dari AuthService secara langsung. Anda akan melakukan hal serupa untuk halaman Pendaftaran juga.

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

Terinspirasi oleh reaksi-dengan-gaya Airbnb, saya juga mulai mengerjakan lib next-with-auth yang akan menjadi fungsi mengembalikan HOC untuk digunakan pada halaman. Saya juga bermain dengan menggabungkan AuthService dan HOC ini. Salah satu solusinya mungkin membuat HOC ini menerima fungsi tingkat izin sebagai argumen selain komponen, seperti redux connect. Terlepas dari itu, dalam pikiran saya, Anda akan menggunakan next-with-auth seperti ini:

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

Melakukan semua ini dengan Redux tampaknya tidak perlu rumit, tetapi pada dasarnya Anda dapat mengikuti contoh wiki, tetapi pindahkan AuthService ke dalam Tindakan (masuk dan keluar) dan memiliki Peredam Pengguna. Anda hanya dapat memanggil tindakan ini di klien, karena tidak ada Penyimpanan lokal di server, jadi Anda perlu memeriksanya di Tindakan Anda. Pada akhirnya, toko redux diletakkan di window . Jadi, Anda bisa men-cache pengguna dengan baik di window sendiri alih-alih menggunakan konteks. Jika Anda tidak ingin redux, Anda juga dapat mencoba react-broadcast .

Terakhir, dengan asumsi next/server dikirimkan sesuai dengan #25. next-with-auth dapat mengabstraksi penyimpanan lokal yang rumit vs. cookie jauh dari pengembang dengan middleware + HOC. Itu juga bisa menangani penyegaran token juga.

Semua 208 komentar

Saran: Gunakan Redux dan JWT untuk menyelesaikan contoh

Saya sedang mengerjakan contoh untuk ini. Saat ini mengalami masalah mendapatkan componentWillReceiveProps untuk diaktifkan pada komponen tingkat tinggi saya (di mana saya berencana untuk memeriksa apakah pengguna diautentikasi dan mengarahkan ulang ke halaman login jika tidak)

Jadi saya memiliki auth yang bekerja dengan baik. Seperti disebutkan di tempat lain, itu hanya sisi klien, yang pada akhirnya hanya setengah dari pertempuran.

"Cukup aman"

Seperti php, unit atom Next adalah halaman. Salah satu fitur paling keren adalah ia malas memuat setiap halaman hanya jika diminta. Dengan hanya autentikasi sisi klien tetapi dengan rendering server, js untuk halaman yang dilindungi itu sebenarnya diunduh oleh browser. Di masa mendatang saat Next menambahkan alur kerja server, Anda diharapkan dapat memblokir render dan redirect di server untuk mencegah hal ini sepenuhnya. Ini akan membutuhkan cookie, sesi, dan penyimpanan sesi AFAIK, tetapi itu hanya biaya untuk melakukan aplikasi hibrida seperti ini.

Contoh Otentikasi

Asumsikan Anda memiliki JWT-secured API dengan dua titik akhir yang menarik: /token dan /me . /token menerima kredensial email/kata sandi dan mengembalikan JWT yang ditandatangani ( id_token ) sementara /me mengembalikan informasi profil yang terkait dengan pengguna yang diautentikasi JWT. Saya mengadaptasi AuthService.js berikut dari kunci Auth0 (menghapus emitor acara, meskipun itu bukan ide terburuk). Ini mengekstrak hampir semua penanganan token JWT sehingga dapat digunakan pada halaman login dan juga di Komponen Tingkat Tinggi (lebih lanjut tentang itu nanti).

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

Selanjutnya adalah HOC untuk membuat halaman perlindungan menjadi lebih sederhana. Untuk mencegah kilatan informasi sensitif yang tidak diinginkan, halaman akan merender Loading... pada server-render pertama saat reaksi mem-boot/membaca token dari localStorage. Ini berarti bahwa halaman yang dilindungi tidak akan SEO, yang mungkin baik-baik saja seperti sekarang, tetapi jelas tidak optimal.

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

Halaman login tidak dapat menggunakan HOC seperti sekarang, karena Login harus bersifat publik. Jadi itu hanya membuat instance dari AuthService secara langsung. Anda akan melakukan hal serupa untuk halaman Pendaftaran juga.

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

Terinspirasi oleh reaksi-dengan-gaya Airbnb, saya juga mulai mengerjakan lib next-with-auth yang akan menjadi fungsi mengembalikan HOC untuk digunakan pada halaman. Saya juga bermain dengan menggabungkan AuthService dan HOC ini. Salah satu solusinya mungkin membuat HOC ini menerima fungsi tingkat izin sebagai argumen selain komponen, seperti redux connect. Terlepas dari itu, dalam pikiran saya, Anda akan menggunakan next-with-auth seperti ini:

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

Melakukan semua ini dengan Redux tampaknya tidak perlu rumit, tetapi pada dasarnya Anda dapat mengikuti contoh wiki, tetapi pindahkan AuthService ke dalam Tindakan (masuk dan keluar) dan memiliki Peredam Pengguna. Anda hanya dapat memanggil tindakan ini di klien, karena tidak ada Penyimpanan lokal di server, jadi Anda perlu memeriksanya di Tindakan Anda. Pada akhirnya, toko redux diletakkan di window . Jadi, Anda bisa men-cache pengguna dengan baik di window sendiri alih-alih menggunakan konteks. Jika Anda tidak ingin redux, Anda juga dapat mencoba react-broadcast .

Terakhir, dengan asumsi next/server dikirimkan sesuai dengan #25. next-with-auth dapat mengabstraksi penyimpanan lokal yang rumit vs. cookie jauh dari pengembang dengan middleware + HOC. Itu juga bisa menangani penyegaran token juga.

Bersemangat untuk mencoba ini! Terima kasih atas implementasi barebone :)

@jaredpalmer Saya sedang mengerjakan sesuatu yang serupa. Bagaimana cara kerja AuthService saat komponen dirender di sisi server? Server akan membutuhkan akses ke JWT tetapi tidak dapat membacanya dari penyimpanan lokal.

@amccloud Tidak. Itulah masalahnya. HOC merender <div>Loading..</div> pada rute yang dilindungi dan harus membaca token dan memutuskan apakah akan mengarahkan ulang di componentDidMount . Agar berfungsi seperti yang Anda inginkan dan merender sisi server, Berikutnya membutuhkan #25, atau setidaknya kemampuan untuk mengatur cookie dengan nilai JWT AFAIK.

Saya menggunakan cookie-js untuk mengatur cookie, tetapi ini sedikit meretas..
masalahnya adalah: jika Anda tidak mengirim cookie, Anda kehilangan semua manfaat nextjs dan rendering sisi server dalam rute yang diautentikasi

@jaredpalmer ini bagus! Terima kasih atas usahanya. Saya akan mencoba menyelesaikan penerapan contoh Anda (atau membantu Anda melakukannya jika Anda mau) di hari-hari berikutnya

Yo! Saya menerbitkan contoh dengan nextjs dan auth0 di sini: https://github.com/luisrudge/next.js-auth0
Ini memiliki konsep tata letak utama dan juga "halaman aman" yang dimuat hanya ketika pengguna diautentikasi.
Beri tahu saya pendapat Anda

@luisrudge luar biasa. Saya mengkloning dan melakukan beberapa perubahan tetapi tampak hebat

Dingin! Menurutmu apa yang hilang? Perubahan apa yang Anda pikirkan?

Pada Minggu, 6 November 2016 pukul 13:12 -0200, "Dan Zajdband" < [email protected] [email protected] > menulis:

@luisr udgehttps://github.com/luisrudge luar biasa. Saya mengkloning dan melakukan beberapa perubahan tetapi tampak hebat

Anda menerima ini karena Anda disebutkan.
Balas email ini secara langsung, lihat di Gi tHubhttps://github.com/zeit/next.js/issues/153#issuecomment -258687108, atau bisukan pembacaannyahttps://github.com/notifications/unsubscribe-auth/ AA5cE8NIsvQ_ITjc1gArTFgNXzEda4TSks5q7e5NgaJpZM4KkJmi.

1) Menggunakan standard untuk linting (jadi konsisten dengan semua yang kita bangun selanjutnya)
2) Menambahkan dukungan multi-tab yang diminta oleh @rauchg
3) Bagian css dapat disederhanakan

Saya akan mengirimkan Anda PR :)

Apakah yang Anda maksud: support multi tab

Pada hari Minggu, 6 November 2016 pukul 13.16 -0200, "Dan Zajdband" < [email protected] [email protected] > menulis:

1) Menggunakan standar untuk linting (sehingga konsisten dengan semua yang kami bangun selanjutnya)
2) Menambahkan dukungan multi-tab yang diminta oleh @rauchghttps ://github.com/rauchg
3) Bagian css dapat disederhanakan

Saya akan mengirimkan Anda PR :)

Anda menerima ini karena Anda disebutkan.
Balas email ini secara langsung, lihat di Gi tHubhttps://github.com/zeit/next.js/issues/153#issuecomment -258687373, atau bisukan pembacaannyahttps://github.com/notifications/unsubscribe-auth/ AA5cE1A6jq4KZc9_ynukTCI4mU-rdsNaks5q7e81gaJpZM4KkJmi.

Anda memiliki 2 tab terbuka, logout pada 1, secara otomatis logout pada tab lainnya

Ahh. Itu sangat keren!

Pada Minggu, 6 November 2016 pukul 13.21 -0200, "Dan Zajdband" < [email protected] [email protected] > menulis:

Anda memiliki 2 tab terbuka, logout pada 1, secara otomatis logout pada yang lain

Anda menerima ini karena Anda disebutkan.
Balas email ini secara langsung, lihat di Gi tHubhttps://github.com/zeit/next.js/issues/153#issuecomment -258687707, atau bisukan pembacaannyahttps://github.com/notifications/unsubscribe-auth/ AA5cE9e2DA4_GgNQIVTMp0hx74G-6RmUks5q7fBfgaJpZM4KkJmi.

Hai @luisrudge Saya mengirimi Anda PR dengan perubahannya https://github.com/luisrudge/next.js-auth0/pull/2

terima kasih banyak untuk melakukan ini <3

btw ini hasilnya :

2016-11-06 11 14 31

@impronunciable @luisrudge Implementasi yang fantastis! Jika Anda ingin menggunakannya tanpa Auth0, sepertinya Anda hanya perlu mengubah file di direktori ./utils, bahkan mungkin hanya lock.js . Saya akan mencoba ini segera. Btw multi-tab terlihat luar biasa

@ugiacoman Saya sudah mulai mengimplementasikan server kecil dengan passwordless.net, beri tahu saya jika Anda ingin mendapatkan kode saya sebagai titik awal

@impronunciable Itu akan luar biasa! Saya sebenarnya akan melakukan sesuatu yang mirip dengan Digit Fabric Twitter.

@impronuncible saya sarankan untuk tidak menggunakan password less.net , sebagai gantinya Anda bisa menggunakan paspor-lokal, dan cukup kirimkan tautan kepada pengguna dengan email dan token mereka dalam string kueri.

Terima kasih @impronunciable ❤️

@ugiacoman ya, cukup mudah untuk menghapus ketergantungan auth0. Saya menggunakannya karena saya tidak ingin memiliki api terpisah untuk menangani auth

@jaredpalmer sejauh yang saya tahu, memiliki #25 akan bagus tetapi tidak memblokir? Maksud saya, kita memiliki akses ke sisi server req di getInitialProps jadi tidak ada yang mencegah penerapan cookie-parser ke dalamnya? Otentikasi sisi server dan manajemen sesi adalah hal baru bagi saya

BTW mengingat localStorage tidak dapat digunakan di sisi server, apakah cookie satu-satunya cara untuk memiliki sesi sisi server? Saya memiliki ingatan yang samar-samar itu mungkin bukan yang paling aman? Tapi apakah ada pilihan lain?

@sedubois

Pendekatan cookie bisa sangat aman jika dilakukan dengan benar. Melakukan hal berikut ini cukup sepele:

  • gunakan bendera httpOnly (mencegah akses JavaScript ke cookie)
  • gunakan tanda aman (hanya setel cookie untuk permintaan https)
  • Cookie yang ditandatangani (verifikasi sumber cookie)

Ada juga keuntungan latensi yang sangat signifikan ketika Anda dapat mengakses informasi otentikasi secara langsung di server.

Kita harus memindahkan contoh ini ke examples/ Saya akan melihat apa yang bisa saya dapatkan

Saya telah berhasil menggunakan react-cookie untuk cookie isomorfik dengan membungkus nextjs di server ekspres khusus dengan cara berikut:

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

Ini memungkinkan saya untuk membuat permintaan yang diautentikasi dari sisi server. Ini tidak mengatasi salah satu masalah peluru asli tetapi memecahkan masalah berbagi status antara klien dan server.

Dari POV seseorang yang belajar banyak hal ini. Saya pikir akan lebih baik jika contoh tidak mengandalkan layanan pihak ke-3 seperti auth0. Akan lebih bermanfaat bagi pendatang baru untuk melihat contoh yang lebih sederhana dengan formulir login/pendaftaran dan menggunakan Redux dan JWT.

Contoh yang kami rencanakan untuk _bundle_ akan didasarkan pada API server Node.js sumber terbuka

Saya telah menambahkan contoh otentikasi berbasis email ke contoh proyek pemula di https://github.com/iaincollins/nextjs-starter

Ini memiliki dukungan sesi (dengan Sesi Ekspres di backend dan API sessionStorage browser untuk menyimpannya di front end), cookie httpOnly, proyeksi CSRF, menggunakan SMTP bawaan untuk mengirim email, mudah untuk mengubah backend yang default ke SQL Lite . Tidak diperlukan konfigurasi untuk menjalankannya.

Proyek ini juga memiliki halaman tata letak, rute khusus dan menyertakan contoh jam dari wiki. Ini bukan contoh autentikasi yang paling keren, tetapi mungkin berguna bagi mereka yang mencari proyek sederhana yang mudah dipahami dan dimainkan.

Saya setuju dengan @iamjacks bahwa contoh dengan JWT sepertinya ide yang bagus.

Saya senang untuk meningkatkan penanganan kesalahan dan menambahkan fitur seperti halaman profil sederhana yang dapat diedit pengguna, dan integrasi paspor dengan contoh untuk oAuth untuk Facebook, Google dan Twitter jika itu akan berguna bagi orang-orang. Jika orang-orang memiliki ide bagus tentang cara yang lebih baik untuk menyebarkan/mengekspos info sesi ke komponen, saya sangat tertarik.

Example screenshot showing what to expect

Itu sangat luar biasa @iaincollins. Kami akan menampilkan ini di catatan rilis untuk 2.0 pasti :)

@rauchg Terima kasih! :)

Saya kira saya harus menambahkan secara eksplisit bahwa dalam contoh sesi ini berbasis klien dan server - yaitu bekerja dengan dan tanpa JavaScript (dan pada sistem tanpa sessionStorage), dan sesi yang sama dibagikan di keduanya.

Mencapai ini mendapat sedikit degil dalam komponen Sesi, yang menggali variabel dengan nama seperti req.connection._httpMessage.locals._csrf untuk mendapatkan token CSRF dari header server - sebagai objek 'req' diteruskan ke halaman di getInitialProps() anehnya sedikit berbeda dari objek req yang diekspos di Express karena saya biasanya mengaksesnya melalui req.locals._csrf (namun req.session sama di keduanya).

penyimpanan lokal tidak aman. apa cara terbaik untuk membuatnya lebih aman. siapa pun dapat mencuri data Penyimpanan lokal dan memasukkannya kembali ke browsernya dan dapat login sebagai pengguna korban!!

@Chathula itu tidak benar. Argumen ini salah.
Jika ada yang memiliki akses ke browser secara fisik, mereka dapat melakukan apa saja.

Itu juga berlaku untuk cookie.

Menggunakan localStorage untuk auth agak aman karena kami mungkin menghilangkan masalah detik berbasis cookie.
Tapi di sisi lain, itu mempengaruhi SSR.

@arunoda saya telah membuat login dengan Laravel API dan Next.js Client. saya menyimpan authUser access_token di dalam localStorage. kemudian periksa pengguna yang masuk atau tidak dengan mengautentikasi. tapi itu tidak aman. jika seseorang mencuri data penyimpanan lokal. dia bisa menggunakannya.

jika seseorang mencuri data penyimpanan lokal.

Bagaimana? Pada dasarnya dia harus memiliki akses ke browser secara fisik. Maka orang itu bisa melakukan apa saja.
Jadi, kita tidak perlu khawatir tentang itu.

tidak bisakah kita menggunakan enkripsi apa pun untuk membuatnya lebih aman?

@Chathula ini keluar dari topik. Ini tidak terlalu relevan dengan Next.js dan kami ingin melanjutkan dengan cara kerja web yang normal.

@Chathula mungkin Anda bisa memulai utas baru di proyek pemula di atas.

@arunoda hahaha !! Terima kasih atas infonya! :D

@Chathula Saya senang membahasnya lebih lanjut dalam masalah proyek pemula jika Anda memiliki masalah khusus.

Saya ingin mengoreksi kesalahpahaman apa pun, untuk menghindari orang-orang yang tidak perlu khawatir.

Web Storage API (yaitu localStorage dan sessionStorage) - seperti cookie tanpa httpOnly set - dibatasi melalui kebijakan Origin yang sama (protokol, nama host, nomor port), tidak benar bahwa "siapa pun dapat mencurinya"; tetapi ya jika seseorang dapat mengeksekusi JavaScript sewenang-wenang di situs Anda melalui Kerentanan Skrip Lintas Situs di aplikasi Anda, maka mereka juga dapat mengakses toko, jadi Anda tidak boleh menyimpan pengidentifikasi sesi di dalamnya.

Inilah sebabnya mengapa Anda akan melihat bahwa token sesi itu sendiri tidak disimpan di localStorage/sessionStorage dan tidak dapat dibaca dalam JavaScript, itu hanya ditransmisikan melalui cookie HTTP Saja (itulah sebabnya kelas sesi menggunakan XMLHttpRequest() daripada fetch() - seperti yang dijelaskan dalam dokumentasi kelas).

Ini berarti bahkan jika seseorang dapat mengeksploitasi Kerentanan Skrip Lintas Situs di aplikasi Anda dan mengeksekusi JavaScript arbitrer di aplikasi web Anda, mereka tetap tidak dapat membaca atau mengekspor token sesi pengguna.

Ini mungkin perbedaan penting yang layak untuk dikerjakan dalam dokumentasi.

Catatan: Enkripsi tambahan data pengguna tidak membantu di sini karena aplikasi selalu harus dapat membaca data agar dapat dirender (jadi Anda juga perlu menyimpan kunci deskripsi di aplikasi, yang akan merender enkripsi data pengguna cukup diperdebatkan).

_UPDATE: Dalam satu atau dua minggu terakhir, contoh telah difaktorkan ulang untuk menggunakan localStorage melalui sessionStorage karena sessionStorage tidak dibagikan antar tab dan berbagi data non-sensitif dengan cara ini mengurangi jumlah pemeriksaan autentikasi yang tidak perlu dan menjaga status sesi tetap konsisten antar tab._

Mungkin berguna bagi sebagian orang saya membuat aplikasi contoh ini saat bereksperimen:

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

Didukung oleh mainan ini backend:

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

Dikerahkan di sini:

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

Backend di sini:

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

@possibilities Terima kasih Mike! Serta mengekspos layanan mikro terpisah yang menunjukkan cara yang bagus untuk menangani halaman aman yang menurut saya mungkin pragma yang baik dan mungkin mengambil inspirasi darinya. Saya punya beberapa ide yang akan muncul di repo next.js-with-auth.

Setelah memberikan beberapa pemikiran lagi, saya mungkin tidak akan menganggap upaya saya di atas sebagai contoh yang bagus. Saya mungkin akan mengubah agar pendaftaran/masuk sepenuhnya mengirimkan gaya web 1.0 sehingga kami dapat membuat cookie HTTP saja di server (menghilangkan aksesibilitas ke JWT melalui XSS) dan kemudian melampirkan objek pengguna ke req gantinya daripada seluruh token. Ini meninggalkan kemungkinan kerentanan CSRF tetapi saya pikir ini lebih mudah untuk dimitigasi daripada XSS (bukan?). Efek samping yang bagus dari ini adalah aplikasi klien dapat menggunakan alur yang hampir sama ketika masuk melalui layanan sumpah.

Saya juga melihat di belakang saya dapat menghindari "middleware" (dan karenanya membutuhkan server khusus) dengan mem-parsing cookie di Page HoC's getInitialProps .

@possibilities Karena halaman 'rahasia' hanyalah sebuah halaman dan dibundel oleh webpack, bukankah itu akan disajikan ke browser jika saya membuka /secret?

Ya, saya kira itu harus ditransfer untuk melakukan pengalihan sisi server.

BTW, saya terganggu kembali ke proyek awal saya masuk dengan github. Alurnya mirip dengan lebih peduli tentang keamanan (yaitu tidak mengekspos rahasia apa pun pada klien untuk menghindari token oauth diekspos melalui XSS). Ini terikat dalam aplikasi yang tepat tetapi jika ada minat, saya dapat memecahnya menjadi sesuatu yang dapat berguna untuk aliran oauth secara umum.

@possibilities Saya pikir ini akan menjadi bantuan yang luar biasa, jika mungkin ada PR dengan contoh with-auth yang paling minimal (tapi tepat) Saya sedang mengerjakan auth di aplikasi saya (https://github.com/relatenow/ berhubungan) tetapi saat ini hanya sisi klien (localStorage).

@sedubois Saya punya pr untuk itu menggunakan passwordless.net https://github.com/zeit/next.js/pull/646 tapi kami akan memindahkan server auth di tempat lain

bagaimana dengan menggunakan graphql?

Apollo memberikan contoh otentikasi graphql:

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

Di sini kami mengautentikasi permintaan graphql, tetapi dapat disesuaikan untuk kasus kami.

Plus graphql dapat mengabstraksi implementasi dan logika. Itu dapat digunakan dengan tanpa kata sandi, auth0, atau apa pun yang kami inginkan.

@impronunciable FYI dengan contoh Anda, saya belum tahu bagaimana menangani sesi, karena saya ingin menyingkirkan tanpa kata sandi. Saya akan mencoba mengadaptasi contoh @iaincollins ' di aplikasi saya.

Persyaratan saya adalah:

  • aman
  • mengautentikasi sisi server lalu sisi klien
  • mendukung Facebook dan login/kata sandi
  • penyedia auth harus mudah diubah
  • buat pengguna di Graphcool
  • mengautentikasi permintaan GraphQL berikutnya ke Graphcool

Jika ini membantu seseorang, inilah aplikasi saya dengan autentikasi sisi server

Otentikasi harus dipisahkan dari server Next.js tetapi saya menunggu orang lain untuk memberikan inspirasi tentang itu ... Saya juga tidak yakin apakah itu dilindungi dengan baik dari CSRF.

Inilah yang saya lakukan:

  • ketika pengguna masuk, javascript sisi klien menyetel cookie di browser yang berisi token pembawa otentikasi
  • saat membuat permintaan yang diautentikasi, kode sisi server (next.js) membaca token pembawa di header permintaan browser dan menggunakannya untuk menghubungi server api atas nama klien

Ini rentan terhadap XSS (bahkan jika reaksi melakukan banyak hal untuk mencegahnya) dan serangan CSRF tetapi sederhana dan berfungsi dengan SSR.

Hanya untuk menambah permintaan

graph.cool + apollo + jwt + auth0 + next.js, 4 bagian pertama sudah dilakukan di https://github.com/graphcool-examples/react-apollo-auth0-example

@balupton dalam contoh Anda apa yang terjadi ketika token kedaluwarsa saat pengguna masih terhubung, apakah sesi baru saja selesai atau diperbarui entah bagaimana?

@nmaro tidak tahu, tidak ditulis oleh saya - sebaiknya tanyakan di sana

Untuk aplikasi saya sendiri, saya menjalankan autentikasi dengan next.js dan auth0, kemudian dengan server zeit/micro API yang memverifikasi token pembawa.

Seharusnya bisa open-source sekitar bulan Februari.

Mengikuti filosofi yang sama yang diikuti next.js (lakukan satu hal dan lakukan dengan baik), saya telah mengembangkan kerangka sistem akun pengguna yang dapat diperluas untuk node.js. Lihat filosofinya di sini: https://medium.com/the-ideal-system/ooth-user-accounts-for-node-js-93cfcd28ed1a#.97kyfg4xg

Proyek github ada di sini: https://github.com/nmaro/ooth/

Tujuannya adalah untuk memiliki autentikasi independen yang dapat diperluas + layanan manajemen pengguna yang ideal untuk digunakan sebagai layanan mikro terpisah, sebuah struktur aplikasi yang akan berfungsi sangat baik dengan node.js.

Contoh dengan otentikasi email+kata sandi ada di sini: https://github.com/nmaro/ooth/tree/master/examples/ooth
Sudah ada paket untuk Facebook dan Google auth (ooth-facebook, dan ooth-google), yang seharusnya mudah diterapkan berdasarkan paspor-facebook dan paspor-google masing-masing.

Saya akan memposting contoh integrasi next.js secepatnya. Jangan ragu untuk bergabung dalam diskusi dan berkontribusi.

Maaf untuk stekernya, tetapi ini untuk kebaikan yang lebih besar - saya benar-benar yakin belum ada solusi yang baik untuk node, dan ini adalah audiens yang tepat dari orang-orang yang mungkin menginginkan hal seperti itu. Perdamaian

Sementara itu... berikut adalah contoh graphql API yang memerlukan otentikasi dengan JWT-Token hanya untuk operasi tulis. Jangan ragu untuk menggunakannya dengan metode otentikasi favorit Anda :)

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

Saya telah memperbarui https://nextjs-starter.now.sh untuk menambahkan dukungan oAuth.

screen shot 2017-02-10 at 05 03 19

  • Ini menggunakan Paspor untuk oAuth, bersama dengan sesi ekspres (seperti sebelumnya).
  • Ada dukungan untuk Facebook, Google dan Twitter+ oAuth dan mudah untuk menambahkan lebih banyak (lihat AUTHENTICATION.md dan route /auth-passport.js ).
  • Ini menggunakan sistem sesi klien/server universal (dengan token CSRF, perlindungan XSS melalui cookie HTTP Only, lapisan ORM yang mendukung Mongo, SQL DB, Redshift, dll.) sebagai penggunaan masuk email.
  • Dapat melaporkan pengalaman mengonfigurasi oAuth di portal pengembang sama mengerikannya dengan sebelumnya (kesalahan aneh terjadi dan sulit untuk di-debug).

Sifat oAuth - db+sesi+paspor dan penanganan kesalahan yang perlu bekerja sama secara erat - dan sesi yang perlu bekerja baik klien dan server dan cara kerjanya dengan rendering universal - berarti sedikit banyak untuk mencoba dan membungkus sekaligus jika Anda mencoba mencari tahu apa yang sedang terjadi, tetapi logika klien tidak memiliki konfigurasi khusus oAuth sehingga tidak terlalu berantakan.

Saya akan senang untuk memisahkan hanya otentikasi menjadi contoh terpisah, meskipun saya menduga itu tidak akan jauh lebih kecil. Jika orang lain ingin, bagus. Saya mungkin akan menambahkan lebih banyak contoh di beberapa titik (seperti halaman manajemen akun). Mungkin lebih baik menautkan ke dokumentasi.

Pekerjaan yang luar biasa! Jika Anda dapat membagi auth Dan menambahkannya ke repo next.js itu akan luar biasa :heart:

saya juga bisa btw 👍🏻

Saya tidak akan punya waktu selama 2 minggu ke depan atau lebih, jadi jika seseorang ingin melakukannya akan sangat bagus.

Saya ingin memperbaikinya dan melihat apakah itu dapat direduksi menjadi hanya sebuah modul (yang memperlihatkan komponen sederhana seperti tombol masuk dan formulir masuk untuk disematkan), dan mengambil beberapa inspirasi dari contoh sisi klien sebelumnya yang sangat bagus oleh @impronunciable.

Pembaruan: Saya sebenarnya akan pergi, itulah sebabnya saya tidak bisa, tetapi ketika saya kembali, saya senang melihat melakukan itu!

Saya telah mengikuti panduan memulai cepat auth0/react dengan beberapa modifikasi, tetapi ketika saya menelepon lock.show() , aplikasi mengeluh:

Kesalahan Tidak Tertangkap: addComponentAsRefTo(...): Hanya ReactOwner yang dapat memiliki referensi. Anda mungkin menambahkan referensi ke komponen yang tidak dibuat di dalam metode render komponen, atau Anda memiliki banyak salinan React yang dimuat

@iaincollins @timneutkens tentang contoh Anda, mohon koreksi saya jika saya salah.

Contoh ini menggunakan cookie httpOnly untuk menyimpan token sesi sehingga aman terhadap serangan injeksi javascript (XSS). Kemudian ada masalah memiliki token csrf yang disimpan di penyimpanan lokal untuk juga melindungi dari serangan CSRF.

Ada asumsi mendasar bahwa kombinasi teknik ini membuat semuanya aman, yang dapat menyesatkan pengguna/pengembang. Penyerang masih dapat menyuntikkan javascript di halaman (XSS), membaca token csrf, dan menggunakannya untuk melakukan permintaan (cookie) yang diautentikasi ke apis. Apakah layak disebutkan dalam readme ?

Hai @davibe

Sayangnya, saat ini tidak ada pendekatan yang secara teknis lebih baik daripada cookie sesi dan token CSRF berputar yang terpisah, jadi saya harus mengatakan bahwa saya sangat senang dengan model itu karena sebenarnya tidak ada cara lain untuk melakukannya (bahkan jika implementasi aktual selalu dapat ditingkatkan).

Kita bisa menambahkan sidik jari browser, mungkin token sesi bisa berputar lebih sering (saya lupa kalau itu otomatis sekarang), token CSRF bisa menjadi header bukan param, cookie harus benar-benar SSL hanya dalam produksi dan kita bisa menambahkan tanggal kedaluwarsa untuk token masuk, tetapi AFAICS ada ruang lingkup yang cukup terbatas untuk peningkatan sejauh model keamanan berjalan dan dan tidak ada yang benar-benar memberikan perlindungan lebih lanjut jika seseorang dapat menyuntikkan kode apa pun yang mereka suka ke aplikasi; tapi tolong jangan ragu untuk mengangkat hal-hal itu sebagai masalah untuk perbaikan dalam repo.

Jika ada opsi pengubahan status akun (yang saat ini tidak ada), kami dapat memiliki CAPTCHA sebelum melakukannya agar lebih sulit untuk membuat perubahan di server tanpa izin, tetapi semua yang terjadi dalam contoh adalah pengguna dapat masuk dan keluar sehingga saat ini di luar jangkauan.

Menyimpan token sesi penyimpanan lokal akan membuatnya kurang aman dan bertentangan dengan tujuan penggunaan dalam spesifikasi, jadi secara pribadi saya tidak mendukung itu - meskipun saya menghargai itu akan menyederhanakan banyak hal, karena tidak memiliki proyeksi CSRF, tetapi orang mungkin tidak perlu contoh itu karena akan sangat mudah dilakukan - saya hanya mencoba memberikannya karena sangat canggung. :-)

Saya sepenuhnya dengan Anda karena saya juga benci betapa canggungnya itu dan tidak menyerah untuk mencoba mengubahnya menjadi modul.

Hmm.. aku mengerti.
Masalah ini sangat berguna bagi saya, terima kasih.

Ini adalah sudut pandang Auth0 https://auth0.com/blog/cookies-vs-tokens-definitive-guide/
Mereka pada dasarnya menyarankan untuk menghindari cookie tetapi saya pikir itu akan meninggalkan SSR pada pemuatan halaman pertama.

Hai semuanya!

Saya juga sedang mengerjakan otentikasi dengan next.js dan komentar dari masalah ini, khususnya @davibe + repo dari @iaincollins dan PR dari @timneutkens sangat membantu.

Solusi saya melakukan hal berikut:

  • Setelah login berhasil, peredam redux saya menyimpan token dan data pengguna dalam cookie menggunakan react-cookie .
  • Halaman/komponen apa pun yang memerlukan informasi tersebut dibungkus dalam komponen tingkat tinggi yang mirip dengan @timneutkens with-session.js . Jika SSR, token akan tersedia di ctx.req.headers.cookie, jika tidak, ambil saja dari dokumen browser (gunakan metode pemuatan react-cookie).
  • Setelah saya memiliki token, saya dapat mengaturnya di header Pembawa / Otorisasi setiap kali saya membuat permintaan.

Ini membantu bahwa saya memiliki layanan mikro otentikasi token JWT saya sendiri yang berjalan dalam wadah buruh pelabuhan.
Mungkin akan lebih mudah untuk menyediakan layanan JWT sederhana sebagai bagian dari contoh with-auth? Jadi menghindari untuk meretas server.js dan berpotensi kehilangan manfaat next.js yang dipanggang dalam hot reload, ssr, dan perutean?

Saya juga tidak yakin apakah pendekatan ini aman dalam hal CSRF/XSS. Setiap komentar dipersilakan.

Terima kasih kepada Anda semua untuk pekerjaan luar biasa yang telah Anda lakukan sejauh ini. Saya penggemar berat proyek ini!

@jcsmesquita Saya sedang mengerjakan versi baru dari contoh dengan semuanya terpisah dari Next.js mirip dengan bagaimana auth diimplementasikan di zeit.co.

@subsumo Terima kasih telah menyebutkan, FYI: NAP milik saya, authen via web didasarkan pada @iaincollins nextjs-starter plus reaksi login klien asli dengan token.

@timneutkens apakah solusi yang Anda kerjakan memungkinkan Anda mengautentikasi ke layanan terpisah?

Saya telah melihat contoh permintaan tarikan auth saat ini https://github.com/zeit/next.js/pull/1141
Tampaknya bagi saya itu hanya memungkinkan untuk mengautentikasi ke server next.js, tetapi tidak secara isomorfik menuju layanan terpisah.

Dengan kata lain, asumsikan Anda ingin memisahkan server next.js dan API aplikasi yang sebenarnya (misalnya REST atau GraphQL), maka yang ingin Anda lakukan adalah klien dan server dapat mengautentikasi ke API. Saya tidak berpikir solusi ini benar-benar membantu Anda di sana.

Saya memikirkan sebuah aliran.

Entitas:

  • Klien (C)
  • Next.js Server (S)
  • API (A)

Tujuannya adalah untuk membuat 3 sesi berbasis cookie:

  1. CS
  2. CA
  3. SA

Sesi 1) adalah agar Klien mengenali Server, dan 2) 3) adalah agar Klien dan Server dapat menggunakan sesi masing-masing untuk mengakses API secara independen.

Ini alurnya:

  1. CS mudah dilakukan, tidak perlu otentikasi
  2. CA dilakukan dengan otentikasi (misalnya dengan nama pengguna/kata sandi). Selain itu, JWT disediakan
  3. Klien menyediakan JWT ke Server dan kemudian membuangnya
  4. SA dilakukan dengan JWT, yang kemudian dibuang

Apa pendapatmu? Apakah ada cara yang lebih mudah? Haruskah kita menyimpan API yang digabungkan dengan server next.js, sehingga hanya diperlukan satu sesi (CS)?

@rauchg Saya tidak memanggil Anda dengan mudah, tetapi saya yakin ini juga tentang arah apa yang harus dituju selanjutnya.js - sebagai "universal front-end" haruskah dijalankan secara terpisah dari API yang menyediakan data? Jika ya, kita perlu melakukan ini dengan benar.

@timneutkens apakah solusi yang Anda kerjakan memungkinkan Anda mengautentikasi ke layanan terpisah?

Itu idenya ya. Sedang sibuk memperbaiki hal-hal lain di Next.js. Akan kembali ke sana secepatnya.

Saya memecah bagian khusus github-auth dari aplikasi saya menjadi contoh yang cukup mudah dicerna. mungkin menarik bagi sebagian orang dan akan menyukai umpan balik tentang kode atau alur: https://github.com/possibilities/next-github-auth-example

PEMBARUAN: Saya memfaktorkan ulang aplikasi contoh menjadi satu set komponen yang dapat digunakan kembali yang dapat "dimasukkan ke" aplikasi berikutnya

Tindak lanjut: Saya menulis integrasi dengan ooth dan GraphQL API.

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

ini didasarkan pada pendekatan yang ada, yaitu otentikasi ke server next.js, yang mengasumsikan api dan server otentikasi untuk menjalankan semua dalam proses yang sama, jadi hanya satu sesi yang harus dibuat. Keuntungannya: pada prinsipnya ia dapat menyimpan kredensial untuk / dapat diperluas ke hampir semua strategi passport.js.

@timneutkens ada kemajuan di depan itu?

Saya memfaktorkan ulang aplikasi contoh auth github saya menjadi satu set dekorator dan komponen halaman yang dapat digunakan kembali untuk "menjatuhkan github auth ke" aplikasi berikutnya. Umpan balik kode dan fungsionalitas disambut. https://github.com/possibilities/next-github-auth

Saya _berpikir_ mungkin menarik untuk memakukan papan di sini dan kemudian terus mengembangkan ini menjadi kerangka kerja autentikasi yang lebih umum untuk selanjutnya.

@timneutkens
Maaf untuk melakukan ping kepada Anda, tetapi apakah Anda membuat kemajuan dalam hal ini? Saya benar-benar bingung tentang bagaimana saya harus mengatur otentikasi dengan next.js dengan benar.

@kolpav Saya telah melakukan beberapa pekerjaan di dalamnya, saat ini dibanjiri dengan hal-hal lain Dengan segala cara ini cukup tinggi dalam daftar prioritas saya untuk Berikutnya

Cara yang jelas, terdokumentasi dengan baik, dan aman untuk mencapai autentikasi dengan aplikasi next.js sangat penting untuk keberhasilannya sebagai kerangka kerja.

Saya tidak ingat kapan terakhir kali saya membuat web yang tidak memiliki otentikasi.
Seperti kebanyakan orang yang saya bayangkan, saya juga ingin melakukan panggilan aman ke data cadangan saya, jadi JWT tampaknya merupakan solusi yang jelas.

Tapi ada begitu banyak diskusi di antara isu-isu dan PR saya tidak yakin harus mulai dari mana!

@timneutkens
Keren 👍 Saya pikir itu akan sangat berharga bagi orang lain.

@camstuart @kolpav Ada beberapa contoh yang bagus dan berfungsi di atas termasuk mendukung oAuth dan auth berbasis email yang menggunakan Cookie JWT dan HTTP oleh kontributor @jaredpalmer , @luisrudge , @impronunciable , @possibilities dan saya sendiri.

Untuk menyorot beberapa tautan, periksa:

(Contoh autentikasi mikro bagus tapi saya pikir perlu diperbarui.)

Ada ruang untuk perbaikan lebih lanjut, yang telah dikomentari oleh komentator tambahan di atas - termasuk komponen penyimpanan sesi dan pemisahan logika server; dan contoh yang menyederhanakan hal-hal lebih jauh yang telah dikerjakan Tim.

Kesederhanaan untuk autentikasi adalah area yang menantang untuk aplikasi Universal, tetapi Anda harus dapat menjalankan contoh di atas - atau hanya mencoba demo secara langsung - dan melihat cara kerjanya tanpa terlalu banyak keributan.

@iaincollins Itu contoh yang bagus. Tetapi bagaimana saya bisa menggunakan (misalnya) proyek pemula? Jadi Jika saya ingin membangun aplikasi saya. Saya perlu mengkloning repo ini? Atau saya perlu "menyalin-menempel" kode dari proyek awal potongan demi potongan ke kode saya sendiri?

Jika proyek awal akan diperbarui - apa yang harus saya lakukan?

@iaincollins
Contoh yang bagus terutama milik Anda.
Tapi tetap saja, saya ingin melihat contoh auth dengan segel persetujuan di atasnya semua mata akan mengarah ke satu arah sehingga setiap kesalahan atau kesalahan tidak akan luput dari perhatian. Untuk saat ini, saya memiliki auth kerja saya sendiri tetapi saya tidak yakin seberapa aman itu.

Setuju @kolpav ,

Saya telah membuat tumpukan untuk ini yang dapat menangani otentikasi dengan mudah dengan GraphQL: https://github.com/thebillkidy/MERGE-Stack

@salmazov Saya telah menemukan cara yang berguna untuk memulai dan memahami apa yang terjadi dalam contoh atau proyek pemula dapat dengan memotongnya, lalu menghapus hal-hal yang tidak relevan sampai Anda hanya memiliki kode yang terkait dengan fungsionalitas Anda ingin menerapkan; dan kemudian mencoba memindahkan fungsionalitas itu ke proyek lain.

@kolpav @camstuart Utas ini berisi diskusi yang sangat luas tentang berbagai model keamanan, termasuk menyanggah beberapa kesalahpahaman umum dan kompromi. Saya secara khusus mencatat poin-poin tentang Cookie Hanya HTTP dan token CSRF (dan perlindungan tambahan yang mereka berikan terhadap XSS dan CSRF karena menggunakan JWT dan/atau API Penyimpanan Web untuk token sesi). Ini benar-benar layak dibaca.

@iaincollins Apakah Anda bermaksud menautkan sesuatu? :senyum:

Hallo teman-teman :)

Saya punya pertanyaan, saya sedang membaca selanjutnya tidak bisa mendapatkan token untuk auth dengan jwt dari penyimpanan lokal.

Jika saya memiliki server untuk membuat hanya biaya pertama situs saya dengan berikutnya. Dan saya memiliki server lain untuk api saya. Ini menerima pengguna/pass dari klien dan memberikan jwt. Dalam hal apa saya perlu mendapatkan token di server??

Mengapa saya perlu token di server render (berikutnya)?

Jika klien tidak mengirim token ke server api, api tidak memberikan data, dan pengguna tidak bisa mendapatkan info pribadi. Saya tidak mengerti mengapa saya harus mengirim token ke server render.

@kamilml

Ini mungkin membantu. Secara umum, Anda memiliki dua opsi:

  1. Berikan JWT server Berikutnya (mungkin melalui cookie). Ini akan memungkinkan server Berikutnya untuk membuat panggilan api atas nama klien. Anda akan menginginkan ini jika rendering sisi server penuh penting bagi Anda.

  2. Simpan JWT di penyimpanan lokal klien dan jangan berikan akses server Berikutnya ke sana. Dalam hal ini, Anda cukup melewati sisi server panggilan api dan menunda render penuh hingga pemuatan sisi klien selesai.

Maaf untuk membuka kembali ini, tetapi saya pikir saya akan menambahkan 2 sen saya ke utas ini, dan bagaimana R&D awal saya berjalan di area ini. Lebih sedikit contoh kode, lebih banyak aliran tingkat tinggi.

Pertama, untuk konteks, sebagian besar aplikasi kami sudah dibangun di Symfony 3 (PHP), dan menggunakan Vue untuk pengalaman hybrid. Server merender halaman pembungkus, dan menetapkan data aplikasi ke __INITIAL_STATE__ untuk diambil oleh aplikasi. Ini telah menghasilkan keputusan antara merender halaman pemasaran di Symfony (untuk SEO), dan memilih UX/UI daripada SEO di area lain dengan mengambil data melalui JS dan memberikan nuansa yang lebih SPA. Juga perlu diperhatikan, tidak semua halaman adalah publik/swasta biner (seperti yang saya lihat dalam beberapa contoh). Beberapa halaman bersifat publik secara default, dan kemudian dirender secara berbeda jika diautentikasi. Kami sedang mempertimbangkan untuk menggunakan SPA untuk bagian-bagian situs, tetapi dalam banyak cara praktis, itu adalah UX/UI yang lebih buruk (TTI lebih lambat, bilah kemajuan, dll.). Plus, itu tidak menyelesaikan masalah SEO, kecuali kami memperkenalkan FOUC dan merender teks dua kali (sekali melalui Symfony, sekali lagi sebagai komponen JS), dll.

Masukkan SSR/Universal JS...

Dalam kasus saya, apa yang saya lakukan, adalah meniru logika PHPSESSID , dengan membuat cookie HttpOnly UJSSESSID (mengadakan nama), dan menetapkan nilainya ke cookie pengguna JWT. Aplikasi Symfony meneruskan ini di setiap permintaan halaman saat pengguna bernavigasi di sekitar situs. Saat pengguna membuka halaman UJS, sisi server aplikasi tersebut akan menerima cookie dalam permintaan (sesuai dengan perilaku bawaan browser). Jika cookie UJSSESSID disetel, aplikasi akan memanggil API untuk mendapatkan informasi pengguna (mis. /api/v1/users/me dengan meneruskan token melalui header Authentication ). Panggilan lainnya dilakukan melalui API, menggunakan token yang sama. Mekanisme logout Symfony menghapus cookie UJSSESSID . Saat berikutnya aplikasi UJS dimuat, itu akan membuat halaman dalam mode pengguna anonim. FYI, perutean halaman Symfony vs. UJS dilakukan melalui ProxyPass Apache. Penyimpanan Lokal tidak digunakan.

Hasil akhirnya adalah UX yang mulus di mana pengguna berada di beberapa halaman yang PHP dengan JS sisi klien, dan beberapa halaman yang UJS. Ini memungkinkan kami melakukan pengujian A/B, dan memperbarui situs secara iteratif – tidak semua orang dapat memulai dari awal :)

Meskipun ini sedikit lebih rumit karena PHP/UJS simbiosis, prinsip yang sama dapat digunakan dalam solusi UJS lengkap dengan middleware server API atau Node.js (mis. Express, Adonis, dll.). Alih-alih mengatur cookie UJSSESSID melalui permintaan halaman PHP ( HttpOnly flag), mintalah pengguna login melalui SPA/UJS Anda, dan atur cookie di sana. Yang TIDAK BOLEH Anda lakukan, adalah menggunakan aplikasi Anda untuk memecahkan kode JWT, atau melakukan panggilan pihak ketiga yang memerlukan client_secret . Gunakan middleware yang tetap berada di server untuk itu.

Harapan yang membantu seseorang. Contoh lain yang pernah saya lihat adalah cawan petri yang terlalu kecil untuk saya.

@jaredpalmer Hei terima kasih atas implementasinya, saya mencobanya, cukup salin-tempel semua kode Anda, ganti dashboard.js Anda dengan index.js saya yang terlihat seperti ini:

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

export default withAuth(index)

dan di withAuth hoc saya mengubahnya untuk mengarahkan ulang ke halaman masuk.
Tetapi sebelum dialihkan ke halaman masuk, isi halaman indeks masih berkedip sebentar. :S

Apa status masalah ini? 😇

Ini sedikit membanjiri orang baru yang membaca seluruh diskusi. Saya memutuskan untuk menerapkan otentikasi yang sangat mendasar di sini. Hanya 2 halaman (indeks, login), dan server khusus
https://github.com/trandainhan/next.js-example-authentication-with-jwt

Pada dasarnya, kami memiliki middleware otentikasi di server untuk memeriksa token di header setiap permintaan. Jwt-token akan disimpan dalam cookie. Saya menemukan ini sangat sederhana, lurus ke depan dan bekerja dengan sangat baik.

@trandainhan Bisakah Anda menambahkan titik akhir POST yang menggunakan token rahasia untuk mencegah serangan CSRF?

@sbking Kode sumber yang diperbarui dengan contoh titik akhir yang dilindungi oleh serangan CSRF

Apakah ini siap digunakan ?

Adakah yang mencoba auth dengan redux-auth-wrapper ?

Halo semua! Selama beberapa bulan terakhir saya membuat, dan sekarang disempurnakan

Ini fitur:

  • Pendaftaran dengan email dan kata sandi
  • Masuk dengan email atau nama pengguna dan kata sandi
  • Halaman akun tempat Anda dapat mengatur nama pengguna, mengubah kata sandi, dan mengirim ulang email verifikasi
  • Lupa kata sandi/setel ulang halaman kata sandi
  • Verifikasi halaman email
  • API GraphQL dasar yang ditautkan ke MongoDB (1 file, dapat dengan mudah dihapus)
  • Boilerplate minimal (logika sebanyak mungkin dienkapsulasi di perpustakaan)

Lihat demo langsung di sini: http://staart.nmr.io/

Saya melakukannya terutama untuk diri saya sendiri untuk pembuatan prototipe cepat, untuk memulai dengan cepat dengan aplikasi dengan sistem akun kerja sederhana yang tidak bergantung pada layanan eksternal. Saya cukup senang dengan hasilnya. Saya bermaksud untuk terus menggunakan dan memelihara perpustakaan ini, jadi cobalah jika Anda merasa bahwa sistem akun + UI untuk simpul yang sudah ada masih belum ada.

@trandainhan Terima kasih, itu contoh yang sangat bagus dan lebih sederhana untuk banyak orang dan akan bekerja dalam banyak skenario.

Saya akan memikirkan jika/bagaimana saya dapat mengadaptasi logika saat ini di nextjs-starter untuk menggunakan sesuatu seperti ini tetapi dengan aman, sambil tetap kompatibel dengan logika sesi ekspres untuk kasus penggunaan dunia nyata yang saya miliki (seperti menggunakan hal-hal seperti Google oAuth API di mana saya memerlukan server untuk menyimpan dan melacak token yang diberikan pada login pertama).

Saya belum tahu apakah itu mungkin, tetapi akan jauh lebih mudah bagi orang-orang jika itu mungkin.

Jika tidak, setidaknya ada baiknya menulis di suatu tempat untuk menjelaskan kepada orang-orang pilihan yang berbeda.

@trandainhan : Jika saya menambahkan <Link href="/">Home</Link> ke login.js, dan kemudian klik Tautan yang dihasilkan, saya kemudian dapat mengakses index.js tanpa login. Bagaimana Anda menyarankan untuk memperbaiki ini dalam contoh Anda?

@iaincollins Saya melihat sebagian besar solusi di sini mengautentikasi terhadap layanan oauth. Apakah ada solusi bagus untuk mengautentikasi terhadap API yang bergantung pada JWT?

@paulwehner Saya pikir itu terjadi karena @trandainhan hanya menangani perutean

@carlos-peru Di bawah tenda, Tautan sebenarnya menggunakan next/router untuk mendorong jalur baru ke dalam riwayat browser. Sepertinya sebagian besar hal ditangani oleh browser, tidak ada yang bisa dilakukan di sini untuk middleware di sisi server. Sejauh ini, saya hanya dapat berpikir untuk membuat komponen Tautan kami sendiri dan melakukan hal-hal lain setiap kali kami mengubah url.

@carlos-peru Anda selalu dapat menggunakan server khusus untuk memiliki kontrol penuh atas perutean.

Terima kasih @trandainhan dan @kolpav! Saya harus memiliki pemahaman yang lebih baik setelah menghabiskan beberapa waktu selama akhir pekan. Saya juga berhasil mengimplementasikan solusi yang bergantung pada HOC yang menyimpan token jwt pada cookie, sehingga server dan klien dapat menggunakan api.

@nmaro Saya memiliki Backend dengan otentikasi JWT untuk situs web di next.js dan aplikasi (react-native).

Jadi. Saya pikir dalam model berikutnya: Klien memperoleh token Facebook (Pengguna menerima login facebook) dan kemudian klien mengirim token ke backend untuk memeriksa dan memvalidasi token pengguna (token paspor-facebook di node-js backend) . Kemudian, jika tokennya bagus, backend mengirimkan ke klien JWT yang dihasilkan di backend.

Masalah? Alat Anda dapat memperoleh kunci dari facebook dan google? Saya menggunakan hello.js tetapi tidak kompatibel dengan next.js dan seluruh dunia menggunakan paspor-facebook. Saya pikir itu kesalahan besar karena server api harus kompatibel dengan klien web dan aplikasi seluler.

Terima kasih

PS: Saya tidak bisa mendapatkan undangan di saluran slack Anda.

@hmontes di sini - undangan ke saluran slack untuk proyek ooth (akun pengguna untuk node, khususnya next.js) jangan ragu untuk bergabung. Ooth menggunakan paspor-facebook-token (bukan paspor-facebook) dan paspor-google-id-token yang saya percaya memecahkan masalah Anda.

@nmaro Saya ingin membantu Anda dengan proyek Anda. Saya memiliki backend dengan Graphql dengan paspor-facebok dan paspor-google-id-token juga !!!

Tetapi. Apakah Anda tahu paket yang kompatibel untuk menghubungkan klien facebook/google di next.js?

Di sisi klien, Anda dapat menggunakan pola serupa daripada yang saya gunakan di sini: 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
(daripada oothClient.authenticate cukup kirim permintaan posting ke rute otentikasi Anda).

@timneutkens apakah PR dengan contoh yang minimal akan diterima?

@nmaro dalam contoh Anda. Mengapa Anda menggunakan componentDidMount alih-alih componentWillMount?

Saya membuat komponen HoC (penyedia) untuk login Google.

Apakah componentWillMount hanya dipanggil pada klien? Maka itu harus baik-baik saja.

Oke. Terima kasih banyak atas contoh Anda. Akhirnya saya bisa menerapkan auth dengan media sosial.

Pertanyaan terakhir. Saya membuat access_token dan refresh_token dan saya ingin memasukkan localStorage untuk menyimpan data.

Di mana saya bisa meletakkan ini di next.js untuk memeriksa login saat halaman disegarkan? Dalam create-react-app saya memasukkannya ke dalam index.js

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

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

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

Terima kasih

Dengan ooth, saya tidak menyimpan token facebook, saya hanya menggunakannya sekali dengan paspor dan kemudian membuat sesi pengguna berbasis cookie normal.

Ah. Oke. Saya menggunakan JWT alih-alih sesi. Jadi, saya mengirim access_token ke backend, itu memeriksa apakah token itu valid di layanan (google, facebook), lalu jika pengguna ada di aplikasi saya dan mengirim saya kembali JWT.

Terima kasih :)

Saya harus menambahkan bahwa berbahaya menyimpan JWT di penyimpanan lokal (karena XSS), lebih baik mengirimnya sebagai cookie jika semuanya dalam satu server/domain, sehingga kode javascript klien tidak bisa mendapatkan JWT, tetapi browser akan mengirim JWT secara otomatis sebagai cookie. JWT itu rumit (lihat diskusi panjang di atas), itu sebabnya saya menggunakan sesi.

Saya menggunakan JWT hanya jika ooth digunakan sebagai layanan mikro otentikasi eksternal (karena cookie hanya berfungsi pada domain yang sama), dan itupun saya menggunakannya tepat sekali untuk kemudian membuat sesi dengan server, sehingga tidak disimpan di mana pun di klien .

Untuk peningkatan keamanan JWT, Anda dapat menggunakan token penyegaran (Diambil dari oauth2).

Aplikasi Seluler dapat menangani Cookie?

@nmaro Oke. Saya memahamimu. Maaf atas kesalahan saya.

Apakah Anda memiliki tutorial atau kode untuk menyimpan Token JWT ke dalam Cookie? Saya mencari https://github.com/zeit/next.js/blob/master/examples/with-firebase-authentication (Sistem auth saya dengan graphql)

Tidak, maaf, saya tidak pernah melakukan itu.

@hmontes @nmaro
Saya menulis ini untuk diri saya sendiri, tetapi dapat membantu:
https://github.com/malixsys/mobazoo

Hai @malixsys terima kasih telah berbagi. Sesuatu yang saya tidak mengerti dari kode Anda: sepertinya Anda akan mengonfigurasi API_BASE_URL ke sesuatu yang eksternal, bukan? Jika Anda mengautentikasi ke API itu, saya kira itu akan memulai sesi berbasis cookie, bukan? Tapi kemudian, bagaimana Anda mentransfer cookie itu ke server next.js, dengan asumsi server next.js ada di domain lain?

Ah tidak, saya mengerti, Anda mengatur /auth/signin dalam proses yang sama. Oke, maka pada dasarnya pendekatan yang saya gunakan untuk ooth dengan next.js / staart.

Sebenarnya tidak, saya masih bingung: di /auth/signin Anda mengembalikan JWT, tetapi Anda tidak pernah melakukan apa pun dengan itu di sisi klien. Kemudian Anda "getUserFromCookie" tetapi saya tidak melihat di mana Anda mengatur cookie.

@nmaro Saya hanya ingin login dasar berfungsi dengan universal pada awalnya. Saya mengatur jwt dan cookie untuk saat ini. Cookie digunakan untuk melakukan universal. Saya belum menggunakan jwt dalam panggilan axios lain di repo ini. Saya melakukannya di garpu pribadi di mana API_BASE_URL menunjuk ke domain lain ...
Semuanya ada di daftar TODO saya, dengan PWA.
Silakan buka masalah atau ping saya di sini...

@nmaro cookie diatur dalam saveUser() sini: https://github.com/malixsys/mobazoo/blob/master/utils/auth.js

Saya tahu bahwa masalah ini sudah selesai, tetapi saya ingin menunjukkan solusi saya.
https://next-auth.now.sh/
Saya pikir ini sedikit mirip dengan situs web zeit.co

9 April

Saya telah melakukan beberapa pekerjaan di dalamnya, saat ini dibanjiri dengan hal-hal lain Dengan segala cara ini cukup tinggi dalam daftar prioritas saya untuk Berikutnya

22 Sep #2974

Kami berencana untuk segera merilis contoh autentikasi resmi, dapatkah Anda merilis ini sebagai repositori terpisah? Terima kasih!

@timneutkens

Hai, maaf mengganggu Anda tentang ini lagi, tetapi bisakah Anda membagikan bagaimana status contoh auth resmi? Ini pasti sesuatu yang saya ingin lihat dan menilai dari jumlah komentar dalam masalah ini yang lain juga. Jadi seberapa tinggi itu dalam daftar prioritas dan haruskah kita berharap? 😄

Hai @kolpav , mereka secara resmi mengumumkan ini sebagai peta jalan untuk Next.js 5.

Terakhir, kami menambahkan beberapa contoh yang sangat diminta (seperti autentikasi pengguna), dokumentasi yang ditingkatkan untuk internal Next.js dan fitur serta perbaikan bug yang lebih kecil.

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

@babenzele Itu berita bagus. Aku pasti merindukan itu

Di mana kita bisa tetap up to date dengan perkembangan Next.js 5? Saya sedang mengintegrasikan auth0 saat ini, tetapi akan lebih baik jika memiliki jalur/contoh auth nextjs resmi untuk diikuti

Tampaknya Next.js sangat membutuhkan contoh autentikasi lokal resmi menggunakan JWT/cookies/localStorage (atau kombinasinya, asalkan aman dan terlindungi dari XSS/CSRF)... Saya menghabiskan beberapa minggu untuk mencoba buat ini menggunakan server Express API terpisah dengan Strategi Lokal Passport.js. Saya mencoba JWT di cookie/localStorage untuk permintaan tanpa kewarganegaraan, dan saya juga mencoba cookie biasa dengan ID sesi dari middleware sesi ekspres di dalamnya setelah saya akhirnya menyerah pada JWT dan keadaan tanpa kewarganegaraan. Saya akhirnya mengalami masalah di mana sesi tambahan sedang dibuat di server Express API karena cara kerja sesi ekspres (dicoba dengan saveUninitialized: false). Saya mempertimbangkan untuk memindahkan kode Express ke server.js di aplikasi Next.js saya, tetapi saya lebih suka itu menjadi server yang terpisah. Saya juga cukup yakin implementasi saya tidak aman dari XSS/CSRF atau pembajakan cookie. Kami membutuhkan contoh resmi yang mencakup praktik terbaik untuk otentikasi/login lokal, atau mungkin modul resmi sebagai bagian dari Next.js yang akan menangani kerumitan bagi kami!

Sementara kami menunggu Next.js 5.x dan contoh lebih lanjut, Anda mungkin ingin melihat https://nextjs-starter.now.sh yang masih aktif dipelihara dan menggunakan Next.js dengan Express, Express Sessions, CSRF ( Token CRSF), XSS (Hanya Cookie HTTP untuk token sesi) dan menggunakan Passport JS untuk mendukung oAuth dan Email.

Saya sebenarnya sedang dalam proses refactoring kode auth menjadi modul, membuatnya sangat mudah untuk menambahkan otentikasi ke proyek Next.js dengan cara yang mudah digunakan. Modul harus memungkinkan Anda untuk menggunakannya dengan mudah dengan database apa pun yang Anda suka, tanpa harus menyalin banyak kode dari contoh Proyek Pemula. Saya berharap bisa menyelesaikannya minggu ini.

Sebagai referensi, metode "Double Submit Cookie" memberikan cara mudah untuk menambahkan perlindungan CSRF jika Anda mencari pendekatan yang sederhana namun aman.

Masalah dengan JWT di localStorage adalah selalu dapat dibaca dari JavaScript sisi klien, jadi vektor untuk pembajakan sesi melalui XSS, jika Anda memiliki konten yang tidak tepercaya (misalnya konten atau iklan yang dikirimkan pengguna).

Jika Anda menggunakan cookie HTTP Saja untuk token sesi - atau sesuatu seperti JWT dengan nilai token di HTTP Saja (atau mengenkripsi seluruh JWT dan mendekripsi menggunakan token Hanya HTTP di server) - maka sesi akan dilindungi semaksimal mungkin menjadi. Idenya adalah, idealnya, token sesi secara khusus tidak boleh dibaca melalui JavaScript sisi klien.

Tentu saja banyak situs tidak menggunakan cookie HTTP Saja karena menyusahkan untuk Aplikasi Halaman Tunggal, dan selalu melibatkan beberapa logika auth di bagian depan, tetapi itu masih merupakan pendekatan yang ideal.

Pilihan lain masih https://github.com/nmaro/ooth yang dipelihara secara aktif, sudah datang dalam paket dan sedang digunakan di beberapa aplikasi produksi.

@iaincollins Saya mengunduh Proyek Pemula Next.js dan mulai memeriksanya. Saya harus memisahkan bagian penting terkait keamanan (XSS/CSRF) dan mencoba mengintegrasikannya ke dalam aplikasi saya, atau menunggu hingga Anda menyelesaikan modul terpisah. Apakah ada tempat saya dapat melacak perkembangan modul itu?

Hai @kelleg1 ,

Modul terpisah sekarang diterbitkan sebagai modul autentikasi berikutnya untuk membuatnya lebih mudah digunakan di proyek lain. Ini termasuk proyek contoh yang menunjukkan cara menggunakannya.

Untuk referensi lebih lanjut, proyek nextjs-starter.now.sh sekarang juga menggunakan next-auth, yang sangat menyederhanakan kode dalam proyek pemula - dan sekarang jauh lebih mudah untuk menambahkan dukungan untuk penyedia oAuth baru atau menggunakannya dengan database yang berbeda ( meskipun contoh masih menggunakan Mongo DB).

Ini masih agak rumit jadi jika Anda memiliki aplikasi yang sudah ada, Anda mungkin merasa lebih mudah untuk digunakan sebagai referensi, tetapi jika demikian saya harap ini membantu

NB: CSRF saat ini masih cukup rapat di dalamnya. Ia menggunakan lusca jadi menganggap res.locals._csrf disetel, tetapi pustaka CSRF yang berbeda menggunakan vars pribadi yang berbeda.

Saya menghargai ini masih lebih rumit untuk digunakan daripada yang diinginkan siapa pun, tetapi setidaknya sekarang kode auth akhirnya dipisahkan menjadi modul sehingga saya dapat mulai melakukan refactor. Saya berharap untuk membuatnya lebih mudah digunakan (dengan penangan default untuk database yang berbeda, dan konfigurasi oAuth yang lebih mudah) dari waktu ke waktu.

@iaincollins sepertinya satu-satunya ketergantungan pada next.js adalah https://github.com/iaincollins/next-auth/blob/master/index.js#L342 ? Jika demikian, akan sangat bagus untuk membuat lib next.js-agnostic.

@sedubois Sangat setuju!

Meskipun itu mungkin diskusi yang bagus untuk masalah repo GitHub daripada di sini. Jika Anda ingin menyarankan cara agar hal itu dapat ditingkatkan, disederhanakan, dan dibuat lebih umum, saya ingin berkolaborasi.

(Memiliki sesuatu yang semudah mungkin digunakan dengan berikutnya masih merupakan tujuan utama, tetapi saya tidak melihat bahwa itu perlu eksklusif, bahkan jika itu berakhir dengan opsi fokus khusus berikutnya juga.)

@timneutkens Selamat atas rilis nextjs 5. Dalam waktu dekat akankah kita melihat penambahan contoh otentikasi lokal resmi ditambahkan ke folder contoh? Atau apakah ini sesuatu yang masih dalam pengerjaan untuk rilis selanjutnya?

Ooth sekarang memiliki dokumentasi yang komprehensif, termasuk spesifikasi otentikasi next.js .

@jaredpalmer Saya suka pendekatan Anda, saya menyalin bagian dari implementasi Anda. Namun, apakah metode getUser aman? Bagaimana jika seseorang mengubah string dalam penyimpanan lokal dengan tangan, apakah akan pintar jika aplikasi mengandalkan ini? Apakah lebih masuk akal untuk mengubahnya menjadi metode yang memecahkan kode bagian publik JWT dari token setiap kali dan membaca status pengguna dari sana? Dengan begitu kita bisa lebih mempercayai keadaan ini karena sifat JWT. Apa pendapat Anda?

Anda harus menyimpannya dalam cookie. Saya menulis bahwa sebelum Next memiliki dukungan untuk server khusus.

@jaredpalmer Bisakah Anda memberi tahu saya lebih banyak tentang itu? Haruskah kita menyimpan semuanya dalam cookie daripada penyimpanan lokal? Apakah HOC Anda juga berbeda? Apakah ini berarti kita sekarang dapat menggunakan metode getInitialProps untuk situs web yang dilindungi rendering sisi server?

Perhatian _jika yang Anda bicarakan tentang penyimpanan adalah data sensitif di penyimpanan lokal/Penyimpanan Web_:

"Jangan pernah menyimpan data sensitif menggunakan Penyimpanan Web: Penyimpanan Web bukanlah penyimpanan yang aman. Ini tidak "lebih aman" daripada cookie karena tidak ditransmisikan melalui kabel. Itu tidak dienkripsi. Tidak ada bendera Aman atau HTTP saja jadi ini bukan tempat untuk menyimpan sesi atau token keamanan lainnya."

Atur token dalam cookie setelah login. gunakan cookie-js. Kemudian gunakan parser cookie ekspres di server sehingga Anda dapat memeriksa get req.headers.cookies.myToken atau yang setara. Di getInitialProps hoc, periksa apakah req ada, lalu ambil token dari req.cookies, jika tidak, dapatkan di klien dari Cookies.get('mytoken'). Pada titik ini Anda akan memiliki akses ke token Anda di klien dan server. Kemudian Anda ingin membuat fetch/axios wrapper/instance dan menggabungkannya dengan ctx berikutnya di getInitialProps sehingga semua halaman Anda memiliki cara untuk membuat permintaan isomorfik yang diautentikasi. Anda mungkin juga ingin mendapatkan pengguna Anda di hoc juga. Jadi Anda tidak perlu mengulanginya di mana-mana. Anda kemudian dapat membuat lebih banyak hoc jika perlu untuk entitas umum seperti withUser(withTeam(Page))

getUser adalah ide yang buruk, Anda hanya boleh menyimpan token.

@jaredpalmer Saya membangun pendekatan yang hampir persis seperti itu dan semuanya bekerja dengan baik. Masalah yang saya coba selesaikan sekarang adalah bagaimana me-refresh token. API yang saya gunakan memiliki token yang relatif berumur pendek (2 jam) dan saya mencoba memahami beberapa sistem agar pengguna tetap masuk saat menggunakan aplikasi.
Apakah Anda punya masukan tentang itu?

Anda juga dapat menyimpan permintaan pada setiap transisi halaman dengan tidak meneruskan data melalui next.js untuk pengguna Anda. Untuk melakukan ini, Anda akan membaca token dari cookie di server.js dan mencoba mengambil pengguna dan meneruskannya ke penangan permintaan berikutnya. Dalam dokumen, dapatkan dari alat peraga dan simpan di JSON di seperti window.USER. Kemudian di hoc Anda, Anda baru saja membacanya dari jendela saat berada di klien. Terakhir, Anda harus menggunakan axios dengan pencegat respons yang segera menghapus cookie Anda setelah menerima kode 403 dan memuat ulang halaman

@pbrandone Meskipun berulang, solusi paling sederhana & paling dapat diprediksi adalah mengirim token Anda dengan setiap permintaan, menerima token yang baru disegarkan di header/badan respons. Klien Anda memperbarui nilainya yang diketahui pada setiap siklus permintaan/tanggapan, secara efektif memberikan token sekali pakai yang tidak pernah basi & tidak dapat disalahgunakan.

Biasanya, dengan pendekatan ini, /token/refresh hanya digunakan untuk "bangun" awal Aplikasi (pikirkan componentWillMount hook untuk <App/> ), memeriksa untuk melihat apakah yang terakhir disimpan token masih valid & dapat digunakan.

Tidak pernah berurusan dengan token penyegaran, tetapi saya mungkin akan mencoba melakukannya di pencegat axios. Harus memikirkannya lebih lanjut, tetapi secara teori Anda akan mencegat permintaan yang buruk, kemudian menggunakan token penyegaran untuk mendapatkan token baru, mengatur cookie dengan token baru, dan memutar ulang permintaan pertama dengan token baru lagi. Pencegat Axios sangat kuat karena memungkinkan Anda untuk menjaga hal-hal seperti ini diabstraksikan dan tidak terlihat dari kode produk Anda. Anda mungkin perlu menulis pencegat permintaan dan respons dan/atau memegang semacam objek/peta stateful yang sedang berjalan yang bisa menjadi berbulu. Semoga membantu

Atau lakukan apa yang Luke katakan. Jauh lebih mudah.

Jika Anda ingin melakukan penyegaran token, Anda harus mencegat cookie (jika Anda menggunakan cookie) melalui pengaturan server khusus. Saya melakukan ini menggunakan express. Jika tidak, Anda dapat melakukan semuanya di sisi klien menggunakan token JWT. Karena saya melakukan milik saya melalui cookie, saya memiliki 2 kasus penggunaan - menangani permintaan navigasi di sisi klien, dan permintaan halaman di sisi server (kapan saja seseorang mengetikkan url secara manual atau membuka halaman refresh.) Tetapi pada dasarnya mereka adalah aliran yang sama hanya dieksekusi secara berbeda karena satu sisi klien dan satu sisi server. Di sisi server sejak saya menggunakan express, saya baru saja membuat middleware untuk memproses cookie, memecahkan kode JWT di dalamnya dan memeriksa kedaluwarsa. Jika sudah kedaluwarsa, buat permintaan untuk mendapatkan token baru dan terus berikan pengguna yang didekodekan ke redux pada klien. Pada klien saya memiliki pembungkus HOC untuk tautan aman yang terus-menerus memeriksa pengguna, setiap kali Anda menavigasi beberapa tempat di klien. HOC akan mendapatkan cookie atau JWT Anda, (dalam kasus saya JWT saya ada dalam cookie) dan memeriksa apakah itu masih valid dengan cepat. Jika tidak valid, ia akan mencoba untuk mendapatkan JWT/Cookie yang diperbarui, dan melanjutkan, jika tidak, Anda akan logout. Ya lebih rumit, tetapi juga lebih aman. Semoga membantu! Jangan ragu untuk mengajukan pertanyaan jika Anda tertarik - saya butuh beberapa saat untuk mengetahui semuanya. Saya pribadi bertanya-tanya tentang orang-orang yang masuk dengan Github atau FB dll - mungkin ok untuk banyak kasus tetapi dalam beberapa kasus itu tidak profesional. Saya belum melihat bank, perawatan kesehatan, tagihan saya yang saya bayar dll - masuk dengan akun FB saya. Mungkin hanya masalah waktu ;)

Adapun token akses yang menyegarkan;
Saya tidak yakin apakah ini cara yang tepat untuk melakukannya, tetapi token akses saya berumur sangat pendek (sekitar satu menit). Untuk menangani masalah kedaluwarsa token sisi klien, saya telah mengambil pendekatan ini;
Setiap kali halaman dimuat, ia memeriksa apakah token kedaluwarsa, jika demikian, itu menyegarkannya. Namun, jika masih valid, ia memanggil metode yang memeriksa berapa banyak waktu hingga kedaluwarsa, dan menetapkan batas waktu yang akan menyegarkan token akses setelah kedaluwarsa. Dan kemudian mengulangi proses ini selama pengunjung berada di situs.

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

Ini mengembalikan milidetik hingga kedaluwarsa:

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

Umpan balik apa pun untuk pendekatan ini akan sangat diterima

@kunokdev - Saya pikir itu awal yang baik. Saya memindahkan fungsi serupa. Saya harus menghitung waktu yang tersisa ke fungsi yang baru saja mengembalikan boolean tergantung pada apakah itu kedaluwarsa atau tidak dan itu membuat kode saya sedikit lebih mudah dibaca dan sederhana plus saya tidak perlu khawatir tentang mengatur ulang penghitung waktu. Kemudian saya hanya memeriksa apakah pengguna kedaluwarsa atau tidak pada permintaan apa pun yang memerlukan auth. Jika saya memiliki penghitung waktu mundur atau sesuatu seperti itu yang terlihat untuk klien atau debugging maka fungsi Anda akan ideal. Itu 2 sen saya 👍

Bukankah contoh auth/login seharusnya yang paling mendasar? yaitu penyimpanan memori dan tidak ada JWT atau hal-hal aneh lainnya. Biasanya ketika Anda berpikir tentang seseorang "masuk" itu berarti mereka memiliki cookie/sesi aktif.

Saya memiliki sisi klien & server login HOC yang berfungsi. Ia menggunakan JWT dan backend (bisa berupa simpul, Django, apa pun).

Check it out dan umpan balik sangat dihargai

https://github.com/hugotox/AppStarter

Kode yang relevan di sini https://github.com/hugotox/AppStarter/blob/master/src/components/auth/login-required.js

@hugotox Saya suka ide menggunakan Redux store untuk menyimpan data auth tetapi ketika Anda memanggil store.dispatch dari getInitialProps beberapa kali bersiaplah untuk efek samping yang tidak diinginkan, ketika komponen yang dihias akan dirender bahkan jika proses auth belum selesai. Mari kita ambil contoh penggunaan dari kode Anda:

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

Di getInitialProps Anda memanggil verifyToken sebelum verificationOk , jadi MyPage.mapStateToProps akan dipanggil 2 kali (jika mendengarkan store.auth.user) dan pertama kali store.auth.user akan menjadi null bahkan untuk halaman yang memerlukan pengguna yang masuk.

Kemarin saya juga merilis versi WIP pertama dari starter kit bertenaga Next.js sendiri, tetapi saya mulai dengan Docker, Flow dan fast-redux: https://github.com/dogada/microchain

Saya menggunakan gambar Docker khusus untuk server API dan aplikasi web yang dapat berjalan di domain yang berbeda, jadi saya masih mencari solusi yang berfungsi yang memungkinkan untuk masuk ke pengguna nyata tetapi juga mengeluarkan token pembawa OAuth untuk klien seluler misalnya.

@spencersmb sorak-sorai yang luar biasa! Ini cukup banyak persis seperti yang saya lakukan. Dalam hal rendering sisi server untuk URL pada kunjungan pertama (tidak pernah masuk), apakah Anda hanya mencegatnya, melihat bahwa tidak ada cookie dan mengarahkan ulang ke halaman jenis halaman/login.js misalnya?

@james-ff Terima kasih telah memposting itu, meskipun rasanya seperti berteriak ke dalam kehampaan.

Sudah dikatakan di utas ini beberapa kali tetapi semua orang tampaknya masih mengabaikan bahwa mereka tidak boleh menyimpan token sesi di JWT dengan localStorage atau dalam cookie yang dapat diakses JavaScript dan tampaknya berniat mencoba menemukan kembali sesi dan otentikasi dengan cara yang kurang aman (dan itu membutuhkan JS sisi klien). ️

Penulis posting ini menulis dengan baik tentang apa yang salah dengan itu pada tahun 2016 tetapi sayangnya hal-hal tampaknya tidak membaik:

Sayangnya, sepertinya saya telah menemukan batas atas panjang artikel sebelum orang berhenti membaca - banyak komentator di Reddit dan Hacker News terus menyarankan "solusi" yang sama berulang kali, sama sekali mengabaikan bahwa mereka sudah ditangani dan dianggap tidak praktis. dalam artikel itu sendiri.

Baik artikel asli dan diagram tindak lanjut cukup bagus.

@iaincollins JWT dan aplikasi/otentikasi tanpa sesi memiliki kelebihan dan banyak orang/perusahaan (termasuk Google) masih ingin menggunakannya. Setelah membaca kasus terhadap JWTs , saya masih berpikir harus ada dua contoh/pustaka auth resmi berikutnya, satu menggunakan sesi (seperti auth berikutnya) dan satu menggunakan JWT, atau mungkin hanya satu yang memungkinkan menggunakan keduanya. Keuntungan, kerugian, dan peringatan harus dijelaskan dengan jelas untuk masing-masing di halaman tutorial Next.js resmi dan/atau dokumentasi modul di suatu tempat. Sampai seseorang menemukan boilerplate/pustaka yang lebih baik, saya mungkin akan terus menggunakan nextjs-starter dan next-auth, karena mereka adalah yang terbaik yang saya temukan.

Saya hanya dengan santai mengawasi ini, tetapi pengalaman saya dengan universal JS auth adalah menyimpan JWT dalam cookie HttpOnly . Benar-benar tidak ada alasan untuk menggunakan localStorage bila Anda memiliki opsi untuk menggunakan sisi server aplikasi untuk menyimpan cookie. Jika Anda memerlukan akses ke JWT untuk panggilan API lintas-Asal di browser, maka Anda dapat meneruskan JWT dalam skenario tipe __INITIAL_STATE__ (perhatikan kerentanan XSS, tetapi setidaknya Anda tidak "menyimpan" itu sisi klien). Untuk akses asal yang sama, cookie akan diteruskan bolak-balik (dengan asumsi Anda menggunakan withCredentials untuk axios, atau credentials: 'include' untuk mengambil), meniadakan kebutuhan untuk menempatkan JWT di JS sama sekali . Anda dapat menggunakan proxy di sisi server aplikasi untuk mengambil JWT dari cookie HttpOnly , _then_ membuat panggilan API lintas-asal Anda juga. Anda meniadakan panggilan preflight dalam skenario itu juga. Untuk masing-masing milik mereka, tetapi saya pribadi tidak berpikir localStorage diperlukan untuk aplikasi universal.

@bjunc Ya, dari semua opsi di mana JWT harus disimpan (localStorage vs. HttpOnly cookie vs. Redux, atau apa pun yang Anda miliki), saya mungkin salah tetapi saya pikir jawabannya pada dasarnya harus selalu cookie HttpOnly. Hal ini tampaknya telah dinyatakan berkali-kali di banyak blog dan forum. (Saya tidak yakin tentang token penyegaran - mungkin mereka harus disimpan dalam cookie HttpOnly juga?) Saya akan berpikir di mana JWT disimpan harus menjadi masalah yang diselesaikan yang terlepas dari kelebihan/kekurangan JWT lainnya.

Saya mencoba melakukan kurang lebih persis seperti yang Anda katakan dalam proyek saya sebelum saya mulai mengadopsi nextjs-starter dan next-auth. Sudah lama tetapi jika saya ingat dengan benar, saya pikir masalah yang saya temui adalah server Express API saya yang saya autentikasi (yang menggunakan sesi ekspres) tidak menginisialisasi/mengambil sesi dengan benar. Saya akan mendapatkan perilaku aneh di mana sesi akan diinisialisasi beberapa kali. Saya bermaksud untuk melanjutkan melakukan kurang lebih apa yang Anda gambarkan jika saya dapat memperbaikinya. Saya juga akan terus bekerja dengan nextjs-starter dan next-auth, karena sesi menghilangkan banyak masalah lain yang ditimbulkan JWT, seperti cara membatalkan token.

Sekali lagi, contoh resmi (atau contoh) akan sangat membantu. Kata kunci: resmi, artinya penulis Next.js telah mempertimbangkan semua kemungkinan dan memasukkan ide dan praktik terbaik ke dalamnya. Idealnya menggunakan fitur ES6/ES7/ES8 modern seperti janji dan async/menunggu.

@kelleg1 sepertinya masalah Anda terkait dengan spesifikasi pembuatan cookie. Misalnya, Anda dapat secara tidak sengaja membuat beberapa cookie dengan nama yang sama dengan menggunakan pengaturan yang berbeda ( HttpOnly , domain, jalur, kedaluwarsa, dll.); yang dapat membuat efek samping aneh seperti yang Anda gambarkan. Salah satu cara untuk men-debug adalah dengan menggunakan alat dev Application->Cookies. Jika Anda melihat banyak cookie dengan nama yang sama, maka itu mungkin mengarahkan Anda ke arah yang benar.

Bagaimanapun, saya tidak berada di tim inti, jadi saya tidak dapat membantu dengan kontribusi "resmi" (dan sebenarnya, saya menggunakan Nuxt.js, bukan Next.js), tetapi prinsipnya sama. Saya bereksperimen dengan beberapa cara berbeda untuk melakukan ini (menimbang pro/kontra JWT, cookie, CSFR, websocket CSWSH, localStorage, dll.). Saya akhirnya sampai pada kesimpulan bahwa sifat universal Next/Nuxt cocok untuk penggunaan cookie JWT HttpOnly . Mungkin orang lain akan mengambil kesimpulan yang berbeda, tapi saya pribadi tidak setuju dengan "ya Tuhan, jangan gunakan JWT, bukankah Anda membaca artikel yang mengatakan bahwa JWT memberi Anda kanker!?".

@iaincollins maaf untuk membawa ini kembali tetapi setiap tutorial di web menggunakan localStorage untuk menyimpan token dan Anda katakan tidak aman. Jika demikian, di mana kita harus menyimpan token?

KUE! :D
kami menggunakan sesuatu seperti ini:

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

Sedikit kludgy tapi cukup aman karena javascript sisi klien tidak pernah melihat token dan cookie adalah httpOnly, aman, ditandatangani dan dikirim secara otomatis oleh axios atau lainnya...

Hai semua, baru saja membuat contoh autentikasi dengan cookie dan redux. Lihat di sini https://github.com/zeit/next.js/pull/4011

Tunggu jadi di mana masalah ini berakhir? Saya tidak pernah dapat menemukan contoh autentikasi Ekspres di repo resmi.

Saya melihat banyak pembicaraan tentang cookie dan sesi, tetapi bagaimana cara kerjanya untuk aplikasi seluler asli saya ketika perlu menekan API?

Itu bisa dilakukan, tapi itulah gunanya JWT :p

Saya baru saja membaca keseluruhan utas ini secara mendetail dan merasa terdorong untuk meringkas temuan saya.

Tampaknya ada dua proyek awal yang layak dengan modul auth yang solid diperhitungkan:

Karya luar biasa dari @iaincollins dan @nmaro !

Terima kasih @curran :)

Saya mendokumentasikan semua perubahan kode yang saya buat untuk menghilangkan aspek asing dari nextjs-starter dalam Permintaan Tarik ini https://github.com/iaincollins/nextjs-starter/pull/86

Ini mungkin semakin mendekati contoh autentikasi sederhana untuk repositori Next.js.

Saya memiliki persyaratan baru-baru ini untuk menerapkan OAuth dengan Office 365, jadi saya pikir saya akan membagikan contoh yang sangat sederhana yang saya kumpulkan di sini . Itu perlu bekerja (dan sama sekali tidak dikembangkan seperti beberapa contoh di atas) tapi saya pikir itu bisa digeneralisasi pada akhirnya untuk menggunakan berbagai klien OAuth juga. Ini menggunakan beberapa contoh yang sudah ditampilkan di repo contoh Next.js serta utas rute yang dilindungi di sini . Bagaimanapun, saya pikir saya akan membagikan jika seseorang menginginkan contoh cepat tentang bagaimana (mungkin) melakukan ini dengan Microsoft.

Bagi siapa pun yang tertarik dengan otentikasi token JWT sederhana yang berfungsi di sisi klien dan server, saya mendapat bantuan dalam obrolan Spectrum dan saya pikir saya akan membagikannya dengan Anda semua. Setiap umpan balik selalu dihargai.

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

Halo kawan-kawan!
Berikut adalah contoh otentikasi lain dengan next.js yang saya buat beberapa bulan yang lalu, mungkin seseorang akan merasa berguna:

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

Ooth 2.0 keluar dengan dokumen baru dan lebih baik

Ooth adalah sistem manajemen identitas pengguna yang dibuat untuk node.js (dengan mempertimbangkan next.js).

Strategi yang didukung saat ini:

  • Utama: nama pengguna/kata sandi (termasuk verifikasi email, lupa pw dll.), tamu, facebook, google
  • Sekunder: sesi berbasis cookie, JWT

Lihat contoh langsung ini yang menggabungkan semuanya dengan next.js ( kode sumber ).

Banyak contoh auth di sini (dan di folder contoh) mengembalikan sesi pengguna/token/etc dari getInitialProps . Sejauh yang saya pahami, ketika halaman dirender di sisi server, ini berarti info sesi pengguna akan dikirim sebagai bagian dari respons halaman HTML (sebagai bagian dari NEXT_DATA ) ke browser.

Saya melihat dua masalah keamanan dengan pola ini ketika getInitialProps dijalankan di sisi server:
1) Sesi pengguna ditransmisikan melalui jaringan dari server ke browser. Jika ada permintaan seperti itu yang menggunakan http:// dan bukan https:// , token pengguna, dll akan diekspos melalui jaringan dalam teks biasa.

2) Sesi pengguna dikembalikan dari server ke browser sebagai bagian dari halaman HTML (dalam tag skrip NEXT_DATA ). Menempatkan token/dll pengguna langsung di halaman HTML tampaknya berisiko, terutama setelah halaman diurai, dirender oleh browser, dan skrip pihak ketiga lainnya sekarang mungkin sedang berjalan.

Apakah masalah-masalah ini sudah ditangani? Apakah ada mitigasi untuk ancaman ini?

Itu sebabnya saya menggunakan cookie. Lihat contoh saya di sini https://github.com/hugotox/nextjs-starter/blob/master/pages/_app.js

Akhirnya! Di sini Anda dapat menemukan contoh autentikasi next.js yang sepenuhnya di-docker dengan container berikut:

  • selanjutnya.js
  • layanan mikro auth (ooth)
  • api (graphql)
  • penyimpanan sesi (redis)
  • proxy terbalik kecil

Semuanya disatukan dengan docker-compose.

Catatan singkat tentang JWT. JWT memiliki kelebihan karena tidak memiliki kewarganegaraan, bagus untuk seluler, dan bagus jika Anda perlu meneruskan kredensial dari satu domain ke domain lainnya. Kerugian utama adalah mereka mengekspos browser ke XSS. Untuk contoh ini saya memilih solusi berbasis sesi cookie murni. Saya masih berhasil membagi semuanya di layanan mikro berkat proxy terbalik (semua layanan mikro berjalan di bawah domain yang sama) dan ke penyimpanan sesi bersama.

https://github.com/nmaro/staart/tree/master/examples/staart
Contoh langsungnya adalah, seperti biasa: https://staart.nmr.io

Saya pikir bijaksana untuk mengklarifikasi, menggunakan JWT tidak secara intrinsik "mengekspos" Anda ke XSS. Sebaliknya, jika situs Anda memiliki kerentanan XSS (bukan karena JWT itu sendiri), JWT dapat disusupi (bersama dengan informasi lain yang dapat diakses skrip); sedangkan cookie httpOnly tidak akan dapat diakses. Jangankan bahwa Anda dapat menggunakan JWT sebagai nilai cookie httpOnly !

Solusi khusus cookie dapat bekerja dengan baik untuk komunikasi domain yang sama, tetapi jika Anda memiliki API tanpa kepala (mis. example.com memanggil api.example.com ), maka itu bukan solusi yang sebenarnya kecuali Anda ingin browser proxy permintaan dari example.com hingga api.example.com dengan membuat panggilan API Anda ke example.com dan meneruskannya dengan cookie yang ditambahkan ke permintaan (yang dilengkapi dengan serangkaian pro/kontra sendiri) .

Saya pribadi merasa kontra dari JWT sangat berlebihan, dan cukup mudah dikurangi melalui banyak perlindungan yang umum diterapkan. Paling tidak, daftar hitam token yang merujuk pada klaim jti (misalnya UUID Versi4) jika token telah disusupi sebelum kedaluwarsa.

Hei @bjunc ya terima kasih sudah mengklarifikasi. Benar, JWT sendiri tidak memaparkan Anda ke XSS. Mengenai pengamatan Anda yang lain, saya ingin menambahkan bahwa mereka masing-masing memiliki jebakan.

Jangankan bahwa Anda dapat menggunakan JWT sebagai nilai dari cookie httpOnly!

Ya, hanya ingin menambahkan bahwa itu menghilangkan satu keuntungan JWT mentransfer kredensial antar domain.

daftar hitam token

Itu, dan praktik umum lainnya dari token penyegaran menghapus keuntungan lain dari JWT karena benar-benar tidak memiliki kewarganegaraan.

Inilah pemahaman saya tentang situasinya:

  • Jika Anda membutuhkan auth lintas lokasi gunakan JWT <- tetapi jika mungkin hindari karena keamanan
  • Jika Anda perlu mengautentikasi dari klien mana pun yang bukan browser dan tidak memiliki masalah XSS (mis. desktop atau aplikasi seluler) gunakan JWT
  • Jika tidak, gunakan sesi berbasis cookie, karena solusi berbasis JWT akan kurang aman (XSS) atau tidak benar-benar stateless (daftar hitam), atau mengharuskan Anda menggunakan proxy untuk menyimpan semuanya di bawah domain yang sama.

Saya menulis artikel Medium di Next.js Authentication/User account.
Ini adalah tutorial ekstensif dan braindump saya dari hampir dua tahun pengembangan dan pemikiran waktu luang ( komentar pertama saya tentang masalah ini adalah dari Februari 2017).

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

Anda terus menghubungkan JWT dengan menjadi kurang aman. JWT tidak membuat situs Anda menjadi kurang aman. Itu bukan kerentanan XSS dengan sendirinya. Jika Anda memiliki eksploitasi XSS, Anda berada dalam masalah yang sama. Bahkan dengan cookie httpOnly , penyerang mungkin tidak dapat membaca nilai cookie, tetapi itu tidak masalah karena mereka dapat menjalankan kode arbitrer – seperti permintaan XHR yang secara otomatis akan melewati cookie sesi (pada dasarnya bertindak sebagai serangan CSRF). Jika API Anda adalah lintas-domain, dan Anda membuat permintaan browser-ke-server, maka JWT ada di suatu tempat dalam kode (baik itu status awal, atau penyimpanan lokal). Jika Anda menggunakan Axios, Anda mungkin bahkan telah menetapkan default global, di mana penyerang hanya perlu membuat permintaan Axios dan bahkan tidak khawatir tentang auth.

Juga, Anda tidak dapat benar-benar berbicara tentang XSS tanpa juga berbicara tentang CSRF; di mana cookie auth ditargetkan secara khusus. Bahkan dengan pengaturan proxy terbalik, serangan CSRF akan memungkinkan penyerang untuk mengeksekusi permintaan yang diautentikasi terhadap API Anda.

Btw, hanya karena Anda memasukkan JWT ke dalam cookie (misalnya, mengetahui apakah pengguna masuk), tidak berarti Anda dilarang menggunakan nilai cookie (mis. JWT) untuk server lintas domain-ke- Akses server API pada pemuatan halaman (yang juga berfungsi untuk skenario proxy terbalik). Anda juga tidak atau dilarang meneruskan JWT dalam keadaan awal juga untuk permintaan server-ke-API-server. Mereka tidak saling eksklusif.

Selain itu, saya menemukan ide JWT "tanpa kewarganegaraan" terlalu berlebihan dan terbatas dalam aplikasi untuk sebagian besar kasus penggunaan. Contohnya:

  • Izin berbasis sumber daya / dinamis (mis. bukan hanya " can edit Post ", melainkan " can edit Post:1634 ").
  • Bagaimana jika akun pengguna telah diblokir/dihapus?
  • Belum membayar langganan bulanan mereka; yang mencekik fungsionalitas?
  • Token masuk daftar hitam (per di atas)?

Anda tidak memasukkan semua itu ke dalam JWT, yang berarti Anda harus masuk ke lapisan domain (mis. database) untuk mengetahuinya. Anda baru saja memuat sumber daya, jadi sebaiknya letakkan di tempat yang dapat diakses oleh aplikasi lainnya, dan sekarang Anda memiliki status. Saya merasa sangat konyol untuk berpikir bahwa semua yang perlu Anda ketahui tentang subjek akan dimasukkan ke dalam token; sekaligus menjaganya sebagian besar anonim dan ringan. Tanpa menyimpang terlalu banyak, ada argumen untuk permintaan "tanpa kewarganegaraan" dalam komunikasi antar-layanan, tetapi bahkan itu menurut saya tidak praktis (setidaknya karena berkaitan dengan konsep memanggang apa yang perlu Anda ketahui tentang subjek ke dalam JWT) .. .

Strategi otentikasi Ooth tersedia sementara itu (baru dalam huruf tebal):

  • Lokal (Nama pengguna/email/sandi)
  • Facebook
  • Google
  • Tamu
  • pelindung
  • Indonesia
  • Authy (Twilio) - tanpa kata sandi melalui SMS

@jaredpalmer Anda menulis
Seperti php, unit atom Next adalah halaman. Salah satu fitur paling keren adalah ia malas memuat setiap halaman hanya jika diminta. Dengan hanya autentikasi sisi klien tetapi dengan rendering server, js untuk halaman yang dilindungi itu sebenarnya diunduh oleh browser. Di masa mendatang saat Next menambahkan alur kerja server, Anda diharapkan dapat memblokir render dan redirect di server untuk mencegah hal ini sepenuhnya. Ini akan membutuhkan cookie, sesi, dan penyimpanan sesi AFAIK, tetapi itu hanya biaya untuk melakukan aplikasi hibrida seperti ini.

Kami 2 tahun kemudian. Apakah ada alur kerja server untuk mencegah pemuatan js untuk halaman yang dilindungi?
@timneutkens mungkin menempatkan konten yang dilindungi di zona lain?
Bagaimana saya sepenuhnya mencegah akses ke konten yang dilindungi?

@lishine Anda memiliki ServerResponse di getInitialProps halaman Anda - Anda dapat dengan mudah mengarahkan ulang seseorang yang tidak memiliki hak.

Apakah ada contoh auth dengan redux?

Apakah ada contoh auth dengan redux?

Anda dapat mencoba contoh ini yang menggunakan redux, dan periksa apakah itu berhasil untuk Anda ...
Anda dapat menemukannya di suatu tempat di topik ini, tetapi jika Anda tidak dapat menemukannya, ini dia:
https://github.com/alan2207/nextjs-jwt-authentication

Saya pikir ini masalah yang lebih rumit ketika menggunakan hasil panggilan API Sisi Server getInitialProps, karena DOM Virtual menggunakan hasil lama setelah tindakan LOGOUT-LOGIN. Saya sedang memikirkan solusi

_EDITED_
dan inilah jawaban saya dengan redux-observable

|Sisi|Autentikasi|TODO|
|---|---|---|
|Server|true|Ambil data awal (dengan proxy cookie permintaan).|
|Server|false|Tampilkan halaman login, dan ambil data setelah login.|
|Klien|true|Ambil data awal.|
|Klien|false|Tampilkan halaman login, dan ambil data setelah login. (Ini hanya terjadi ketika sesi berakhir di perpindahan halaman ke halaman)|

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

Tampaknya rumit ketika sesuatu yang sederhana akan dilakukan, di sepanjang baris:

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

Contoh ini digabungkan sebagai bagian dari Next.js 8
https://github.com/zeit/next.js/tree/canary/examples/with-cookie-auth

@timneutkens terima kasih atas tautannya.

melihat https://github.com/zeit/next.js/blob/canary/examples/with-cookie-auth/www/utils/auth.js#L26 -L34 ... periksa setelah auth() dipanggil?

Menguji contoh tanpa cookie menyebabkan Profile.getInitialProps() dipanggil, sedangkan saya pikir pengalihan akan terjadi bahkan sebelum mencoba mendapatkan lebih banyak "alat peraga awal" ...

Saya membuat contoh di sini yang memiliki pra-rendering + otentikasi sisi server dengan apollo

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

Harap diingat bahwa pedoman keamanan OWASP merekomendasikan untuk tidak menyimpan token JWT di Penyimpanan Lokal, yaitu "Satu Skrip Lintas Situs dapat digunakan untuk mencuri semua data dalam objek ini, jadi sekali lagi disarankan untuk tidak menyimpan informasi sensitif di penyimpanan lokal."

Inilah Auth0: Tempat Menyimpan Token dan Tom Abbott: Tempat Menyimpan JWT Anda – Penyimpanan Web Cookies vs HTML5 .

Berikut adalah contoh dengan server proxy Nuxt.js + Express.js + backend Django. Di mana server Express digunakan untuk mem-proxy permintaan auth ke backend yang sebenarnya dan menangani perlindungan CSRF saat menggunakan penyimpanan token JWT dalam cookie (menerapkan beberapa batasan pada panjang token / berapa banyak info yang dapat disimpan dalam token JWT): https:/ /github.com/danjac/nuxt-python-secure-example

@timneutkens Saya memerlukan beberapa dokumen tentang cara mengirim token dari cookie ke middleware redux kustom SSR. Saya mendapatkan cookie di dalam _app.js . Tetapi bagaimana saya harus meneruskannya ke customApimiddleware. Di mana saya telah menulis permintaan pengambilan. Terima kasih

Saya menulis artikel Medium di Next.js Authentication/User account.
Ini adalah tutorial ekstensif dan braindump saya dari hampir dua tahun pengembangan dan pemikiran waktu luang ( komentar pertama saya tentang masalah ini adalah dari Februari 2017).

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

Saya pikir ini adalah salah satu tutorial terbaik untuk menangani otentikasi di aplikasi nextj.js. Saya telah melihat hal-hal seperti menyimpan token ke localStorage (XSS), menyimpan token dalam cookie (tanpa menangani CSRF), dan bahkan menyimpan token dalam cookie dari browser (baik XSS dan CSRF rentan).

Saya sangat menyukai solusi Anda dengan proxy terbalik dan berbagi info sesi antara layanan yang berbeda. Saya benar-benar ingin tidak membuat server khusus untuk aplikasi next.js, tetapi saya pikir ini adalah cara paling mudah untuk menangani sesi dan mencegah csrf (dan mungkin menambahkan proxy terbalik). Saya bahkan mungkin akhirnya membuat proyek monolit (baik untuk merender aplikasi dan menangani operasi db dll).

Saya telah melihat bahwa beberapa orang (termasuk ZEIT) membuat API tidak memiliki status dan membiarkan aplikasi next.js menangani sesi tersebut. Ini meneruskan token ke API. Tetapi mengikuti sesi hanya membuat segalanya sedikit lebih ketat dan tidak terlalu rumit.

Akan lebih baik jika memiliki contoh autentikasi lengkap untuk next.js. Dengan hal-hal seperti autentikasi untuk API eksternal, menyimpan sesi di aplikasi next.js, berbagi sesi antar layanan atau memberikan token kepada mereka, dan bahkan mungkin menyegarkan token jika sudah kedaluwarsa. (Banyak orang menulis banyak tentang JWT dan hanya menggunakannya dalam tutorial mereka, tetapi kebanyakan mereka bahkan tidak kedaluwarsa atau bahkan tidak menyegarkannya.)

Bagaimanapun, Anda telah menulis salah satu tutorial terlengkap tentang hal ini. Jadi terima kasih!

Saya sangat berharap akan ada contoh dan dokumentasi yang lebih lengkap dan jelas.

Akan lebih baik jika memiliki contoh autentikasi lengkap untuk next.js. Dengan hal-hal seperti autentikasi untuk API eksternal, menyimpan sesi di aplikasi next.js, berbagi sesi antar layanan atau memberikan token kepada mereka, dan bahkan mungkin menyegarkan token jika sudah kedaluwarsa. (Banyak orang menulis banyak tentang JWT dan hanya menggunakannya dalam tutorial mereka, tetapi kebanyakan mereka bahkan tidak kedaluwarsa atau bahkan tidak menyegarkannya.)

Saya juga bingung harus memilih pendekatan yang mana.
Terima kasih banyak atas tautan ke artikel.
Saat ini, implementasi mana yang telah Anda tetapkan?
Sudahkah Anda menemukan contoh otorisasi komprehensif untuk v9.3+ berikutnya?

Layak untuk dicoba pendekatan berbasis cookie baru Auth0
(Tentu saja ini untuk penyedia identitas tertentu, tetapi pendekatan dapat berguna untuk dilihat)
https://github.com/auth0/nextjs-auth0

  • Sangat keren bahwa Anda dapat "memproksi" permintaan api melalui rute api nextjs (bahkan melalui satu rute dinamis)
  • Maka Anda tidak perlu mengekspos token akses dll ke sisi klien (karena rute api nextjs hanya mengeksekusi sisi server), sisi server dapat memperoleh token akses dll melalui perpustakaan auth0 dan cookie dengan rahasia
  • Kode sisi klien Anda akan memanggil rute api nextjs Anda, dan rute api kemudian akan melakukan permintaan api yang sebenarnya

Ingatlah bahwa mereka mengatakan pendekatan ini "eksperimental" di ReadMe

Layak untuk dicoba pendekatan berbasis cookie baru Auth0
(Tentu saja ini untuk penyedia identitas tertentu, tetapi pendekatan dapat berguna untuk dilihat)
https://github.com/auth0/nextjs-auth0

  • Sangat keren bahwa Anda dapat "memproksi" permintaan api melalui rute api nextjs (bahkan melalui satu rute dinamis)
  • Maka Anda tidak perlu mengekspos token akses dll ke sisi klien (karena rute api nextjs hanya mengeksekusi sisi server), sisi server dapat memperoleh token akses dll melalui perpustakaan auth0 dan cookie dengan rahasia
  • Kode sisi klien Anda akan memanggil rute api nextjs Anda, dan rute api kemudian akan melakukan permintaan api yang sebenarnya

Ingatlah bahwa mereka mengatakan pendekatan ini "eksperimental" di ReadMe

Artikel ini sangat membantu dan mencakup banyak arsitektur yang berbeda.
https://auth0.com/blog/ultimate-guide-nextjs-authentication-auth0/

Menggunakan rute API sebagai proxy, login/logout melalui rute API, mendapatkan token dari API, menyetelnya sebagai cookie HttpOnly adalah pendekatan yang solid menurut saya.
Satu kekhawatiran mungkin CSRF, tetapi Anda dapat dengan mudah membuat beberapa solusi dengan paket csrf npm (bukan csurf , tetapi itu mungkin berhasil juga).

@onderonur , terima kasih untuk artikel auth0.
yaitu, saat ini ada contoh implementasi yang dapat diandalkan atau setidaknya minimal pada jwt murni dengan next.js?
Saya tidak ingin membuat lapisan lanjutan dengan cookie dan mengaturnya. Dalam aplikasi csr, kami cukup menyimpan token di penyimpanan lokal dan mengirimkannya bersama dengan permintaan.

@onderonur , terima kasih untuk artikel auth0.
yaitu, saat ini ada contoh implementasi yang dapat diandalkan atau setidaknya minimal pada jwt murni dengan next.js?
Saya tidak ingin membuat lapisan lanjutan dengan cookie dan mengaturnya. Dalam aplikasi csr, kami cukup menyimpan token di penyimpanan lokal dan mengirimkannya bersama dengan permintaan.

Saya telah menggunakan metode ini untuk salah satu repo saya tetapi masih dalam konsep, jadi pastikan untuk mengujinya sendiri :)
https://github.com/onderonur/post-gallery
Sebenarnya "lapisan cookie" bukanlah hal yang canggih. Panggil saja titik akhir login API Anda melalui rute API /api/login dan jika permintaan berhasil, setel token dalam cookie httpOnly .
Anda dapat memeriksa repo saya untuk implementasi yang sama persis.

Salah satu opsi lainnya adalah (jika Anda ingin memiliki alur yang hampir sama dengan menyetel token di penyimpanan lokal), Anda dapat menggunakan paket js-cookie npm, panggil titik akhir login Anda dengan permintaan sisi klien, akhiri jika kembali token, atur dalam cookie. Dan ketika Anda membuat permintaan (melalui pencegat axios dll) membaca nilai cookie dan meneruskannya ke API Anda sebagai header permintaan. Saya telah melihat banyak (dan bahkan beberapa aplikasi populer) menggunakan pendekatan ini. Tapi ini sedikit tidak aman. Karena Anda tidak dapat mengatur cookie httpOnly di browser. Jadi, JavaScript akan dapat membaca cookie token Anda. Dengan demikian, akan ada kerentanan XSS.

Menghargai ini adalah utas lama (dan topik yang sudah berjalan lama secara umum) tetapi bagi mereka yang mencari referensi atau contoh tambahan, kami telah mengambil pekerjaan di NextAuth.js v2 baru-baru ini. Saya menyebutkannya bukan sebagai plug – ini adalah proyek open source dan banyak orang telah membantunya – tetapi ini sangat mudah digunakan dan kode serta pendekatannya mungkin berguna sebagai referensi untuk orang-orang.

Untuk beberapa latar belakang, seperti NextAuth v1, ia menggunakan cookie yang ditandatangani, diawali dan hanya HTTP, menghindari perangkap keamanan umum menggunakan token sisi klien.

NextAuth.js v2 mendukung masuk dengan Apple, Google, Facebook, Twitter, GitHub, Auth0, Okta, Slack, Discord, dan penyedia OAuth lainnya (mendukung 1.x dan 2.x). Anda dapat menggunakannya dengan MySQL, MariaDB, Postgres, MongoDB - atau tanpa database semua (hanya Token Web OAuth dan JSON untuk solusi tanpa server 100%).

Penggunaannya sangat sederhana, ada metode statis Universal yang disebut session() dan React Hook bernama useSession() yang dapat Anda gunakan di sisi klien komponen:

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

Itu dibangun untuk Next.js 9.x dan Tanpa Server, dan tidak memiliki ketergantungan seperti Express atau PassportJS. Ini termasuk penyedia autentikasi yang dapat Anda gunakan di _app.js untuk secara otomatis menambahkan status autentikasi ke semua halaman; ini berfungsi untuk rendering sisi klien dan server.

Untuk info lebih lanjut, lihat next-auth.js.org atau lihat next-auth@beta di NPM

Ini masih dalam proses - kami masih menyempurnakan dokumentasi dan model acara - dengan target tanggal rilis ~awal~ pertengahan Juni.

Menghargai ini adalah utas lama (dan topik yang sudah berjalan lama secara umum) tetapi bagi mereka yang mencari referensi atau contoh tambahan, kami telah mengambil pekerjaan di NextAuth.js v2 baru-baru ini. Saya menyebutkannya bukan sebagai plug – ini adalah proyek open source dan banyak orang telah membantunya – tetapi ini sangat mudah digunakan dan kode serta pendekatannya mungkin berguna sebagai referensi untuk orang-orang.

Untuk beberapa latar belakang, seperti NextAuth v1, ia menggunakan cookie yang ditandatangani, diawali dan hanya HTTP, menghindari perangkap keamanan umum menggunakan token sisi klien.

NextAuth.js v2 mendukung masuk dengan Apple, Google, Facebook, Twitter, GitHub, Auth0, Okta, Slack, Discord, dan penyedia OAuth lainnya (mendukung 1.x dan 2.x). Anda dapat menggunakannya dengan MySQL, MariaDB, Postgres, MongoDB - atau tanpa database semua (hanya Token Web OAuth dan JSON untuk solusi tanpa server 100%).

Penggunaannya sangat sederhana, ada metode statis Universal yang disebut session() dan React Hook bernama useSession() yang dapat Anda gunakan di sisi klien komponen:

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

Itu dibangun untuk Next.js 9.x dan Tanpa Server, dan tidak memiliki ketergantungan seperti Express atau PassportJS. Ini termasuk penyedia autentikasi yang dapat Anda gunakan di _app.js untuk secara otomatis menambahkan status autentikasi ke semua halaman; ini berfungsi untuk rendering sisi klien dan server.

Untuk info lebih lanjut, lihat next-auth.js.org atau lihat next-auth@beta di NPM

Ini masih dalam proses - kami masih menyempurnakan dokumentasi dan model acara - dengan target tanggal rilis ~awal~ pertengahan Juni.

Kerja bagus ini!
Bisakah ini digunakan di sisi klien saja? Misalnya, saya memiliki aplikasi Rails API - dan menggunakan JS berikutnya untuk sisi klien.

Apakah halaman ini membantu?
0 / 5 - 0 peringkat