Next.js: إضافة مثال تسجيل الدخول / المصادقة

تم إنشاؤها على ٢٩ أكتوبر ٢٠١٦  ·  208تعليقات  ·  مصدر: vercel/next.js

مع:

  • مساعد المصادقة القابل لإعادة الاستخدام عبر الصفحات
  • مزامنة الجلسة بين علامات التبويب
  • خلفية بريد إلكتروني بسيطة بدون كلمة مرور مستضافة على now.sh

أعتقد أن هذا سيكون مفيدًا للغاية لكثير من الوافدين الجدد.

التعليق الأكثر فائدة

لذلك لدي المصادقة تعمل بسلاسة. كما ذكرنا في مكان آخر ، إنه جانب العميل فقط ، والذي يمثل في النهاية نصف المعركة فقط.

"آمن جدًا"

مثل php ، فإن الوحدة الذرية لـ Next هي الصفحة. واحدة من أروع الميزات هي أنه لا يقوم بتحميل كل صفحة إلا عند الطلب. باستخدام المصادقة من جانب العميل فقط ولكن مع عرض الخادم ، يتم في الواقع تنزيل js لتلك الصفحة المحمية بواسطة المتصفح. في المستقبل ، عندما يضيف Next مهام سير عمل الخادم ، نأمل أن تتمكن من حظر العرض وإعادة التوجيه على الخادم لمنع ذلك تمامًا. سيتطلب ذلك ملفات تعريف الارتباط ، والجلسات ، ومخازن جلسات AFAIK ، ولكن هذا هو مجرد تكلفة القيام بتطبيقات مختلطة مثل هذه.

مثال المصادقة

افترض أن لديك واجهة برمجة تطبيقات مؤمنة بواسطة JWT مع نقطتي نهاية مهمتين: /token و /me . يقبل /token بيانات اعتماد البريد الإلكتروني / كلمة المرور ويعيد JWT موقعًا ( id_token ) بينما يعرض /me معلومات الملف الشخصي المتعلقة بمستخدم JWT المصادق عليه. لقد قمت بتكييف AuthService.js التالي من قفل Auth0 (إزالة باعث الحدث ، على الرغم من أن هذه ليست أسوأ فكرة). فهو يستخرج تقريبًا كل معالجة رمز JWT بحيث يمكن استخدامه في صفحة تسجيل الدخول وأيضًا في مكون ترتيب أعلى (المزيد حول ذلك لاحقًا).

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

التالي هو المكوّن الإضافي (HOC) لجعل حماية الصفحات أكثر بساطة. لمنع حدوث وميض غير مرغوب فيه للمعلومات الحساسة ، ستعرض الصفحة الخادم Loading... عند أول عرض أثناء بدء تشغيل / قراءة الرمز المميز من localStorage. هذا يعني أن الصفحات المحمية لن يتم تحسين محركات البحث (SEO) ، وهو أمر مقبول على الأرجح حتى الآن ، ولكنه بالتأكيد ليس الأمثل.

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

لا يمكن لصفحة تسجيل الدخول استخدام HOC كما هي الآن ، لأن تسجيل الدخول يجب أن يكون عامًا. لذلك فهي تقوم فقط بعمل نسخة من AuthService مباشرة. ستفعل شيئًا مشابهًا لصفحة تسجيل أيضًا.

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

مستوحاة من تفاعل Airbnb مع الأنماط ، بدأت أيضًا العمل على next-with-auth lib والذي سيكون دالة تُرجع HOC ليتم استخدامه على الصفحات. لقد لعبت أيضًا بدمج AuthService و HOC هذا. قد يكون أحد الحلول هو جعل هذا المكوّن من HOC يقبل وظيفة مستوى الإذن كوسيطة بالإضافة إلى المكون ، مثل اتصال redux. بغض النظر ، في رأيي ، يمكنك استخدام next-with-auth مثل هذا:

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

يبدو أن القيام بكل هذا مع Redux معقدًا بشكل غير ضروري ، ولكن في الأساس يمكنك اتباع مثال wiki ، ولكن يمكنك نقل AuthService إلى الإجراءات (تسجيل الدخول والخروج) والحصول على User Reducer. لا يمكنك استدعاء هذه الإجراءات إلا على العميل ، نظرًا لعدم وجود تخزين محلي على الخادم ، لذلك تحتاج إلى التحقق من ذلك في إجراءاتك. في النهاية ، يتم وضع متجر redux على window على أي حال. لذلك يمكنك تخزين المستخدم مؤقتًا بشكل جيد على window بنفسك بدلاً من استخدام السياق. إذا كنت لا تريد إعادة التشغيل ، فيمكنك أيضًا تجربة react-broadcast .

أخيرًا ، بافتراض شحن next/server وفقًا لـ # 25. next-with-auth بتجريد عناصر التخزين المحلي المعقدة مقابل ملفات تعريف الارتباط بعيدًا عن المطور باستخدام البرامج الوسيطة + المكوّن الإضافي. يمكنه أيضًا التعامل مع تحديث الرمز المميز أيضًا.

ال 208 كومينتر

اقتراح: استخدم Redux و JWT لإنجاز المثال

أنا أعمل على مثال لهذا. أواجه حاليًا مشكلات في تشغيل مكون componentWillReceiveProps على مكوّن عالي المستوى (حيث أخطط للتحقق مما إذا كان المستخدم قد تمت مصادقته وإعادة توجيهه إلى صفحة تسجيل الدخول إذا لم يكن كذلك)

لذلك لدي المصادقة تعمل بسلاسة. كما ذكرنا في مكان آخر ، إنه جانب العميل فقط ، والذي يمثل في النهاية نصف المعركة فقط.

"آمن جدًا"

مثل php ، فإن الوحدة الذرية لـ Next هي الصفحة. واحدة من أروع الميزات هي أنه لا يقوم بتحميل كل صفحة إلا عند الطلب. باستخدام المصادقة من جانب العميل فقط ولكن مع عرض الخادم ، يتم في الواقع تنزيل js لتلك الصفحة المحمية بواسطة المتصفح. في المستقبل ، عندما يضيف Next مهام سير عمل الخادم ، نأمل أن تتمكن من حظر العرض وإعادة التوجيه على الخادم لمنع ذلك تمامًا. سيتطلب ذلك ملفات تعريف الارتباط ، والجلسات ، ومخازن جلسات AFAIK ، ولكن هذا هو مجرد تكلفة القيام بتطبيقات مختلطة مثل هذه.

مثال المصادقة

افترض أن لديك واجهة برمجة تطبيقات مؤمنة بواسطة JWT مع نقطتي نهاية مهمتين: /token و /me . يقبل /token بيانات اعتماد البريد الإلكتروني / كلمة المرور ويعيد JWT موقعًا ( id_token ) بينما يعرض /me معلومات الملف الشخصي المتعلقة بمستخدم JWT المصادق عليه. لقد قمت بتكييف AuthService.js التالي من قفل Auth0 (إزالة باعث الحدث ، على الرغم من أن هذه ليست أسوأ فكرة). فهو يستخرج تقريبًا كل معالجة رمز JWT بحيث يمكن استخدامه في صفحة تسجيل الدخول وأيضًا في مكون ترتيب أعلى (المزيد حول ذلك لاحقًا).

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

التالي هو المكوّن الإضافي (HOC) لجعل حماية الصفحات أكثر بساطة. لمنع حدوث وميض غير مرغوب فيه للمعلومات الحساسة ، ستعرض الصفحة الخادم Loading... عند أول عرض أثناء بدء تشغيل / قراءة الرمز المميز من localStorage. هذا يعني أن الصفحات المحمية لن يتم تحسين محركات البحث (SEO) ، وهو أمر مقبول على الأرجح حتى الآن ، ولكنه بالتأكيد ليس الأمثل.

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

لا يمكن لصفحة تسجيل الدخول استخدام HOC كما هي الآن ، لأن تسجيل الدخول يجب أن يكون عامًا. لذلك فهي تقوم فقط بعمل نسخة من AuthService مباشرة. ستفعل شيئًا مشابهًا لصفحة تسجيل أيضًا.

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

مستوحاة من تفاعل Airbnb مع الأنماط ، بدأت أيضًا العمل على next-with-auth lib والذي سيكون دالة تُرجع HOC ليتم استخدامه على الصفحات. لقد لعبت أيضًا بدمج AuthService و HOC هذا. قد يكون أحد الحلول هو جعل هذا المكوّن من HOC يقبل وظيفة مستوى الإذن كوسيطة بالإضافة إلى المكون ، مثل اتصال redux. بغض النظر ، في رأيي ، يمكنك استخدام next-with-auth مثل هذا:

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

يبدو أن القيام بكل هذا مع Redux معقدًا بشكل غير ضروري ، ولكن في الأساس يمكنك اتباع مثال wiki ، ولكن يمكنك نقل AuthService إلى الإجراءات (تسجيل الدخول والخروج) والحصول على User Reducer. لا يمكنك استدعاء هذه الإجراءات إلا على العميل ، نظرًا لعدم وجود تخزين محلي على الخادم ، لذلك تحتاج إلى التحقق من ذلك في إجراءاتك. في النهاية ، يتم وضع متجر redux على window على أي حال. لذلك يمكنك تخزين المستخدم مؤقتًا بشكل جيد على window بنفسك بدلاً من استخدام السياق. إذا كنت لا تريد إعادة التشغيل ، فيمكنك أيضًا تجربة react-broadcast .

أخيرًا ، بافتراض شحن next/server وفقًا لـ # 25. next-with-auth بتجريد عناصر التخزين المحلي المعقدة مقابل ملفات تعريف الارتباط بعيدًا عن المطور باستخدام البرامج الوسيطة + المكوّن الإضافي. يمكنه أيضًا التعامل مع تحديث الرمز المميز أيضًا.

متحمس لتجربة هذا! شكرا على التنفيذ المجرد :)

jaredpalmer أنا أعمل على شيء مشابه. كيف يعمل AuthService عند عرض أحد المكونات من جانب الخادم؟ سيحتاج الخادم إلى الوصول إلى JWT ولكن لا يمكنه قراءته من التخزين المحلي.

amccloud لا. هذه هي القضية برمتها. يعرض HOC <div>Loading..</div> على المسارات المحمية ويجب أن يقرأ الرمز المميز ويقرر ما إذا كان سيتم إعادة التوجيه في componentDidMount . لكي يعمل بالطريقة التي تريدها ويعرض جانب الخادم ، يحتاج Next # 25 ، أو على الأقل القدرة على تعيين ملف تعريف ارتباط بقيمة JWT AFAIK.

لقد استخدمت ملف تعريف الارتباط js لتعيين ملف تعريف ارتباط ، لكنه نوع من الاختراق ..
الشيء هو: إذا لم ترسل ملف تعريف ارتباط ، فستفقد جميع مزايا nextjs والعرض الجانبي للخادم في المسارات المصدق عليها

jaredpalmer هذا شيء عظيم! شكرا لهذا الجهد. سأحاول إنهاء تطبيق مثالك (أو مساعدتك في القيام بذلك إذا أردت) في الأيام التالية

يو! لقد نشرت مثالًا باستخدام nextjs و auth0 هنا: https://github.com/luisrudge/next.js-auth0
إنه يحتوي على مفهوم التخطيط الرئيسي وأيضًا "الصفحات الآمنة" التي يتم تحميلها فقط عند مصادقة المستخدم.
اسمحوا لي أن أعرف ما هو رأيك 🎉

تضمين التغريدة أنا أستنسخ وأقوم ببعض التغييرات ولكن يبدو رائعًا

رائع! ما رأيك أنه مفقود؟ ما هي التغييرات التي تفكر فيها؟

في الأحد ، 6 تشرين الثاني (نوفمبر) 2016 الساعة 1:12 مساءً -0200 ، كتب "Dan Zajdband" < [email protected] [email protected] >:

luisr udgehttps: //github.com/luisrudge مذهل. أنا أستنسخ وأقوم ببعض التغييرات ولكن يبدو رائعًا

أنت تتلقى هذا لأنه تم ذكرك.
قم بالرد على هذه الرسالة الإلكترونية مباشرةً ، أو قم tHubhttps: //github.com/zeit/next.js/issues/153#issuecomment -258687108 ، أو كتم قراءة ال

1) استخدام standard للفحص (لذا فهو متوافق مع كل شيء نقوم ببنائه بعد ذلك)
2) إضافة دعم متعدد علامات التبويب المطلوب منrauchg
3) يمكن تبسيط جزء css

سأرسل لك العلاقات العامة :)

ماذا تقصد بدعم متعدد علامات التبويب؟

في الأحد ، 6 تشرين الثاني (نوفمبر) 2016 الساعة 1:16 مساءً -0200 ، كتب "Dan Zajdband" < [email protected] [email protected] >:

1) استخدام معيار الفحص (لذلك فهو متوافق مع كل ما نقوم ببنائه بعد ذلك)
2) إضافة دعم متعدد علامات التبويب المطلوب بواسطة rauchghttps : //github.com/rauchg
3) يمكن تبسيط جزء css

سأرسل لك العلاقات العامة :)

أنت تتلقى هذا لأنه تم ذكرك.
قم بالرد على هذه الرسالة الإلكترونية مباشرةً ، أو قم tHubhttps: //github.com/zeit/next.js/issues/153#issuecomment -258687373 ، أو كتم القراءة التالية: //github.com/notifications/unsubscribe-auth/ AA5cE1A6jq4KZc9_ynukTCI4mU-rdsNaks5q7e81gaJpZM4KkJmi.

لديك علامتا تبويب مفتوحتان ، تسجيل الخروج على 1 ، تسجيل الخروج تلقائيًا على الأخرى

آه. هذا رائع جدًا!

في الأحد ، 6 تشرين الثاني (نوفمبر) 2016 الساعة 1:21 مساءً -0200 ، كتب "Dan Zajdband" < [email protected] [email protected] >:

لديك علامتا تبويب مفتوحتان ، تسجيل الخروج على 1 ، تسجيل الخروج تلقائيًا على الآخرين

أنت تتلقى هذا لأنه تم ذكرك.
قم بالرد على هذه الرسالة الإلكترونية مباشرةً ، أو قم tHubhttps: //github.com/zeit/next.js/issues/153#issuecomment -258687707 ، أو كتم القراءة التالية: //github.com/notifications/unsubscribe-auth/ AA5cE9e2DA4_GgNQIVTMp0hx74G-6RmUks5q7fBfgaJpZM4KkJmi.

مرحبًا luisrudge ، لقد أرسلت لك العلاقات العامة مع التغييرات https://github.com/luisrudge/next.js-auth0/pull/2

شكرا جزيلا لفعل هذا <3

راجع للشغل هذه هي النتيجة:

2016-11-06 11 14 31

تضمين التغريدة إذا كنت تريد استخدامه بدون Auth0 ، فيبدو أنك تحتاج فقط إلى تغيير الملفات الموجودة في ./utils dir ، وربما حتى lock.js . سأحاول ذلك قريبًا. بالمناسبة ، تبدو علامة التبويب المتعددة رائعة 💯

ugiacoman لقد بدأت في تنفيذ خادم صغير باستخدام passwordless.net ، أخبرني إذا كنت تريد الحصول على الكود الخاص بي كنقطة بداية

تضمين التغريدة كنت سأفعل شيئًا مشابهًا مع Twitter Fabric's Digits.

impronuncible أقترح عدم استخدام password less.net ، بدلاً من ذلك يمكنك فقط استخدام جواز السفر المحلي ، وإرسال رابط فقط إلى المستخدمين مع بريدهم الإلكتروني والرمز المميز في سلسلة الاستعلام.

شكرا @ impronunciable ❤️

ugiacoman نعم ، من السهل جدًا إزالة تبعية auth0. لقد استخدمته لأنني لم أرغب في الحصول على واجهة برمجة تطبيقات منفصلة للتعامل مع المصادقة

jaredpalmer على حد علمي ، سيكون الحصول على رقم 25 أمرًا رائعًا ولكنه لا يمنعه؟ أعني أن لدينا حق الوصول إلى جانب الخادم req في getInitialProps لذا لا شيء يمنع تطبيق cookie-parser عليه؟ المصادقة من جانب الخادم وإدارة الجلسة هي كلها أشياء جديدة بالنسبة لي 😬

راجع للشغل لا يمكن استخدام localStorage من جانب الخادم ، فهل ملفات تعريف الارتباط هي الطريقة الوحيدة للحصول على جلسات من جانب الخادم؟ لدي ذكرى غامضة أنه قد لا يكون أسلم؟ لكن هل هناك أي خيار آخر؟

تضمين التغريدة

يمكن أن يكون نهج ملفات تعريف الارتباط آمنًا جدًا إذا تم إجراؤه بشكل صحيح. القيام بما يلي أمر تافه إلى حد ما:

  • استخدم علامة httpOnly (تمنع وصول JavaScript إلى ملف تعريف الارتباط)
  • استخدم علامة آمنة (قم فقط بتعيين ملف تعريف الارتباط لطلبات https)
  • ملفات تعريف الارتباط الموقعة (التحقق من مصدر ملف تعريف الارتباط)

هناك أيضًا ميزة كبيرة جدًا في زمن الانتقال عندما يمكنك الوصول إلى معلومات المصادقة مباشرة على الخادم.

يجب أن ننقل هذا المثال إلى examples/ سأرى ما يمكنني التوصل إليه

لقد تمكنت من استخدام react-cookie لملفات تعريف الارتباط المتشابهة عن طريق تغليف nextjs في خادم سريع مخصص بالطريقة التالية:

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

هذا يسمح لي بتقديم طلب مصدق من جانب الخادم. لا يعالج هذا أيًا من المشكلات الأصلية ولكنه حل مشكلة مشاركة الحالة بين العميل والخادم.

من وجهة نظر شخص يتعلم الكثير من هذه الأشياء. أعتقد أنه سيكون من الأفضل إذا كانت الأمثلة لا تعتمد على خدمات الجهات الخارجية مثل auth0. سيكون من المفيد أكثر للقادمين الجدد أن يروا مثالًا مجردة أكثر مع نماذج تسجيل الدخول / الاشتراك واستخدام Redux و JWT.

المثال الذي نخطط لـ _bundle_ سيعتمد على واجهات برمجة تطبيقات خادم Node.js مفتوحة المصدر

لقد أضفت مثالاً للمصادقة المستندة إلى البريد الإلكتروني إلى مثال لمشروع بداية على https://github.com/iaincollins/nextjs-starter

يحتوي على دعم الجلسة (مع Express Sessions على الواجهة الخلفية وجلسة المستعرض API لتخزينها مؤقتًا على الواجهة الأمامية) ، http فقط ملفات تعريف الارتباط ، إسقاط CSRF ، يستخدم SMTP المدمج لإرسال رسائل البريد الإلكتروني ، وهو سهل لتغيير الواجهة الخلفية الافتراضية إلى SQL Lite . لا يوجد تكوين مطلوب لتشغيله.

يحتوي المشروع أيضًا على صفحات تخطيط ومسارات مخصصة ويتضمن مثال الساعة من الويكي. إنه ليس أفضل مثال على المصادقة ولكنه قد يكون مفيدًا لمن يبحثون عن سهولة البدء بمشروع بسيط يسهل فهمه والتلاعب به.

أتفق مع iamjacks في أن مثالاً مع JWT يبدو فكرة جيدة.

يسعدني تحسين معالجة الأخطاء وإضافة ميزات مثل صفحة ملف تعريف بسيطة يمكن للمستخدمين تحريرها ، وتكامل جواز السفر مع أمثلة لـ oAuth لـ Facebook و Google و Twitter إذا كان ذلك سيكون مفيدًا للأشخاص. إذا كان لدى الأشخاص أفكار جيدة حول طرق أفضل لنشر / كشف معلومات الجلسة للمكونات التي أنا مهتم بها للغاية.

Example screenshot showing what to expect

هذا أمر لا يصدق جميلة iaincollins. سنعرض هذا في ملاحظات الإصدار لـ 2.0 بالتأكيد :)

rauchg شكرا لك! :)

أعتقد أنني يجب أن أضيف صراحةً أنه في هذا المثال ، تكون الجلسات قائمة على كل من العميل والخادم - أي العمل مع وبدون JavaScript (وعلى أنظمة بدون جلسة تخزين) ، ويتم مشاركة الجلسة نفسها عبر كليهما.

إن تحقيق ذلك يحصل على القليل من الشهرة في مكون الجلسة ، والذي يتعمق في المتغيرات بأسماء مثل req.connection._httpMessage.locals._csrf للحصول على رمز CSRF المميز من رؤوس الخادم - حيث يتم تمرير الكائن "req" إلى الصفحات في getInitialProps () يختلف الشيء المثير للفضول عن الكائن req المعروض في Express حيث يمكنني الوصول إليه عادةً من خلال req.locals._csrf (ومع ذلك ، فإن req.session هو نفسه في كليهما).

localStorage غير آمن. ما هي أفضل طريقة لجعله أكثر أمانًا. يمكن لأي شخص سرقة بيانات التخزين المحلي ووضعها مرة أخرى في متصفحه ويمكن تسجيله كمستخدم ضحية !!

Chathula هذا ليس صحيحا. هذه الحجة خاطئة.
إذا كان لدى أي شخص حق الوصول إلى المتصفح فعليًا ، فيمكنه فعل أي شيء.

هذا صحيح بالنسبة لملفات تعريف الارتباط أيضًا.

يعد استخدام localStorage للمصادقة آمنًا لأننا قد نتخلص من مشكلات ثانية تتعلق بملفات تعريف الارتباط.
ولكن من ناحية أخرى ، فإنه يؤثر على SSR.

arunoda لقد

إذا سرق شخص ما بيانات التخزين المحلية.

كيف؟ في الأساس يجب أن يكون لديه حق الوصول إلى المتصفح فعليًا. ثم يمكن لهذا الشخص أن يفعل أي شيء.
لذا ، لا ينبغي أن نقلق بشأن ذلك.

ألا يمكننا استخدام أي تشفير لجعله أكثر أمانًا؟

Chathula هذا

Chathula يمكن أن تبدأ موضوعًا جديدًا في مشروع البداية أعلاه.

تضمين التغريدة شكرا لك على المعلومات! :د

Chathula يسعدني أن أناقشها أكثر في قضية المشروع

أرغب في تصحيح أي سوء فهم ، لتجنب انزعاج الناس دون داع.

واجهة برمجة تطبيقات Web Storage (أي localStorage و sessionStorage) - مثل ملفات تعريف الارتباط بدون تعيين http فقط - مقيدة عبر نفس سياسة الأصل (البروتوكول ، اسم المضيف ، رقم المنفذ) ، ليس صحيحًا أن "أي شخص يمكنه سرقة [هو]" ؛ ولكن نعم ، إذا كان شخص ما قادرًا على تنفيذ JavaScript عشوائي على موقعك عبر ثغرة أمنية في برمجة المواقع المتقاطعة في تطبيقك ، فيمكنه الوصول إلى المتجر أيضًا ، لذلك يجب ألا تخزن معرّفات الجلسة فيه.

هذا هو السبب في أنك سترى أن رمز الجلسة نفسه لا يتم تخزينه في localStorage / sessionStorage ولا يمكن قراءته في JavaScript ، ويتم نقله فقط عبر ملف تعريف ارتباط HTTP فقط (وهذا هو السبب في أن فئة الجلسة تستخدم XMLHttpRequest () بدلاً من fetch () - كما هو موضح في وثائق الفصل).

هذا يعني أنه حتى إذا كان شخص ما قادرًا على استغلال ثغرة أمنية في البرمجة عبر الموقع في تطبيقك وتنفيذ JavaScript تعسفي في تطبيق الويب الخاص بك ، فلا يزال يتعذر عليه قراءة رمز جلسة مستخدم أو تصديره.

ربما يكون هذا تمييزًا مهمًا يستحق العمل في التوثيق.

ملاحظة: التشفير الإضافي لبيانات المستخدم ليس مفيدًا هنا لأن التطبيق يحتاج دائمًا إلى أن يكون قادرًا على قراءة البيانات حتى يمكن عرضها (لذلك ستحتاج أيضًا إلى تخزين مفتاح وصف في التطبيق ، مما يؤدي إلى تشفير بيانات المستخدم موضع نقاش إلى حد ما).

_UPDATE: في الأسبوع أو الأسبوعين الماضيين ، تمت إعادة هيكلة المثال لاستخدام localStorage عبر sessionStorage حيث أن sessionStorage لا تتم مشاركتها بين علامات التبويب ومشاركة البيانات غير الحساسة بهذه الطريقة تقلل من عدد عمليات التحقق من المصادقة غير الضرورية وتحافظ على حالة الجلسة متسقة بين علامات التبويب.

ربما يكون مفيدًا لبعض الأشخاص الذين صنعت نموذج التطبيق هذا أثناء التجربة:

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

بدعم من هذه اللعبة الخلفية:

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

تم النشر هنا:

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

الخلفية هنا:

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

@ إمكانيات شكرا مايك! بالإضافة إلى الكشف عن خدمة مصغرة منفصلة تعرض طريقة لطيفة للتعامل مع الصفحات الآمنة التي كنت أعتقد أنها قد تكون عملية جيدة وقد تستلهم منها. لدي بعض الأفكار التي سأطرحها في الريبو التالي. js-with-auth.

بعد إعطاء المزيد من التفكير ، ربما لن أعتبر جهودي أعلاه كمثال رائع. من المحتمل أن أتغير إلى تقديم نمط الويب 1.0 للاشتراك / تسجيل الدخول بالكامل حتى نتمكن من إنشاء ملف تعريف ارتباط HTTP فقط على الخادم (مما يلغي إمكانية الوصول إلى JWT عبر XSS) ثم إرفاق كائن المستخدم بـ req بدلاً من ذلك من الرمز بأكمله. هذا يترك احتمال وجود ثغرات أمنية في CSRF ولكني أعتقد أن هذا أكثر وضوحًا للتخفيف من XSS (لا؟). أحد الآثار الجانبية الرائعة لهذا هو أن تطبيق العميل يمكن أن يستخدم تدفقًا متطابقًا تقريبًا عند تسجيل الدخول عبر خدمة القسم.

أرى أيضًا أنه يمكنني تجنب "البرامج الوسيطة" (وبالتالي أحتاج إلى خادم مخصص) من خلال تحليل ملف تعريف الارتباط في Page HoC's getInitialProps .

possabilities بما أن الصفحة "السرية" هي مجرد صفحة ومجمعة في حزمة الويب ، ألن يتم تقديمها إلى المتصفح إذا انتقلت إلى / سرًا؟

نعم ، أفترض أنه يجب أن يكون سلكيًا لإجراء إعادة توجيه من جانب الخادم.

راجع للشغل ، لقد تم تشتيت انتباهي إلى مشروعي الأولي لتسجيل الدخول باستخدام جيثب. يتشابه التدفق مع مزيد من الاهتمام بالأمان (أي عدم الكشف عن أي سر على العميل لتجنب الكشف عن رمز oauth عبر XSS). إنه مقيد في تطبيق مناسب ولكن إذا كان هناك أي اهتمام يمكنني تقسيمه إلى شيء يمكن أن يكون مفيدًا لتدفق oauth بشكل عام.

@ الاحتمالات أعتقد أنها ستكون مساعدة رائعة ، إذا كان يمكن أن يكون هناك

sedubois لدي علاقات عامة لذلك باستخدام passwordless.net https://github.com/zeit/next.js/pull/646 لكننا سننقل خادم المصادقة إلى مكان آخر

ماذا عن استخدام الرسم البياني؟

يعطي Apollo مثالاً على مصادقة Graphql:

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

نحن هنا نصادق على طلب رسم بياني ، ولكن يمكن تكييفه لحالتنا.

بالإضافة إلى Graphql يمكنها تجريد التنفيذ والمنطق. يمكن استخدامه بدون كلمة مرور أو auth0 أو أي شيء آخر قد نفضله.

impronunciable لمعلوماتك مع iaincollins في تطبيقي.

متطلباتي هي:

  • يؤمن
  • مصادقة جانب الخادم ثم جانب العميل
  • دعم كل من Facebook وتسجيل الدخول / كلمة المرور
  • يجب تغيير موفري المصادقة بسهولة
  • إنشاء مستخدم في Graphcool
  • مصادقة طلبات GraphQL اللاحقة إلى Graphcool

في حال كان ذلك يساعد شخصًا ما ، فإليك تطبيقي بمصادقة من جانب الخادم 🙂

يجب فصل المصادقة عن خادم Next.js ، لكنني أنتظر شخصًا آخر لتقديم الإلهام حول ذلك ... كما أنني لست متأكدًا مما إذا كان محميًا بشكل صحيح ضد CSRF.

وهذا هو ما فعلته:

  • عندما يقوم المستخدم بتسجيل الدخول ، يقوم جافا سكريبت من جانب العميل بتعيين ملف تعريف ارتباط في المتصفح يربط رمز حامل المصادقة
  • عند إجراء طلبات مصادقة ، يقرأ رمز جانب الخادم (next.js) رمز الحامل في رؤوس طلب المتصفح ويستخدمه للاتصال بخادم api نيابة عن العميل

هذا عرضة لـ XSS (حتى لو كان رد الفعل يفعل الكثير لمنعه) وهجمات CSRF ولكنه بسيط ويعمل مع SSR.

فقط للإضافة إلى الطلبات

graph.cool + apollo + jwt + auth0 + next.js ، تم تنفيذ الأجزاء الأربعة الأولى من ذلك بالفعل على https://github.com/graphcool-examples/react-apollo-auth0-example

balupton في

nmaro لا أعرف ، ولم أكتب بواسطتي - من الأفضل أن أسأل هناك

بالنسبة إلى تطبيقي الخاص ، حصلت على مصادقة باستخدام next.js و auth0 ، ثم مع خادم zeit / micro API الذي يتحقق من الرموز المميزة لحاملها.

يجب أن تكون قادرة على فتح المصدر في وقت ما في فبراير.

باتباع نفس الفلسفة التي اتبعها next.js (افعل شيئًا واحدًا وافعله جيدًا) ، لقد طورت الهيكل العظمي لنظام حسابات المستخدمين الموسعة للعقدة. شاهد الفلسفة هنا: https://medium.com/the-ideal-system/ooth-user-accounts-for-node-js-93cfcd28ed1a#.97kyfg4xg

مشروع جيثب موجود هنا: https://github.com/nmaro/ooth/

الهدف هو الحصول على مصادقة موسعة ومستقلة + خدمة إدارة مستخدم مثالية لاستخدامها كخدمة مصغرة منفصلة ، وهيكل تطبيق يعمل بشكل جيد مع node.js.

مثال على مصادقة البريد الإلكتروني + كلمة المرور هنا: https://github.com/nmaro/ooth/tree/master/examples/ooth
هناك حزم بالفعل في مكانها لـ Facebook و Google auth (ooth-facebook و ooth-google) ، والتي يجب أن تكون سهلة التنفيذ بناءً على جواز السفر facebook و جواز السفر google على التوالي.

سأقوم بنشر مثال لتكامل next.js في أسرع وقت ممكن. لا تتردد في الانضمام إلى المناقشة والمساهمة.

آسف على التوصيل ، ولكنه من أجل الصالح العام - أعتقد حقًا أنه لا يوجد حل جيد للعقدة حتى الآن ، وهذا فقط الجمهور المناسب للأشخاص الذين قد يرغبون في مثل هذا الشيء. سلام

وفي الوقت نفسه ... هنا مثال على واجهة برمجة تطبيقات Graphql تتطلب المصادقة باستخدام JWT-Token لعمليات الكتابة فقط. لا تتردد في استخدامه مع طريقة المصادقة المفضلة لديك :)

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

لقد قمت بتحديث https://nextjs-starter.now.sh لإضافة دعم oAuth.

screen shot 2017-02-10 at 05 03 19

  • يستخدم Passport لـ oAuth ، جنبًا إلى جنب مع الجلسات السريعة (كما كان من قبل).
  • هناك دعم لـ Facebook و Google و Twitter + oAuth ومن السهل إضافة المزيد (انظر AUTHENTICATION.md و path / auth- جواز السفر . js).
  • يستخدم نظام جلسة العميل / الخادم العالمي (مع رموز CSRF ، وحماية XSS عبر ملفات تعريف الارتباط HTTP فقط ، وطبقة ORM التي تدعم Mongo ، و SQL DBs ، و Redshift ، وما إلى ذلك) كما يستخدمها تسجيل الدخول إلى البريد الإلكتروني.
  • يمكن الإبلاغ عن تجربة تكوين oAuth على بوابات المطورين رهيبة تمامًا كما كانت دائمًا (تحدث أخطاء غريبة ويصعب تصحيحها).

إن طبيعة oAuth - جلسات db + + جواز السفر ومعالجة الأخطاء التي تحتاج إلى العمل معًا بشكل وثيق - والجلسات التي تحتاج إلى العمل مع كل من العميل والخادم وكيف يعمل ذلك مع العرض العام - تعني القليل من المحاولة والالتفاف في وقت واحد إذا أنت تحاول معرفة ما يحدث ، لكن منطق العميل لا يحتوي على أي تكوين محدد لـ oAuth ، لذا فهو ليس فوضويًا للغاية.

سأكون سعيدًا بتقسيم المصادقة فقط إلى مثال منفصل ، على الرغم من أنني أظن أنه لن يكون أصغر كثيرًا. إذا أراد شخص آخر ، فهذا عظيم. ربما سأضيف المزيد إلى المثال في مرحلة ما (مثل صفحة إدارة الحساب). ربما يكون ربط المزيد من الوثائق أمرًا جيدًا.

عمل مدهش! إذا كان بإمكانك تقسيم المصادقة وإضافتها إلى مستودع js التالي ، فسيكون ذلك رائعًا: القلب:

يمكنني أن أفعل ذلك أيضًا

لن يكون لدي وقت خلال الأسبوعين المقبلين أو نحو ذلك ، لذلك إذا أراد شخص ما القيام بذلك فسيكون ذلك رائعًا.

أرغب في إعادة تشكيلها ومعرفة ما إذا كان من الممكن اختزالها إلى مجرد وحدة نمطية (تعرض مكونات بسيطة مثل أزرار تسجيل الدخول ونماذج تسجيل الدخول لتضمينها) ، وأخذ بعض الإلهام من المثال السابق الجميل من جانب العميل فقط بقلمimpronunciable.

تحديث: سأذهب بعيدًا بالفعل ، ولهذا السبب لا يمكنني ذلك ، ولكن عندما أعود ، يسعدني أن أفعل ذلك!

لقد اتبعت دليل البدء السريع auth0 / response مع بعض التعديلات ، ولكن عندما أتصل بـ lock.show() ، فإن شكاوى التطبيق:

خطأ غير معلوم: addComponentAsRefTo (...): يمكن فقط لـ ReactOwner أن يحتوي على مراجع. ربما تضيف مرجعًا إلى مكون لم يتم إنشاؤه داخل طريقة render للمكون ، أو لديك نسخ متعددة من React تم تحميلها

iaincollinstimneutkens فيما يتعلق بمثالك ، من فضلك

يستخدم المثال ملف تعريف الارتباط httpOnly لتخزين الرمز المميز للجلسة مما يجعله آمنًا ضد هجمات إصابات جافا سكريبت (XSS). ثم يتورط في مشكلة تخزين رمز csrf في التخزين المحلي للحماية أيضًا من هجمات CSRF.

هناك افتراض أساسي مفاده أن هذا المزيج من الأساليب يجعل الأشياء آمنة ، مما قد يضلل المستخدم / المطور. لا يزال بإمكان المهاجم جرح جافا سكريبت في الصفحة (XSS) ، وقراءة رمز csrf المميز ، واستخدامه لتنفيذ طلبات (ملف تعريف الارتباط) المصدق عليها إلى apis. هل يستحق الذكر في التمهيدي؟

مرحبًا davibe

للأسف ، لا يوجد حاليًا نهج أفضل تقنيًا من ملف تعريف ارتباط الجلسة ورمز CSRF منفصل دوار ، لذا أعتقد أنني يجب أن أقول إنني سعيد على نطاق واسع بالنموذج كما هو لأنه لا توجد بالفعل طريقة أخرى للقيام بذلك (حتى لو كان من الممكن دائمًا تحسين التنفيذ الفعلي).

يمكننا إضافة بصمة المتصفح ، ربما يمكن تدوير رمز الجلسة بشكل متكرر (نسيت ما إذا كان ذلك تلقائيًا في الوقت الحالي) ، يمكن أن يكون رمز CSRF عبارة عن رأس بدلاً من المعلمات ، يجب أن تكون ملفات تعريف الارتباط بالفعل SSL فقط في الإنتاج ويمكننا إضافة تاريخ انتهاء صلاحية رموز تسجيل الدخول ، لكن AFAICS هناك مجال محدود إلى حد ما للتحسين فيما يتعلق بنموذج الأمان ولا يوجد شيء يمنح حقًا مزيدًا من الحماية في حالة تمكن أي شخص من إدخال أي رمز يريده في التطبيق ؛ ولكن من فضلك لا تتردد في إثارة هذه الأشياء باعتبارها قضايا لتحسين الريبو.

إذا كانت هناك أي خيارات لتعديل حالة الحساب (وهي غير موجودة حاليًا) ، فيمكننا الحصول على CAPTCHA قبل تنفيذها لجعل الأمر أكثر صعوبة لإجراء التغييرات على الخادم دون إذن ، ولكن كل ما يحدث في المثال هو أنه يمكن للمستخدمين تسجيل الدخول ومن ثم فإن هذا خارج النطاق حاليًا.

إن تخزين الرموز المميزة للجلسة التخزينية المحلية سيجعلها أقل أمانًا بشكل ملحوظ وتتعارض مع الاستخدام المقصود في المواصفات ، لذلك أنا شخصياً لا أؤيد ذلك - على الرغم من أنني أقدر أنه سيبسط الأمور ، مثل عدم وجود إسقاط CSRF ، ولكن من المحتمل أن يكون الأشخاص لست بحاجة إلى مثال على ذلك لأنه سيكون من السهل جدًا القيام به - لقد حاولت فقط تقديم مثال لأنه محرج للغاية. :-)

أنا معك تمامًا لأنني أكره أيضًا مدى صعوبة الأمر ولم أتخل عن محاولة تحويله إلى وحدة نمطية.

حسنًا .. فهمت.
هذه المسألة كانت مفيدة جدا لي شكرا لكم.

هذه وجهة نظر Auth0 https://auth0.com/blog/cookies-vs-tokens-definitive-guide/
يقترحون بشكل أساسي تجنب ملفات تعريف الارتباط ولكن هذا من شأنه أن يترك SSR عند تحميل الصفحة الأولى على ما أعتقد.

مرحبا جميعا!

أنا أعمل أيضًا على المصادقة مع next.js والتعليقات من هذه المشكلة ، ولا سيما davibe + الريبو منiaincollins والعلاقات العامة منtimneutkens كانت مفيدة للغاية.

يقوم الحل الخاص بي بما يلي:

  • عند تسجيل الدخول بنجاح ، يقوم مخفض إعادة الإرسال الخاص بي بحفظ الرمز المميز وبيانات المستخدم في ملف تعريف ارتباط باستخدام ملف تعريف ارتباط التفاعل .
  • يتم تغليف أي صفحة / مكون يحتاج إلى هذه المعلومات في مكون ذي ترتيب أعلى مشابه لـ timneutkens with-session.js . في حالة SSR ، سيكون الرمز المميز متاحًا في ctx.req.headers.cookie ، وإلا يمكنك الحصول عليه من مستند المتصفح (استخدم طريقة تحميل ملف تعريف الارتباط التفاعلي).
  • بمجرد أن أحصل على الرمز المميز ، يمكنني تعيينه في رؤوس حامل / التفويض كلما تقدمت بطلب.

من المفيد أن يكون لدي خدمة مصغرة لمصادقة رمز JWT الخاصة بي تعمل في حاوية عامل إرساء.
ربما سيكون من الأسهل تقديم خدمة JWT بسيطة كجزء من مثال with-auth؟ وبالتالي تجنب اختراق server.js واحتمالية فقدان مزايا next.js baked-in hot reload، ssr and routing؟

لست متأكدًا أيضًا مما إذا كان هذا النهج آمنًا من حيث CSRF / XSS. نرحب بأي تعليقات.

شكرًا لكم جميعًا على العمل الرائع الذي أنجزتموه حتى الآن. أنا معجب كبير بهذا المشروع!

jcsmesquita أنا أعمل على إصدار جديد من المثال مع فصل كل شيء عن Next.js على غرار كيفية تنفيذ المصادقة في zeit.co.

subsumo شكرًا على الذكر ، لمعلوماتك: NAP هو ملكي ، يعتمد authen عبر الويب على nextjs-starter بالإضافة إلى تفاعل تسجيل دخول العميل الأصلي باستخدام الرمز المميز.

timneutkens هل الحل الذي تعمل عليه يسمح لك بالمصادقة نحو خدمة منفصلة؟

لقد كنت أبحث في نموذج طلب سحب مثال المصادقة الحالي https://github.com/zeit/next.js/pull/1141
يبدو لي أنه يسمح فقط بالمصادقة مع خادم next.js ، ولكن ليس متماثلًا تجاه خدمة منفصلة.

بمعنى آخر ، افترض أنك تريد فصل خادم next.js وواجهة برمجة تطبيقات التطبيق الفعلية (مثل REST أو GraphQL) ، فإن ما تريد فعله هو أن يكون العميل والخادم قادرين على المصادقة تجاه واجهة برمجة التطبيقات. لا أعتقد أن هذا الحل يساعدك حقًا هناك.

فكرت في التدفق.

جهات:

  • العميل (ج)
  • خادم (S) Next.js
  • API (A)

الهدف هو إنشاء 3 جلسات قائمة على ملفات تعريف الارتباط:

  1. CS
  2. كاليفورنيا
  3. SA

الجلسة 1) بحيث يتعرف العميل على الخادم ، و 2) 3) بحيث يمكن لكل من العميل والخادم استخدام جلساتهما الخاصة للوصول إلى واجهة برمجة التطبيقات بشكل مستقل.

هذا هو التدفق:

  1. يتم تنفيذ CS بسهولة ، ولا حاجة للمصادقة
  2. يتم عمل CA مع المصادقة (على سبيل المثال مع اسم المستخدم / كلمة المرور). بالإضافة إلى ذلك ، يتم توفير JWT
  3. يوفر العميل JWT للخادم ثم يتجاهلها
  4. يتم تنفيذ SA مع JWT ، والتي يتم التخلص منها بعد ذلك

ما هو رأيك؟ هل توجد طريقة أسهل؟ هل يجب علينا بدلاً من ذلك الاحتفاظ بواجهة برمجة التطبيقات مقترنة بخادم next.js ، بحيث تكون هناك حاجة إلى جلسة واحدة فقط (CS)؟

rauchg أنا لا

timneutkens هل الحل الذي تعمل عليه يسمح لك بالمصادقة نحو خدمة منفصلة؟

هذه هي الفكرة. كنت مشغولاً في إصلاح أشياء أخرى على Next.js. سوف نعود إليها في أسرع وقت ممكن.

لقد كسرت الأجزاء الخاصة بـ github-auth من تطبيقي في مثال سهل الهضم. قد يكون مثيرًا للاهتمام بالنسبة للبعض ويحب أي تعليقات على الكود أو التدفق: https://github.com/possembers/next-github-auth-example

تحديث: لقد أعدت تصميم التطبيق النموذجي في مجموعة قابلة لإعادة الاستخدام من المكونات التي يمكن "إسقاطها" في التطبيقات التالية

المتابعة: لقد كتبت تكاملًا مع ooth وواجهة برمجة تطبيقات GraphQL.

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

يعتمد على الأساليب الحالية ، أي المصادقة تجاه خادم next.js ، أي أنه يفترض أن API وخادم المصادقة يعملان في نفس العملية ، لذلك يجب إنشاء جلسة واحدة فقط. الميزة: من حيث المبدأ ، يمكنه تخزين أوراق الاعتماد / قابلة للتوسيع فعليًا لأي استراتيجية جواز سفر.

timneutkens أي تقدم على هذا الصعيد؟

لقد أعدت تصميم تطبيق مثال github auth في مجموعة قابلة لإعادة الاستخدام من الزخارف ومكوِّن الصفحة من أجل "إسقاط github auth في" التطبيقات التالية. تم الترحيب بتعليقات التعليمات البرمجية والوظائف. https://github.com/possuable/next-github-auth

أعتقد أنه قد يكون من المثير للاهتمام تحديد اللوحات هنا ثم الاستمرار في تطوير هذا إلى إطار تأليف أكثر عمومية في المرحلة التالية.

تضمين التغريدة
آسف لإجراء اختبار الاتصال ولكن هل أحرزت أي تقدم في هذا الأمر؟ لقد فقدت تمامًا كيفية إعداد المصادقة مع next.js بشكل صحيح.

kolpav لقد أنجزت بعض الأعمال عليها ، وهي غارقة حاليًا في أشياء أخرى 😥 بكل الوسائل ، هذا يحتل مكانة عالية جدًا في قائمة أولوياتي لـ Next

تعد الطريقة الواضحة والموثقة جيدًا والآمنة لتحقيق المصادقة باستخدام تطبيق next.js أمرًا بالغ الأهمية لنجاحه كإطار عمل.

لا أتذكر آخر مرة أنشأت فيها صفحة ويب لا تحتوي على مصادقة.
مثل معظم الأشخاص الذين أتخيلهم ، أريد أيضًا إجراء مكالمات آمنة إلى بياناتي المدعومة من أجل الراحة ، لذلك يبدو أن JWT هو الحل الواضح.

ولكن هناك الكثير من النقاش بين القضايا والعلاقات العامة لست متأكدًا من أين أبدأ!

تضمين التغريدة
رائع 👍 أعتقد أنه سيكون ذا قيمة كبيرة للآخرين.

camstuartkolpav هناك بعض الخير ونماذج العمل فوق بما في ذلك دعم OAuth و البريد الإلكتروني المصادقة على أساس أن الاستخدامات سواء JWT وHTTP الكوكيز من قبل المشاركينjaredpalmer،luisrudge،impronunciable،possibilities ونفسي.

لتسليط الضوء على بعض الروابط العمل التحقق:

(كان مثال المصادقة الجزئية جيدًا ولكني أعتقد أنه بحاجة إلى التحديث.)

هناك مجال لمزيد من التحسين ، والذي علق عليه معلقون إضافيون أعلاه - بما في ذلك مكون مخزن الجلسة وتقسيم منطق الخادم ؛ ومثال يبسط الأمور بشكل أكبر والذي عمل عليه تيم.

تعد بساطة المصادقة منطقة صعبة للتطبيقات العالمية ، ولكن يجب أن تكون قادرًا على الحصول على الأمثلة المذكورة أعلاه - أو مجرد تجربة العروض التوضيحية مباشرة - ومعرفة كيفية عملها دون الكثير من الجلبة.

iaincollins هذه أمثلة رائعة. ولكن كيف يمكنني استخدام (على سبيل المثال) مشروع بداية؟ لذلك إذا كنت أرغب في إنشاء تطبيقي. أحتاج إلى استنساخ هذا الريبو؟ أو أحتاج إلى "نسخ ولصق" الكود من مشروع بادئ مقسم إلى جزء إلى الكود الخاص بي؟

إذا تم تحديث مشروع البداية - ماذا أفعل؟

تضمين التغريدة
أمثلة لطيفة خاصة لك.
لكن مع ذلك ، أود أن أرى مثال المصادقة مع ختم الموافقة عليه zeit كل العيون تشير إلى اتجاه واحد حتى لا تمر أي أخطاء أو أخطاء دون أن يلاحظها أحد. في الوقت الحالي ، لدي ترخيص العمل الخاص بي ولكني لست متأكدًا من مدى أمانه.

متفق عليه kolpav ، فإن نشر الأمان الخاص بك هو عمل صعب. الأفضل ترك للخبراء

لقد أنشأت مكدسًا لهذا يمكنه التعامل مع المصادقة بسهولة باستخدام GraphQL: https://github.com/thebillkidy/MERGE-Stack

@ salmazov لقد وجدت طريقة مفيدة للبدء وفهم ما يحدث في مثال أو مشروع مبتدئ يمكن أن يكون تفرعها ، ثم تجريد الأشياء غير ذات الصلة حتى يتم تركك مع الكود المتعلق بالوظيفة فقط تريد أن تنفذ ؛ ثم محاولة نقل هذه الوظيفة إلى مشروع آخر.

kolpavcamstuart يحتوي هذا الموضوع على مناقشة مستفيضة لنماذج الأمان المختلفة ، بما في ذلك فضح بعض المفاهيم الخاطئة الشائعة والمفاضلات. أود أن أشير بشكل خاص إلى النقاط حول ملفات تعريف الارتباط HTTP فقط ورموز CSRF (والحماية الإضافية التي توفرها ضد XSS و CSRF على استخدام JWT و / أو Web Storage API لرموز الجلسة). إنه حقًا يستحق القراءة.

iaincollins هل قصدت ربط شيء ما؟ :ابتسامة:

مرحبا يا شباب :)

لدي سؤال ، كنت أقرأ بعد ذلك ، لا يمكنني الحصول على الرموز المميزة للمصادقة مع jwt من localstorage.

إذا كان لدي خادم لتقديم الشحنة الأولى لموقعي مع التالي. ولدي خادم آخر لواجهة برمجة التطبيقات الخاصة بي. هذا يتلقى المستخدم / المرور من العميل ويعطي jwt. في أي الحالات أحتاج إلى الحصول على الرمز المميز في الخادم ؟؟

لماذا أحتاج إلى رمز مميز في خادم التقديم (التالي)؟

إذا لم يرسل العميل الرمز المميز إلى خادم api ، فإن واجهة برمجة التطبيقات لا تعطي البيانات ، ولا يمكن للمستخدم الحصول على معلومات خاصة. أنا لا أفهم لماذا أحتاج إلى إرسال الرمز المميز إلى خادم العرض.

تضمين التغريدة

هذا قد يساعد. بشكل عام ، لديك خياران:

  1. امنح الخادم التالي JWT (ربما عبر ملف تعريف الارتباط). سيسمح هذا للخادم التالي بإجراء مكالمات API نيابة عن العميل. قد ترغب في ذلك إذا كان العرض الكامل من جانب الخادم مهمًا لك.

  2. قم بتخزين JWT في وحدة التخزين المحلية للعميل ولا تمنح خادم Next إمكانية الوصول إليه. في هذه الحالة ، يمكنك ببساطة تجاوز جانب خادم مكالمات api وتأجيل العرض الكامل حتى يكتمل تحميل جانب العميل.

أعتذر عن إعادة فتح هذا ، لكنني اعتقدت أنني سأضيف سنتي إلى هذا الموضوع ، وكيف يتم البحث والتطوير الأولي في هذا المجال. أمثلة التعليمات البرمجية أقل ، المزيد من التدفق عالي المستوى.

أولاً ، بالنسبة إلى السياق ، تم إنشاء معظم تطبيقنا بالفعل في Symfony 3 (PHP) ، ويستخدم Vue لتجربة مختلطة. يعرض الخادم صفحة مجمّعة ، ويعيّن بيانات التطبيق إلى __INITIAL_STATE__ حتى يلتقط التطبيق. وقد أدى ذلك إلى اتخاذ قرار بين عرض صفحات التسويق في Symfony (لكبار المسئولين الاقتصاديين) ، واختيار UX / UI على تحسين محركات البحث في مناطق أخرى عن طريق جلب البيانات عبر JS وتوفير إحساس أكثر بـ SPA-ish. تجدر الإشارة أيضًا إلى أن ليست كل الصفحات ثنائية عامة / خاصة (كما رأيت في بعض الأمثلة). تكون بعض الصفحات عامة بشكل افتراضي ، ثم يتم عرضها بشكل مختلف إذا تمت مصادقتها. كنا نفكر في استخدام SPA لأجزاء من الموقع ، ولكن من نواح كثيرة عملية ، كانت UX / UI أسوأ (TTI أبطأ ، أشرطة التقدم ، إلخ). بالإضافة إلى ذلك ، هذا لا يحل مشكلة تحسين محركات البحث ، ما لم نقدم FOUC ونعرض النص مرتين (مرة من خلال Symfony ، ومرة ​​أخرى كمكونات JS) ، إلخ.

أدخل SSR / Universal JS ...

في حالتي ، ما فعلته هو تقليد المنطق PHPSESSID ، من خلال إنشاء ملف تعريف ارتباط HttpOnly UJSSESSID (صنع الاسم) ، وتعيين القيمة إلى المستخدم JWT. يمرر تطبيق Symfony هذا في كل طلب صفحة أثناء تنقل المستخدم حول الموقع. عندما ينقر المستخدم على صفحات UJS ، سيتلقى جانب الخادم لهذه التطبيقات ملفات تعريف الارتباط في الطلب (حسب السلوك المضمن في المتصفح). إذا تم تعيين ملف تعريف الارتباط UJSSESSID ، فإن التطبيق يستدعي واجهة برمجة التطبيقات للحصول على معلومات المستخدم (على سبيل المثال ، /api/v1/users/me مع تمرير الرمز عبر رأس Authentication ). تتم بقية الاستدعاءات من خلال API ، باستخدام نفس الرمز المميز. تعمل آلية تسجيل الخروج من Symfony على مسح ملف تعريف الارتباط UJSSESSID . في المرة التالية التي يتم فيها تحميل تطبيق UJS ، سيعرض الصفحات في وضع المستخدم المجهول. لمعلوماتك ، يتم توجيه صفحة Symfony مقابل UJS من خلال Apache ProxyPass . لا يتم استخدام LocalStorage.

والنتيجة النهائية هي تجربة مستخدم سلسة حيث يكون المستخدم في بعض الصفحات التي تحتوي على PHP مع JS من جانب العميل ، وبعض الصفحات التي هي UJS. يتيح لنا ذلك إجراء اختبارات A / B ، وتحديث الموقع بشكل متكرر - لا يبدأ الجميع من الصفر :)

في حين أن هذا أكثر تعقيدًا بعض الشيء بسبب تكافؤ PHP / UJS ، يمكن استخدام نفس المبدأ في حل UJS كامل مع API أو برمجية خادم Node.js (مثل Express و Adonis وما إلى ذلك). بدلاً من تعيين ملف تعريف الارتباط UJSSESSID عبر طلب صفحة PHP ( HttpOnly flag) ، اطلب من المستخدم تسجيل الدخول من خلال SPA / UJS ، واضبط ملف تعريف الارتباط هناك. ما لا يجب عليك فعله ، هو استخدام التطبيق الخاص بك لفك تشفير JWT ، أو إجراء مكالمات من طرف ثالث تتطلب client_secret . استخدم برمجية وسيطة تبقى على الخادم لذلك.

أتمنى أن يساعد هذا شخص ما. الأمثلة الأخرى التي رأيتها كانت طبق بتري قليلًا جدًا بالنسبة لي.

jaredpalmer مرحبًا ، شكرًا على هذا التنفيذ ، لقد جربته ، فقط قمت بنسخ ولصق كل التعليمات البرمجية الخاصة بك واستبدلت لوحة القيادة الخاصة بك مع index.js الخاص بي الذي يبدو كالتالي:

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

export default withAuth(index)

وفي withAuth hoc ، قمت بتغييره لإعادة التوجيه إلى صفحة تسجيل الدخول.
ولكن قبل إعادة التوجيه إلى صفحة تسجيل الدخول ، لا تزال محتويات صفحة الفهرس تومض قليلاً. :س

ما هي حالة هذه القضية؟ 😇

هذا أمر مربك بعض الشيء بالنسبة للأشخاص الجدد الذين يقرؤون خلال المناقشة بأكملها. قررت تطبيق المصادقة الأساسية للغاية هنا. صفحتان فقط (فهرس ، تسجيل دخول) ، وخادم مخصص
https://github.com/trandainhan/next.js-example-authentication-with-jwt

في الأساس ، لدينا برمجيات مصادقة وسيطة في الخادم للتحقق من الرمز المميز في رأس كل طلب. سيتم تخزين رمز jwt في ملفات تعريف الارتباط. أجد أن هذا بسيط للغاية ومباشر ويعمل بشكل جيد للغاية.

trandainhan هل يمكنك إضافة نقطة نهاية POST تستخدم رمزًا مميزًا سريًا لمنع هجمات CSRF؟

sbking كود مصدر محدث

هل هذا جاهز للاستخدام 😬؟

هل حاول أي شخص المصادقة باستخدام غلاف إعادة المصادقة ؟

مرحبا جميعا! على مدار الأشهر الماضية ، قمت بإنشائه ، وصقلته الآن

يتميز بما يلي:

  • التسجيل بالبريد الإلكتروني وكلمة المرور
  • تسجيل الدخول بالبريد الإلكتروني أو اسم المستخدم وكلمة المرور
  • صفحة الحساب حيث يمكنك تعيين اسم المستخدم الخاص بك وتغيير كلمة المرور الخاصة بك وإعادة إرسال بريد إلكتروني للتحقق
  • نسيت كلمة المرور / إعادة تعيين صفحات كلمة المرور
  • تحقق من صفحة البريد الإلكتروني
  • واجهة برمجة تطبيقات GraphQL أساسية مرتبطة بـ MongoDB (ملف واحد ، يمكن إزالته بسهولة)
  • الحد الأدنى من المعايير (يتم تغليف أكبر قدر ممكن من المنطق في المكتبات)

تحقق من العرض التوضيحي المباشر هنا: http://staart.nmr.io/

لقد فعلت ذلك بشكل أساسي لنفسي من أجل النماذج الأولية السريعة ، للبدء بسرعة مع تطبيق بنظام حسابات بسيط وعملي لا يعتمد على الخدمات الخارجية. أنا سعيد جدًا بالنتائج. أعتزم الاستمرار في استخدام هذه المكتبات وصيانتها ، لذا جربها إذا شعرت أن نظام حسابات مؤسس + واجهة مستخدم للعقدة ما زالت مفقودة.

trandainhan شكرًا ، هذا مثال رائع حقًا وأبسط بكثير لكثير من الأشخاص وسيعمل في الكثير من السيناريوهات.

سأفكر فيما إذا كان بإمكاني / كيف يمكنني تكييف المنطق الحالي في nextjs-starter لاستخدام شيء كهذا بدلاً من ذلك ولكن بشكل آمن ، مع الاستمرار في التوافق مع منطق الجلسة السريعة لحالات الاستخدام الواقعية التي أمتلكها (مثل استخدام أشياء مثل Google oAuth APIs حيث أحتاج إلى الخادم للاحتفاظ بالرموز المميزة الممنوحة وتتبعها عند تسجيل الدخول لأول مرة).

لم أكتشف ما إذا كان ذلك ممكنًا حتى الآن ، ولكن سيكون من الأسهل كثيرًا على الأشخاص إذا كان كذلك.

إذا لم يكن الأمر كذلك ، فمن الجدير على الأقل كتابة لطيفة في مكان ما لشرح الخيارات المختلفة للناس.

trandainhan : إذا أضفت <Link href="/">Home</Link> إلى login.js ، ثم نقرت على الرابط الذي تم إنشاؤه ، يمكنني بعد ذلك الوصول إلى index.js دون تسجيل الدخول. كيف تقترح إصلاح هذا في المثال الخاص بك؟

iaincollins أرى معظم الحلول هنا تتم المصادقة عليها مقابل خدمة oauth. هل هناك أي حل جيد للمصادقة مقابل واجهة برمجة تطبيقات تعتمد على JWT؟

paulwehner أعتقد أن هذا يحدث لأن trandainhan تعامل فقط مع توجيه المصادقة من جانب الخادم. ما زلت غير واضح بشأن كيفية عمل التوجيه من جانب العميل في next.js لأنه يتم التعامل مع كل شيء تحت الغطاء بواسطة المكون التالي / الرابط.

@ carlos-peru تحت الغطاء ، يستخدم Link فعليًا التالي / جهاز التوجيه لدفع مسار جديد إلى سجل المتصفح. يبدو أنه يتم التعامل مع معظم الأشياء بواسطة المستعرض ، فلا يوجد شيء يمكن القيام به هنا للبرامج الوسيطة على جانب الخادم. حتى الآن ، لا يمكنني التفكير إلا في إنشاء مكون ارتباط خاص بنا والقيام بأشياء أخرى كلما قمنا بتغيير عنوان url.

@ carlos-peru يمكنك دائمًا استخدام خادم مخصص للتحكم الكامل في التوجيه.

شكرا @ trandainhan و @ kolpav! يجب أن أحصل على فهم أفضل بعد قضاء بعض الوقت في عطلة نهاية الأسبوع. تمكنت أيضًا من تنفيذ حل يعتمد على HOC الذي يحتفظ برمز jwt المميز على ملف تعريف ارتباط ، بحيث يمكن للخادم والعميل استهلاك واجهة برمجة التطبيقات.

nmaro لديّ Backend مع مصادقة JWT لموقع ويب في next.js وتطبيق (تفاعل أصلي).

وبالتالي. أعتقد في النموذج التالي: يحصل العميل على رمز Facebook (يقبل المستخدم تسجيل الدخول إلى facebook) ثم يرسل العميل إلى الواجهة الخلفية الرمز المميز للتحقق والتحقق من رمز المستخدم (جواز السفر-facebook-token في node-js backend) . بعد ذلك ، إذا كان الرمز المميز جيدًا ، ترسل الواجهة الخلفية إلى العميل JWT الذي تم إنشاؤه في الخلفية.

المشكلة؟ يمكن لأداتك الحصول على المفتاح من facebook و google؟ أنا أستخدم hello.js ولكنه غير متوافق مع next.js وكل العالم يستخدم facebook-facebook. أعتقد أن هذا خطأ كبير لأن خادم api يجب أن يكون متوافقًا مع عميل الويب وتطبيق الجوال.

شكرا لك

ملاحظة: لا يمكنني الحصول على دعوة في قناة Slack الخاصة بك.

hmontes هنا - دعوة إلى قناة Slack لمشروع

nmaro أريد مساعدتك في مشروعك. لدي خلفية مع Graphql مع جواز السفر و Facebok وجواز السفر Google-id-token أيضًا !!!

لكن. هل تعرف حزمة متوافقة لربط عميل facebook / google في next.js؟

على جانب العميل ، يمكنك استخدام نمط مشابه لما استخدمته هنا: https://github.com/nmaro/staart/blob/master/packages/staart/src/components/login-facebook.js https: // github. com / nmaro / staart / blob / master /pack / staart / src / element / login-google.js
(بدلاً من oothClient.authenticate أرسل فقط طلب نشر إلى مسار المصادقة الخاص بك).

timneutkens هل سيكون موضع ترحيب العلاقات العامة مع الحد الأدنى من مثال مع ooth؟

nmaro في

أنا أقوم بإنشاء مكون HoC (المزود) لتسجيل الدخول إلى Google.

هل يتم استدعاء componentWillMount على العميل فقط؟ ثم يجب أن يكون على ما يرام.

حسنا. شكرا جزيلا لك على الأمثلة الخاصة بك. أخيرًا يمكنني تنفيذ المصادقة باستخدام وسائل التواصل الاجتماعي.

السؤال الأخير. لقد أنشأت access_token و Refresh_token وأريد أن أضع في localStorage لحفظ البيانات.

أين يمكنني وضع هذا في next.js للتحقق من تسجيل الدخول عند تحديث الصفحة؟ في تطبيق create-react-app ، أضع ذلك في 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}>
....

شكرا لك

مع ooth ، لا أقوم بتخزين رموز facebook ، فأنا أستخدمها مرة واحدة فقط مع جواز السفر ثم أنشئ جلسة مستخدم عادية قائمة على ملفات تعريف الارتباط.

آه. حسنا. أنا أستخدم JWT بدلاً من الجلسات. لذلك ، أرسل access_token إلى الواجهة الخلفية ، ويتحقق مما إذا كان الرمز المميز صالحًا في الخدمة (google ، facebook) ، ثم إذا كان المستخدم موجودًا في تطبيقي وأرسل لي JWT مرة أخرى.

شكرا لك :)

يجب أن أضيف أنه من الخطر تخزين JWTs في التخزين المحلي (بسبب XSS) ، من الأفضل إرسالها كملفات تعريف الارتباط إذا كانت كلها في خادم / مجال واحد ، لذلك لا يمكن لرمز جافا سكريبت للعميل الحصول على JWT ، لكن المتصفح سيرسل JWT تلقائيًا كملفات تعريف الارتباط. تعتبر JWTs خادعة (انظر المناقشات الطويلة أعلاه) ، ولهذا السبب أستخدم الجلسات في Ooth.

لا أستخدم JWT إلا إذا تم استخدام ooth كخدمة مصغرة للمصادقة الخارجية (لأن ملفات تعريف الارتباط تعمل فقط على نفس المجال) ، وحتى بعد ذلك أستخدمها مرة واحدة بالضبط لإنشاء جلسة مع الخادم ، لذلك لا يتم تخزينها في أي مكان على العميل .

لزيادة أمان JWT ، يمكنك استخدام رمز تحديث مميز (مأخوذ من oauth2).

هل يمكن لتطبيق جوال التعامل مع ملفات تعريف الارتباط؟

تضمين التغريدة أنا أفهمك. آسف لخطئي.

هل لديك برنامج تعليمي أو رمز لحفظ رمز JWT في ملف تعريف ارتباط؟ أنا أبحث عن https://github.com/zeit/next.js/blob/master/examples/with-firebase-authentication (نظام المصادقة الخاص بي مع رسم بياني)

كلا ، آسف ، لم أفعل ذلك أبدًا.

تضمين التغريدة
لقد كتبت هذا لنفسي ، لكنني قد أساعد:
https://github.com/malixsys/mobazoo

يا malixsys شكرا للمشاركة. هناك شيء لا أفهمه من شفرتك: يبدو أنك ستهيئ API_BASE_URL إلى شيء خارجي ، أليس كذلك؟ إذا قمت بالمصادقة تجاه واجهة برمجة التطبيقات تلك ، أعتقد أنها ستبدأ جلسة قائمة على ملف تعريف الارتباط ، أليس كذلك؟ ولكن بعد ذلك ، كيف تنقل ملف تعريف الارتباط هذا إلى خادم next.js ، بافتراض أن خادم next.js موجود على مجال آخر؟

آه لا ، أرى أنك قمت بتعيين / مصادقة / تسجيل الدخول في نفس العملية. حسنًا ، إنه نفس النهج الذي استخدمته مع next.js / staart.

في الواقع لا ، ما زلت في حيرة من أمري: في / auth / signin تعيد JWT ، لكنك لا تفعل أي شيء مع ذلك من جانب العميل. لاحقًا يمكنك "getUserFromCookie" ولكني لا أرى مكان تعيين ملف تعريف الارتباط.

nmaro أردت فقط تسجيل دخول أساسي للعمل مع Universal في البداية. أنا على حد سواء تعيين jwt وملف تعريف الارتباط في الوقت الحالي. يتم استخدام ملف تعريف الارتباط لعمل عالمي. لا يزال يتعين علي استخدام jwt في استدعاء axios آخر في هذا الريبو. أفعل في مفترق خاص حيث يشير API_BASE_URL إلى مجال آخر ...
كل ذلك في قائمة المهام الخاصة بي ، مع PWA.
لا تتردد في فتح مشكلة أو الاتصال بي هنا ...

تم تعيين ملف تعريف الارتباط nmaro في saveUser() هنا: https://github.com/malixsys/mobazoo/blob/master/utils/auth.js

أعلم أن هذه المشكلة قد تم إغلاقها ، لكني أرغب في عرض الحل الخاص بي.
https://next-auth.now.sh/
أعتقد أنه مشابه إلى حد ما لموقع zeit.co

9 أبريل

لقد أنجزت بعض الأعمال عليها ، وأنا غارقة حاليًا في أشياء أخرى 😥 بكل الوسائل ، هذا يحتل مكانة عالية جدًا في قائمة أولوياتي لـ Next

22 سبتمبر # 2974

نحن نخطط لإصدار مثال مصادقة رسمي قريبًا ، هل يمكنك إصدار هذا كمستودع منفصل؟ Thaaaanks!

تضمين التغريدة

مرحبًا ، آسف لإزعاجك بشأن هذا مرة أخرى ولكن هل يمكنك من فضلك مشاركة كيف هو حالة مثال المصادقة الرسمية؟ إنه بالتأكيد شيء أرغب في رؤيته والحكم عليه من خلال عدد التعليقات في هذه القضية للآخرين أيضًا. إذن ما هو مكانها في قائمة الأولويات وهل يجب أن نرفع آمالنا؟ 😄

مرحبًا kolpav ، لقد أعلنوا رسميًا عن هذا على خريطة الطريق لـ Next.js 5.

أخيرًا ، نضيف بعض الأمثلة المطلوبة بشدة (مثل مصادقة المستخدم) ، ووثائق محسّنة للداخلية Next.js وميزات أصغر وإصلاحات أخطاء.

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

babenzele هذه أخبار رائعة. لابد أنني فاتني ذلك 😅

أين يمكننا مواكبة تطور Next.js 5؟ أقوم بدمج auth0 في الوقت الحالي ، ولكن سيكون من الرائع أن يكون لديك مسار / مثال رسمي لمصادقة nextjs ليتبعه

يبدو أن Next.js في حاجة ماسة إلى مثال مصادقة محلي رسمي باستخدام JWT / cookies / localStorage (أو مزيج منها ، طالما أنه آمن ومحمي من XSS / CSRF) ... قضيت عدة أسابيع في محاولة ابتكر هذا باستخدام خادم Express API منفصل مع إستراتيجية Passport.js المحلية. لقد جربت JWT في ملف تعريف ارتباط / تخزين محلي للطلبات عديمة الحالة ، وجربت أيضًا ملف تعريف ارتباط عادي مع معرف الجلسة من البرنامج الوسيط للجلسة السريعة فيه بمجرد أن تخليت أخيرًا عن JWT وانعدام الجنسية. انتهى بي الأمر إلى مواجهة مشكلات حيث تم إنشاء جلسات إضافية على خادم Express API بسبب الطريقة التي تعمل بها الجلسة السريعة (تمت تجربتها مع saveUninitialized: false). فكرت في نقل كود Express إلى server.js في تطبيق Next.js ، لكنني أفضل أن يكون خادمًا منفصلاً. أنا متأكد أيضًا من أن تطبيقي ليس آمنًا من XSS / CSRF أو اختطاف ملفات تعريف الارتباط. نحتاج إلى مثال رسمي يغطي أفضل الممارسات للمصادقة المحلية / تسجيل الدخول ، أو ربما وحدة رسمية كجزء من Next.js التي ستتعامل مع التعقيدات بالنسبة لنا!

بينما ننتظر Next.js 5.x وأمثلة أخرى ، قد ترغب في إلقاء نظرة على https://nextjs-starter.now.sh الذي لا يزال قيد الصيانة ويستخدم Next.js مع Express و Express Sessions و CSRF ( رموز CRSF) ، XSS (ملفات تعريف الارتباط HTTP فقط لرموز الجلسة) ويستخدم Passport JS لدعم oAuth والبريد الإلكتروني.

أنا في الواقع بصدد إعادة هيكلة كود المصادقة إلى وحدة نمطية ، مما يجعل من السهل حقًا إضافة المصادقة إلى مشاريع Next.js بطريقة سهلة الاستخدام. يجب أن تسمح لك الوحدة باستخدامها بسهولة مع أي قاعدة بيانات تريدها ، دون الحاجة إلى نسخ مجموعة من التعليمات البرمجية من مثال Starter Project. آمل أن أنتهي من ذلك هذا الأسبوع.

كمرجع ، توفر طريقة "إرسال ملفات تعريف الارتباط المزدوجة" طريقة سهلة لإضافة حماية CSRF إذا كنت تبحث عن طريقة بسيطة ولكنها آمنة.

تكمن المشكلة في JWT في localStorage في أنه يمكن قراءته دائمًا من جانب العميل JavaScript ، لذا فهو متجه لاختطاف الجلسات عبر XSS ، إذا كان لديك محتوى غير موثوق به (مثل المحتوى أو الإعلانات المقدمة من المستخدم).

إذا كنت تستخدم ملفات تعريف الارتباط HTTP فقط للرموز المميزة للجلسة - أو شيء مثل JWT مع قيمة رمزية في HTTP فقط (أو تشفير JWT بالكامل وفك تشفيره باستخدام رمز HTTP فقط على الخادم) - فستكون الجلسات محمية قدر الإمكان يكون. الفكرة هي أنه ، من الناحية المثالية ، يجب ألا تكون الرموز المميزة للجلسة على وجه التحديد قابلة للقراءة عبر JavaScript من جانب العميل.

بالطبع لا تستخدم الكثير من المواقع ملفات تعريف الارتباط HTTP فقط لأنها تمثل ألمًا لتطبيقات الصفحة الواحدة ، وتنطوي دائمًا على وجود بعض منطق المصادقة في الواجهة الأمامية ، لكنها لا تزال الطريقة المثالية.

لا يزال الخيار الآخر هو https://github.com/nmaro/ooth الذي يتم صيانته بنشاط ، ويأتي بالفعل في حزم ويتم استخدامه في اثنين من تطبيقات الإنتاج.

iaincollins قمت بتنزيل Next.js Starter Project وبدأت في البحث فيه. سأحتاج إلى فصل الأجزاء الهامة المتعلقة بالأمان (XSS / CSRF) ومحاولة دمجها في تطبيقي ، أو انتظر حتى تنتهي من الوحدة المنفصلة. هل هناك مكان يمكنني من خلاله تتبع تطور تلك الوحدة؟

مرحبًا @ kelleg1 ،

تم نشر الوحدة المنفصلة الآن كوحدة المصادقة التالية لتسهيل استخدامها في مشاريع أخرى. يتضمن مشروع مثال يوضح كيفية استخدامه.

لمزيد من المرجع ، يستخدم مشروع

لا يزال الأمر معقدًا إلى حد ما على الرغم من ذلك ، إذا كان لديك تطبيق موجود ، فقد تجد أنه من الأسهل استخدامه كمرجع ، ولكن إذا كان الأمر كذلك ، آمل أن يساعدك

ملحوظة: CSRF لا تزال مرتبطة بإحكام في الوقت الحالي. يستخدم lusca لذلك يفترض أن res.locals._csrf تم تعيينه ، لكن مكتبات CSRF المختلفة تستخدم متغيرات خاصة مختلفة.

أقدر أنه لا يزال الاستخدام أكثر تعقيدًا مما قد يرغب أي شخص كما هو ، ولكن على الأقل الآن تم فصل رمز المصادقة أخيرًا إلى وحدة نمطية حتى أتمكن من البدء في إعادة البناء. آمل أن أجعل استخدامه أسهل (مع معالجات افتراضية لقواعد بيانات مختلفة ، وتكوين أسهل لـ oAuth) بمرور الوقت.

iaincollins يبدو أن الاعتماد الوحيد على next.js هو https://github.com/iaincollins/next-auth/blob/master/index.js#L342 ؟ إذا كان الأمر كذلك ، فسيكون من الرائع جعل lib هو التالي.

sedubois أتفق تمامًا!

على الرغم من أن هذا من المحتمل أن يكون مناقشة جيدة لمشكلات GitHub repo بدلاً من هنا. 🙂 إذا كنت ترغب في اقتراح طرق يمكن تحسينها وتبسيطها وجعلها أكثر عمومية ، فأنت ترغب في التعاون.

(لا يزال وجود شيء يسهل استخدامه مع التالي قدر الإمكان هدفًا أساسيًا ، لكنني لا أرى أنه يحتاج إلى أن يكون حصريًا ، حتى لو انتهى به الأمر مع الخيارات المركزة المحددة التالية أيضًا.)

timneutkens تهانينا على إصدار nextjs 5. في المستقبل القريب ، هل سنرى إضافة مثال مصادقة محلية رسمية مضافة إلى مجلد الأمثلة؟ أم أن هذا شيء لا يزال قيد الإعداد لإصداره لاحقًا؟

لدى Ooth الآن وثائق شاملة ، بما في ذلك

jaredpalmer أحب تطبيقك . ومع ذلك ، هل طريقة getUser آمنة؟ ماذا لو قام شخص ما بتغيير السلسلة داخل التخزين المحلي يدويًا ، فهل سيكون من الذكاء أن يعتمد التطبيق على ذلك؟ هل سيكون من المنطقي تغييره إلى أسلوب يقوم بفك تشفير جزء JWT العام من الرمز المميز في كل مرة ويقرأ حالة المستخدم من هناك؟ بهذه الطريقة يمكننا أن نثق في هذه الحالة أكثر بسبب طبيعة الأشياء. ما هو رأيك؟

يجب عليك تخزينه في ملف تعريف الارتباط. لقد كتبت ذلك قبل أن يحصل Next على دعم للخوادم المخصصة.

jaredpalmer هل يمكن أن تخبرني المزيد عنها؟ هل يجب علينا تخزين كل شيء في ملفات تعريف الارتباط بدلاً من التخزين المحلي؟ هل سيكون ترتيب المراكز الخاص بك مختلفًا أيضًا؟ هل هذا يعني أنه يمكننا الآن استخدام طريقة getInitialProps لمواقع الويب المحمية من جانب الخادم؟

مجرد تنبيه _ إذا كان ما تتحدث عنه هو تخزين بيانات حساسة في التخزين المحلي / تخزين الويب _:

"لا تقم أبدًا بتخزين البيانات الحساسة باستخدام تخزين الويب: تخزين الويب ليس تخزينًا آمنًا. إنه ليس" أكثر أمانًا "من ملفات تعريف الارتباط لأنه لا يتم نقله عبر السلك. إنه غير مشفر. لا يوجد أمان أو علامة HTTP فقط لذلك ليس مكانًا للاحتفاظ بالجلسة أو رموز الأمان الأخرى ".

قم بتعيين الرمز المميز في ملف تعريف الارتباط بعد تسجيل الدخول. استخدم ملف تعريف الارتباط js. ثم استخدم محلل ملفات تعريف الارتباط السريع على الخادم بحيث يمكنك التحقق من الحصول على req.headers.cookies.myToken أو ما يعادله. في getInitialProps المخصص ، تحقق من وجود req ، ثم احصل على الرمز المميز من req.cookies ، وإلا احصل عليه على العميل من Cookies.get ("mytoken"). في هذه المرحلة ، سيكون لديك حق الوصول إلى الرمز المميز الخاص بك على العميل والخادم. ثم تريد إنشاء غلاف / مثيل لجلب / axios ودمجه مع ctx التالي في getInitialProps بحيث يكون لجميع صفحاتك طريقة لتقديم طلبات متشابهة مصادق عليها. قد ترغب أيضًا في جعل المستخدم الخاص بك في حالة مخصصة أيضًا. لذلك لا تحتاج إلى تكرار ذلك في كل مكان. يمكنك بعد ذلك إنشاء المزيد من المناظرات إذا كنت بحاجة إلى كيانات مشتركة مثل withUser (withTeam (صفحة))

getUser فكرة سيئة ، يجب عليك فقط تخزين الرمز المميز.

jaredpalmer لقد قمت ببناء نهج يشبه ذلك تمامًا تقريبًا وكل شيء يعمل بشكل جيد. المشكلة التي أحاول حلها الآن هي كيفية تحديث الرموز. تحتوي واجهة برمجة التطبيقات التي أعمل معها على رموز قصيرة العمر نسبيًا (ساعتان) وأحاول الحصول على رأسي حول بعض الأنظمة للحفاظ على تسجيل دخول المستخدم أثناء استخدام التطبيق.
هل لديك أي مساهمة في ذلك؟

يمكنك أيضًا حفظ طلب في كل انتقال للصفحة من خلال عدم تمرير البيانات عبر next.js للمستخدم الخاص بك. للقيام بذلك ، يجب عليك قراءة الرمز المميز من ملف تعريف الارتباط في server.js ومحاولة جلب المستخدم ونقل ذلك إلى معالج الطلب التالي. في المستند ، احصل عليه من الدعائم وقم بتخزينه في JSON على مثل window.USER. ثم في منطقتك ، قرأتها للتو من النافذة عندما تكون في أرض العميل. أخيرًا ، يجب عليك استخدام axios مع معترض استجابة يمسح ملف تعريف الارتباط فورًا عند استلام رمز 403 ويعيد تحميل الصفحة

pbrandone على الرغم من أنه متكرر ، فإن الحل الأبسط والأكثر توقعًا هو إرسال الرمز المميز الخاص بك مع كل طلب ، وتلقي رمز تم تحديثه حديثًا في رأس / نص الاستجابة. يقوم عميلك بتحديث قيمته المعروفة في كل دورة طلب / استجابة ، ويمنح بشكل فعال الرموز المميزة ذات الاستخدام الفردي التي لا معنى لها ولا يمكن إساءة استخدامها.

عادةً ، باستخدام هذا الأسلوب ، يتم استخدام /token/refresh فقط من أجل "التنبيه" الأولي للتطبيق (فكر في ربط componentWillMount لـ <App/> ) ، والتحقق لمعرفة ما إذا كان آخر حفظ الرمز المميز لا يزال صالحًا وقابل للاستخدام.

لم أضطر أبدًا للتعامل مع رموز التحديث ، لكنني كنت سأحاول إجراء ذلك في جهاز اعتراض أكسيوس. سيتعين عليك التفكير في الأمر أكثر ، ولكن من الناحية النظرية ، ستعترض طلبًا سيئًا ، ثم تستخدم رمز التحديث للحصول على رمز جديد ، وتعيين ملف تعريف الارتباط مع الرمز المميز الجديد ، وإعادة تشغيل الطلب الأول بالرمز المميز الجديد مرة أخرى. تعتبر أجهزة اعتراض Axios قوية حقًا لأنها تتيح لك الاحتفاظ بأشياء مثل هذه مجردة وبعيدًا عن رمز المنتج الخاص بك. قد تحتاج إلى كتابة طلب واستجابة اعتراض و / أو الاحتفاظ بنوع من كائن / خريطة ذات حالة في التقدم والتي يمكن أن تصبح مشعرة. نأمل أن يساعد ذلك

أو افعل ما قاله لوقا. أسهل بكثير.

إذا كنت تريد تحديث الرموز المميزة ، فستحتاج إلى اعتراض ملف تعريف الارتباط (إذا كنت تستخدم ملفات تعريف الارتباط) من خلال إعداد خادم مخصص. فعلت هذا باستخدام صريح. وإلا يمكنك القيام بذلك من جانب العميل بالكامل باستخدام رموز JWT. نظرًا لأنني كنت أعمل من خلال ملفات تعريف الارتباط ، فقد كان لدي حالتا استخدام - التعامل مع طلبات التنقل من جانب العميل ، وطلبات الصفحة من جانب الخادم (في أي وقت يكتب شخص ما عنوان url يدويًا أو يضرب تحديث الصفحة.) لكنهما في الأساس هما نفس التدفق تم التنفيذ بشكل مختلف لأن أحدهما من جانب العميل والآخر من جانب الخادم. على جانب الخادم منذ أن استخدمت express ، قمت للتو بإنشاء برنامج وسيط لمعالجة ملف تعريف الارتباط وفك تشفير JWT بداخله والتحقق من انتهاء الصلاحية. إذا انتهت صلاحيته ، اطلب الحصول على رمز جديد واستمر في تمرير المستخدم الذي تم فك تشفيره لإعادة التشغيل على العميل. على العميل ، لدي غلاف HOC للروابط الآمنة التي تتحقق باستمرار من المستخدم ، في كل مرة تتنقل فيها في مكان ما على العميل. سيحصل المورّد ذو الترتيب الأعلى على ملف تعريف الارتباط أو JWT (في حالتي ، فإن JWT الخاص بي موجود في ملف تعريف ارتباط) ويتحقق مما إذا كان لا يزال صالحًا بسرعة. إذا لم يكن صالحًا ، فسيحاول الحصول على JWT / ملف تعريف ارتباط محدث ، والمتابعة ، وإلا فسيتم تسجيل خروجك. نعم أكثر تعقيدًا ولكن أيضًا أكثر أمانًا. امل ان يساعد! لا تتردد في طرح الأسئلة إذا كنت مهتمًا - فقد استغرق الأمر بعض الوقت لمعرفة كل شيء. أنا شخصياً أتساءل عن الأشخاص loggin في Github أو FB وما إلى ذلك - ربما يكون جيدًا في الكثير من الحالات ولكن في بعض الحالات ليس احترافيًا. لا يزال يتعين علي رؤية بنك أو رعاية صحية أو أي من فواتيري التي أدفعها وما إلى ذلك - قم بتسجيل دخولي باستخدام حساب FB الخاص بي. يمكن أن تكون مجرد مسألة وقت ؛)

أما بالنسبة لتجديد رموز الوصول ؛
لست متأكدًا مما إذا كانت هذه طريقة مناسبة للقيام بذلك ، ولكن رموز الوصول الخاصة بي قصيرة جدًا (دقيقة أو نحو ذلك). للتعامل مع مشكلات انتهاء صلاحية الرمز المميز من جانب العميل ، اتبعت هذا النهج ؛
في كل مرة يتم فيها تحميل الصفحة ، تتحقق مما إذا كان الرمز المميز منتهي الصلاحية ، وإذا كان الأمر كذلك ، فإنه يقوم بتحديثه. ومع ذلك ، إذا كان لا يزال صالحًا ، فإنه يستدعي الطريقة التي تتحقق من مقدار الوقت حتى انتهاء الصلاحية ، وتعيين المهلة التي ستعمل على تحديث رمز الوصول عند انتهاء الصلاحية. ثم تكرر هذه العملية طالما أن الزائر موجود في الموقع.

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

هذا يعود بالمللي ثانية حتى انتهاء الصلاحية:

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

أي ردود فعل على هذا النهج سيكون موضع ترحيب كبير

kunokdev - أعتقد أن هذه بداية جيدة. لقد قمت بنقل وظيفة مماثلة كان علي أن أحسب الوقت المتبقي إلى func الذي أعاد للتو قيمة منطقية اعتمادًا على ما إذا كانت منتهية الصلاحية أم لا ، وهذا جعل الكود الخاص بي أكثر سهولة وقابلية للقراءة بالإضافة إلى أنني لست بحاجة للقلق بشأن إعادة تعيين أجهزة ضبط الوقت. ثم أتحقق فقط مما إذا كان المستخدم منتهي الصلاحية أم لا في أي نوع من الطلبات التي تتطلب المصادقة. إذا كان لدي عداد للعد التنازلي أو شيء من هذا القبيل كان مرئيًا للعميل أو تصحيح الأخطاء ، فستكون وظيفتك مثالية. هذا هو 2 سنتي 👍

ألا يجب أن يكون مثال المصادقة / تسجيل الدخول هو أبسط مثال ممكن؟ أي ذاكرة تخزين ولا JWT أو أشياء رمزية غريبة. عادة عندما تفكر في شخص ما "قام بتسجيل الدخول" فهذا يعني أن لديه ملف تعريف ارتباط / جلسة نشطة.

لدي عميل وخادم يعملان لتسجيل الدخول. يستخدم JWT وخلفية (يمكن أن يكون عقدة أو django أو أيًا كان).

تحقق من ذلك وأي ملاحظات محل تقدير كبير

https://github.com/hugotox/AppStarter

الكود ذو الصلة هنا https://github.com/hugotox/AppStarter/blob/master/src/components/auth/login-required.js

hugotox تعجبني فكرة استخدام متجر Redux لتخزين بيانات المصادقة ولكن عندما تتصل بـ store.dispatch من getInitialProps عدة مرات ، كن جاهزًا للتأثيرات الجانبية غير المرغوب فيها ، عندما يتم عرض المكون المزين حتى إذا كانت عملية المصادقة لم تنته بعد. لنأخذ مثال الاستخدام من التعليمات البرمجية الخاصة بك:

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

في getInitialProps تتصل بـ verifyToken قبل verificationOk ، لذلك سيتم استدعاء MyPage.mapStateToProps مرتين (إذا استمع إلى store.auth.user) وأول مرة store.auth.user سيكون فارغًا حتى بالنسبة للصفحة التي تتطلب تسجيل دخول مستخدم.

بالأمس ، أصدرت أيضًا أول إصدار ويب من مجموعة أدوات بدء التشغيل الخاصة بـ Next.js ، لكنني بدأت مع Docker و Flow و fast-redux: https://github.com/dogada/microchain

أستخدم صور Docker المخصصة لخادم واجهة برمجة التطبيقات وتطبيق الويب التي يمكن تشغيلها على مجالات مختلفة ، لذلك ما زلت أبحث عن حل عملي يسمح بتسجيل الدخول إلى مستخدمين حقيقيين ولكن أيضًا إصدار رموز OAuth المميزة لعملاء الأجهزة المحمولة على سبيل المثال.

تضمين التغريدة هذا إلى حد كبير هو بالضبط الطريقة التي كنت أعمل بها. فيما يتعلق بالتقديم من جانب الخادم لعنوان URL في المرة الأولى للزيارة (لم يتم تسجيل الدخول مطلقًا) ، هل تقوم فقط باعتراضه ، مع ملاحظة عدم وجود ملف تعريف ارتباط وإعادة التوجيه إلى صفحة نوع pages / login.js على سبيل المثال؟

@ james-ff نشكرك على نشر ذلك ، حتى لو بدا الأمر وكأنك تصرخ في الفراغ.

لقد قيل في سلسلة الرسائل هذه عدة مرات ولكن يبدو أن الجميع ما زالوا يتجاهلون أنه لا ينبغي لهم

كتب مؤلف هذا المنشور جيدًا عن الخطأ في ذلك في عام 2016 ولكن للأسف لا يبدو أن الأمور قد تحسنت:

لسوء الحظ ، يبدو أنني وجدت الحد الأقصى لطول المقالة قبل أن يتوقف الناس عن القراءة - ظل العديد من المعلقين على Reddit و Hacker News يقترحون نفس "الحلول" مرارًا وتكرارًا ، متجاهلين تمامًا أنه تمت معالجتها بالفعل ووجدوا أنها غير عملية في المقالة نفسها.

كل من المقالة الأصلية ومخطط المتابعة رائعان بالرغم من ذلك.

iaincollins JWTs والتطبيقات / المصادقة بدون جلسات لها مزاياها ولا يزال الكثير من الأشخاص / الشركات (بما في ذلك Google) يرغبون في استخدامها. بعد قراءة القضية ضد JWTs ، ما زلت أعتقد أنه يجب أن يكون هناك مثالين / مكتبات رسمية

لقد كنت أحتفظ بعلامات تبويب عرضية فقط حول هذا الأمر ، ولكن تجربتي مع مصادقة JS العالمية هي تخزين JWT في ملف تعريف ارتباط HttpOnly . لا يوجد سبب حقيقي لاستخدام localStorage عندما يكون لديك خيار استخدام جانب الخادم من التطبيق لتخزين ملف تعريف الارتباط. إذا كنت بحاجة إلى الوصول إلى JWT لاستدعاءات واجهة برمجة التطبيقات عبر الأصل في المتصفح ، فيمكنك تمرير JWT في سيناريو من النوع __INITIAL_STATE__ (كن على دراية بنقاط ضعف XSS ، لكنك على الأقل لا "تخزن" من جانب العميل). للوصول إلى نفس الأصل ، سيتم تمرير ملف تعريف الارتباط ذهابًا وإيابًا (بافتراض أنك تستخدم withCredentials لـ axios ، أو credentials: 'include' للجلب) ، مما يلغي الحاجة إلى وضع JWT في JS على الإطلاق . يمكنك استخدام وكيل على جانب الخادم من التطبيق للحصول على JWT من ملف تعريف الارتباط HttpOnly ، ثم قم بإجراء مكالمات API متعددة الأصول أيضًا. أنت ترفض استدعاء الاختبار المبدئي في هذا السيناريو أيضًا. لكل منهم ، لكنني شخصياً لا أعتقد أن التخزين المحلي ضروري للتطبيقات العامة.

bjunc نعم ، من بين جميع الخيارات المتعلقة بالمكان الذي يجب تخزين JWT فيه (localStorage مقابل HttpOnly cookie vs. Redux ، أو ماذا لديك) ، قد أكون مخطئًا ولكني أعتقد أن الإجابة يجب أن تكون دائمًا ملف تعريف ارتباط HttpOnly. يبدو أن هذا تم ذكره مرات لا تحصى في العديد من المدونات والمنتديات. (لست متأكدًا من رموز التحديث - ربما يجب تخزينها في ملف تعريف ارتباط HttpOnly أيضًا؟) أعتقد أن مكان تخزين JWTs يجب أن يكون مسألة تم حلها بعيدًا عن بقية مزايا / عيوب JWTs.

حاولت أن أفعل إلى حد ما ما قلته بالضبط في مشروع خاص بي قبل أن أبدأ في تبني nextjs-starter و next-auth. لقد مرت بعض الوقت ولكن إذا كنت أتذكر بشكل صحيح ، أعتقد أن المشكلة التي واجهتها كانت أن خادم Express API الذي كنت أقوم بالمصادقة عليه (والذي كان يستخدم الجلسة السريعة) لم يكن يهيئ / يجلب الجلسة بشكل صحيح. سأحصل على سلوك غريب حيث سيتم بدء الجلسات عدة مرات. أعتزم استئناف عمل أكثر أو أقل مما وصفته إذا كان بإمكاني إصلاح ذلك. سأستمر أيضًا في العمل مع nextjs-starter و next-auth ، نظرًا لأن الجلسات تقضي على العديد من المخاوف الأخرى التي تطرحها JWT ، مثل كيفية إبطال الرموز المميزة.

مرة أخرى ، قد يكون من المفيد استخدام مثال رسمي (أو أمثلة). الكلمة الأساسية: رسمي ، وتعني أن مؤلفي Next.js قد درسوا جميع الاحتمالات ودمجوا فيها أفضل الأفكار والممارسات. من الناحية المثالية ، يتم استخدام ميزات ES6 / ES7 / ES8 الحديثة مثل الوعود وعدم التزامن / الانتظار.

@ kelleg1 يبدو أن HttpOnly ، المجال ، المسار ، انتهاء الصلاحية ، وما إلى ذلك) ؛ مما قد يؤدي إلى آثار جانبية غريبة كما تصفها. طريقة واحدة لتصحيح الأخطاء هي استخدام تطبيق أدوات التطوير-> ملفات تعريف الارتباط. إذا رأيت مجموعة من ملفات تعريف الارتباط تحمل الاسم نفسه ، فقد يوجهك ذلك إلى الاتجاه الصحيح.

على أي حال ، أنا لست عضوًا في الفريق الأساسي ، لذلك لا يمكنني المساعدة في مساهمة "رسمية" (وفي الواقع ، أنا أستخدم Nuxt.js ، وليس Next.js) ، لكن المبادئ هي نفسها. لقد جربت عدة طرق مختلفة للقيام بذلك (تقييم إيجابيات / سلبيات JWT وملفات تعريف الارتباط و CSFR و websocket CSWSH و localStorage وما إلى ذلك). توصلت في النهاية إلى استنتاج مفاده أن الطبيعة العالمية لـ Next / Nuxt أفسحت نفسها جيدًا لاستخدام ملفات تعريف الارتباط HttpOnly JWT. ربما يتوصل الآخرون إلى استنتاج مختلف ، لكنني شخصياً لست في معسكر "يا إلهي ، لا تستخدم JWT ، ألم تقرأ هذا المقال الذي يقول أن نظرية الحرب العادلة تُسبب لك السرطان !؟".

iaincollins آسف لإعادة هذا مرة أخرى ولكن كل برنامج تعليمي واحد على الويب يستخدم localStorage لحفظ الرمز المميز وأنت تقول إنه غير آمن. إذا كان الأمر كذلك ، أين من المفترض أن نخزن الرمز المميز؟

بسكويت! :د
نستخدم شيئًا مثل هذا:

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

قليل الكلام ولكنه آمن جدًا نظرًا لأن جافا سكريبت من جانب العميل لا يرى أبدًا رمزًا مميزًا وملف تعريف الارتباط هو http فقط ، وآمن ، وموقع ، ومُرسل تلقائيًا بواسطة axios أو غيره ...

مرحبًا بالجميع ، لقد قمت للتو بإنشاء مثال مصادقة مع ملفات تعريف الارتباط والإعادة. انظر هنا https://github.com/zeit/next.js/pull/4011

انتظر حتى أين انتهى هذا الموضوع؟ لم أتمكن أبدًا من العثور على مثال للمصادقة السريعة في الريبو الرسمي.

أرى الكثير من الحديث عن ملفات تعريف الارتباط والجلسات ، ولكن كيف يعمل ذلك مع تطبيق الهاتف المحمول الأصلي الخاص بي عندما يحتاج إلى الوصول إلى واجهة برمجة التطبيقات؟

jackjwilliams ألا يجب أن تدعم مكتبات HTTP لتطبيقات الجوال ملفات تعريف الارتباط أيضًا؟
https://stackoverflow.com/questions/1660927/iphone-make-post-request-handle-cookie
https://stackoverflow.com/questions/678630/how-do-i-make-an-http-request-using-cookies-on-android

يمكن القيام بذلك ، ولكن هذا ما تمثله JWT: p

لقد قمت للتو بقراءة مفصلة لهذا الموضوع بأكمله وأشعر أنني مضطر لتلخيص النتائج التي توصلت إليها.

يبدو أن هناك مشروعين قابلين للتطبيق مع وحدات المصادقة الصلبة التي تم أخذها في الاعتبار:

عمل ممتاز من قبل iaincollins و nmaro !

شكرا @ كوران :)

لقد قمت بتوثيق جميع التغييرات البرمجية التي أجريتها لإخراج الجوانب الخارجية لـ nextjs-starter في طلب السحب هذا https://github.com/iaincollins/nextjs-starter/pull/86

قد يكون هذا أقرب إلى مثال مصادقة صلبة لمخزون Next.js.

كان لدي مطلب مؤخرًا لتطبيق OAuth مع Office 365 ، لذلك اعتقدت أنني سأشارك مثالًا بسيطًا جدًا جمعته معًا هنا . إنه يحتاج إلى عمل (وهو ليس قريبًا من التطور مثل بعض الأمثلة المذكورة أعلاه) ولكن أعتقد أنه يمكن تعميمه في النهاية لاستخدام عملاء OAuth المختلفين أيضًا. إنه يستخدم العديد من الأمثلة الموضحة بالفعل في أمثلة Next.js repo بالإضافة إلى خيط المسارات المحمي هنا . على أي حال ، كنت أحسب أنني سأشاركها في حال أراد شخص ما مثالًا سريعًا لكيفية (ربما) القيام بذلك مع Microsoft.

لأي شخص مهتم بمصادقة رمزية بسيطة لـ JWT تعمل من جانب العميل والخادم ، حصلت على بعض المساعدة في دردشة Spectrum واعتقدت أنني سأشاركها معكم جميعًا. دائما موضع تقدير أي ردود فعل.

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

اهلا ياجماعة!
في ما يلي مثال آخر للمصادقة باستخدام next.js الذي أنشأته منذ شهرين ، ربما سيجده أحد الأشخاص مفيدًا:

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

Ooth 2.0 خارجا مع جديدة وأفضل مستندات

Ooth هو نظام إدارة هوية مستخدم تم إنشاؤه لـ node.js (مع وضع next.js في الاعتبار).

الاستراتيجيات المدعومة حاليًا:

  • أساسي: اسم المستخدم / كلمة المرور (بما في ذلك التحقق من البريد الإلكتروني ، نسيت pw وما إلى ذلك) ، ضيف ، facebook ، google
  • الثانوية: الجلسات القائمة على ملفات تعريف الارتباط ، JWTs

تحقق من هذا المثال المباشر الذي يجمع كل ذلك مع next.js ( شفرة المصدر ).

العديد من نماذج المصادقة هنا (وفي مجلد الأمثلة) ترجع جلسة المستخدم / الرمز المميز / إلخ من getInitialProps . بقدر ما أفهم ، عندما يتم عرض الصفحة من جانب الخادم ، فهذا يعني أنه سيتم إرسال معلومات جلسة المستخدم كجزء من استجابة صفحة HTML (كجزء من NEXT_DATA ) إلى المتصفح.

أرى مشكلتين للأمان في هذا النمط عند تشغيل getInitialProps من جانب الخادم:
1) يتم نقل جلسة المستخدم عبر الشبكة من خادم إلى متصفح. إذا كانت أي من هذه الطلبات تستخدم http:// وليس https:// ، فسيتم عرض رمز المستخدم ، وما إلى ذلك عبر الشبكة بنص عادي.

2) يتم إرجاع جلسة المستخدم من الخادم إلى المتصفح كجزء من صفحة HTML (في علامة البرنامج النصي NEXT_DATA ). يبدو أن وجود رمز المستخدم / إلخ مباشرة على صفحة HTML أمر محفوف بالمخاطر ، خاصة بعد تحليل الصفحة وعرضها بواسطة المتصفح ، وقد تكون البرامج النصية الأخرى التابعة لجهات خارجية قيد التشغيل الآن.

هل هذه القضايا التي تم تناولها بالفعل؟ هل هناك أي عوامل تخفيف لهذه التهديدات؟

لهذا السبب أستخدم ملفات تعريف الارتباط. انظر المثال الخاص بي هنا https://github.com/hugotox/nextjs-starter/blob/master/pages/_app.js

أخيرا! هنا يمكنك العثور على مثال مصادقة next.js كامل الإرساء مع الحاويات التالية:

  • next.js
  • المصادقة المصغرة (ooth)
  • api (رسم بياني)
  • تخزين الجلسة (redis)
  • وكيل عكسي صغير

يتم سحب كل شيء مع عامل البناء.

ملاحظة سريعة على JWTs. تتمتع JWTs بمزايا كونها عديمة الجنسية وجيدة للجوال وجيدة إذا كنت بحاجة إلى تمرير بيانات الاعتماد من مجال إلى آخر. العيب الرئيسي هو أنهم يعرضون المتصفح لـ XSS. في هذا المثال ، اخترت حلًا خالصًا يعتمد على جلسات ملفات تعريف الارتباط. ما زلت قادراً على تقسيم الأشياء في الخدمات المصغرة بفضل الوكيل العكسي (تعمل جميع الخدمات المصغرة ضمن نفس المجال) وتخزين الجلسة المشتركة.

https://github.com/nmaro/staart/tree/master/examples/staart
المثال الحي هو ، كالعادة: https://staart.nmr.io

أعتقد أنه من الحكمة التوضيح ، استخدام JWT لا "يعرضك" جوهريًا لـ XSS. بدلاً من ذلك ، إذا كان موقعك يشتمل على ثغرة XSS (ليس بسبب JWT نفسها) ، فقد يتم اختراق JWT (إلى جانب أي معلومات أخرى يمكن الوصول إليها من البرنامج النصي) ؛ بينما لن يمكن الوصول إلى ملفات تعريف الارتباط httpOnly . بغض النظر عن أنه يمكنك استخدام JWT كقيمة لملف تعريف الارتباط httpOnly !

يمكن أن تعمل حلول ملفات تعريف الارتباط فقط بشكل جيد للاتصال في نفس المجال ، ولكن إذا كان لديك واجهة برمجة تطبيقات بدون رأس (على سبيل المثال ، example.com calling api.example.com ) ، فهذا ليس حلاً حقًا إلا إذا كنت تريد متصفح وكيل الطلبات من example.com إلى api.example.com عن طريق إجراء مكالمات API الخاصة بك إلى example.com وإعادة توجيهها مع ملف تعريف الارتباط الملحق بالطلب (والذي يأتي مع مجموعة الإيجابيات / العيوب الخاصة به) .

أنا شخصياً أشعر أن سلبيات نظرية الحرب العادلة مبالغ فيها إلى حد كبير ، ويمكن التخفيف من حدتها بسهولة من خلال مجموعة كبيرة من إجراءات الحماية المطبقة بشكل شائع. ليس أقلها ، قائمة سوداء رمزية تشير إلى مطالبة jti (على سبيل المثال ، الإصدار 4 UUID) في حالة تعرض الرمز المميز للاختراق قبل انتهاء الصلاحية.

مرحبا bjunc نعم شكرا

بغض النظر عن أنه يمكنك استخدام JWT كقيمة لملف تعريف الارتباط httpOnly!

نعم ، أود فقط أن أضيف أن ذلك يزيل الميزة الوحيدة لـ JWT لنقل بيانات الاعتماد بين المجالات.

قائمة سوداء رمزية

يؤدي ذلك ، والممارسة الشائعة الأخرى المتمثلة في رمز التحديث إلى إزالة الميزة الأخرى لـ JWT المتمثلة في كونك عديم الجنسية حقًا.

هذا هو فهمي للوضع:

  • إذا كنت بحاجة إلى مصادقة المواقع المتقاطعة ، فاستخدم JWT <- ولكن إذا أمكن تجنب ذلك بسبب الأمان
  • إذا كنت بحاجة إلى المصادقة من أي عميل ليس مستعرضًا ولا يحتوي على مشكلة XSS (مثل تطبيق سطح المكتب أو تطبيق الهاتف المحمول) ، فاستخدم JWT
  • بخلاف ذلك ، استخدم الجلسات القائمة على ملفات تعريف الارتباط ، لأن الحل المستند إلى JWT سيكون إما أقل أمانًا (XSS) أو لا يكون عديم الجنسية بالفعل (قوائم سوداء) ، أو يتطلب منك استخدام وكيل لإبقاء كل شيء تحت نفس المجال على أي حال.

لقد كتبت مقالًا على موقع Medium على حسابات المستخدمين / المصادقة على Next.js.
إنه برنامج تعليمي مكثف وتفكيري عن التفكير في ما يقرب من عامين من التطوير والتفكير في وقت الفراغ ( تعليقي الأول على هذه المسألة هو من فبراير 2017).

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

استمر في ربط JWT بكونك أقل أمانًا. JWT لا تجعل موقعك أقل أمانًا. إنها ليست في حد ذاتها ثغرة أمنية في XSS. إذا كان لديك استغلال XSS ، فأنت في مشكلة متساوية بغض النظر. حتى مع ملف تعريف الارتباط httpOnly ، قد لا يتمكن المهاجم من قراءة قيمة ملف تعريف الارتباط ، ولكن لا يهم لأنه يمكنه تشغيل تعليمات برمجية عشوائية - مثل طلبات XHR التي ستمرر ملفات تعريف الارتباط للجلسة تلقائيًا (تعمل بشكل أساسي كـ هجوم CSRF). إذا كانت واجهة برمجة التطبيقات الخاصة بك متعددة المجالات ، وكنت تقدم طلبات من متصفح إلى خادم ، فإن JWT في مكان ما في الكود على أي حال (سواء كانت الحالة الأولية ، أو التخزين المحلي). إذا كنت تستخدم Axios ، فربما تكون قد عيّنت الإعدادات الافتراضية العامة ، حيث يحتاج المهاجم فقط إلى تقديم طلب Axios ولا يقلق بشأن المصادقة.

أيضًا ، لا يمكنك التحدث حقًا عن XSS دون الحديث أيضًا عن CSRF ؛ حيث يتم استهداف ملفات تعريف الارتباط للمصادقة على وجه التحديد. حتى مع إعداد الوكيل العكسي ، سيسمح هجوم CSRF للمهاجم بتنفيذ الطلبات المصادق عليها ضد واجهة برمجة التطبيقات الخاصة بك.

راجع للشغل ، لمجرد أنك وضعت JWT في ملف تعريف ارتباط (على سبيل المثال ، معرفة ما إذا كان المستخدم قد قام بتسجيل الدخول) ، فهذا لا يعني أنك ممنوع من استخدام قيمة ملف تعريف الارتباط (على سبيل المثال JWT) لخادم متعدد المجالات إلى- الوصول إلى خادم API عند تحميل الصفحة (والذي يعمل أيضًا مع سيناريو الوكيل العكسي). كما أنك لست ممنوعًا من اجتياز JWT في الحالة الأولية وكذلك لطلبات الخادم من المتصفح إلى واجهة برمجة التطبيقات. إنهما ليسا متعارضين.

جانبا ، أجد فكرة JWT "عديمة الجنسية" مبالغ فيها ومحدودة في التطبيق لغالبية حالات الاستخدام. على سبيل المثال:

  • الأذونات المستندة إلى الموارد / الديناميكية (على سبيل المثال ، ليس فقط " can edit Post " ، ولكن بدلاً من " can edit Post:1634 ").
  • ماذا لو تم حظر / حذف حساب المستخدم؟
  • لم يدفعوا اشتراكهم الشهري ؛ الذي يخنق الوظيفة؟
  • في القائمة السوداء الرمز المميز (أعلاه)؟

أنت لا تخبز كل ذلك في JWT ، مما يعني أنه يجب عليك الانغماس في طبقة المجال (أي قاعدة البيانات) لمعرفة ذلك. لقد قمت للتو بتحميل المورد ، لذا يمكنك وضعه في المكان الذي يمكن لبقية التطبيق الوصول إليه ، والآن لديك الحالة. أجد أنه من السخف حقًا التفكير في أن كل ما تحتاج لمعرفته حول هذا الموضوع سيتم تحويله إلى رمز مميز ؛ مع إبقائه مجهول الهوية وخفيف الوزن في الوقت نفسه. بدون الاستطراد كثيرًا ، هناك حجة للطلبات "عديمة الجنسية" في الاتصال بين الخدمات ، ولكن حتى ذلك أجده غير عملي (على الأقل من حيث صلته بمفهوم خبز ما تحتاج لمعرفته حول الموضوع في JWT) .. .

استراتيجيات المصادقة Ooth متاحة في الوقت نفسه (جديد بالخط العريض):

  • محلي (اسم المستخدم / البريد الإلكتروني / كلمة المرور)
  • موقع التواصل الاجتماعي الفيسبوك
  • متصفح الجوجل
  • ضيف
  • باتريون
  • تويتر
  • Authy (Twilio) - بدون كلمة مرور عبر الرسائل القصيرة

jaredpalmer كتبت
مثل php ، فإن الوحدة الذرية لـ Next هي الصفحة. واحدة من أروع الميزات هي أنه لا يقوم بتحميل كل صفحة إلا عند الطلب. باستخدام المصادقة من جانب العميل فقط ولكن مع عرض الخادم ، يتم في الواقع تنزيل js لتلك الصفحة المحمية بواسطة المتصفح. في المستقبل ، عندما يضيف Next مهام سير عمل الخادم ، نأمل أن تتمكن من حظر العرض وإعادة التوجيه على الخادم لمنع ذلك تمامًا. سيتطلب ذلك ملفات تعريف الارتباط ، والجلسات ، ومخازن جلسات AFAIK ، ولكن هذا هو مجرد تكلفة القيام بتطبيقات مختلطة مثل هذه.

نحن بعد عامين. هل هناك سير عمل خادم لمنع تحميل js للصفحات المحمية؟
timneutkens ربما وضع محتوى محمي في منطقة أخرى؟
كيف يمكنني منع الوصول إلى المحتوى المحمي تمامًا؟

lishine لديك ServerResponse في getInitialProps من صفحتك - يمكنك بسهولة إعادة توجيه شخص لا يتمتع بامتيازات.

هل هناك مثال على المصادقة مع الإعادة؟

هل هناك مثال على المصادقة مع الإعادة؟

يمكنك تجربة هذا المثال الذي يستخدم redux ، ومعرفة ما إذا كان يعمل من أجلك ...
يمكنك العثور عليه في مكان ما في هذا الموضوع ، ولكن في حالة عدم العثور عليه ، فإليك ما يلي:
https://github.com/alan2207/nextjs-jwt-authentication

أعتقد أن هذه مشكلة أكثر تعقيدًا عند استخدام getInitialProps لنتائج استدعاء API من جانب الخادم ، لأن DOM الظاهري يستخدم النتائج القديمة بعد إجراء LOGOUT-LOGIN. أفكر في الحل

_EDITED_
وإليك إجابتي مع إمكانية إعادة الملاحظة

| الجانب | المصادقة | المهام |
| --- | --- | --- |
| الخادم | صحيح | إحضار البيانات الأولية (مع وكيل ملف تعريف الارتباط للطلب). |
| الخادم | خطأ | إظهار صفحة تسجيل الدخول ، وجلب البيانات بعد تسجيل الدخول. |
| العميل | صحيح | إحضار البيانات الأولية. |
| العميل | خطأ | إظهار صفحة تسجيل الدخول ، وجلب البيانات بعد تسجيل الدخول. (يحدث هذا فقط عندما تنتهي الجلسة في نقل صفحة إلى صفحة) |

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

يبدو معقدًا عندما يحدث شيء بسيط ، على غرار:

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

تم دمج هذا المثال كجزء من Next.js 8
https://github.com/zeit/next.js/tree/canary/examples/with-cookie-auth

timneutkens شكرا على الرابط.

انظر إلى https://github.com/zeit/next.js/blob/canary/examples/with-cookie-auth/www/utils/auth.js#L26 -L34 ... لا ينبغي أن يكون هناك نوع من تحقق بعد أن تم استدعاء auth() ؟

يؤدي اختبار المثال بدون ملف تعريف الارتباط إلى استدعاء Profile.getInitialProps() ، بينما كنت أعتقد أن إعادة التوجيه ستحدث قبل محاولة الحصول على المزيد من "الدعائم الأولية" ...

لقد قدمت مثالًا هنا يحتوي على عرض مسبق من جانب الخادم + مصادقة ث / أبولو

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

يرجى أن تضع في اعتبارك أن إرشادات أمان OWASP توصي بعدم تخزين رمز JWT المميز في التخزين المحلي ، أي "يمكن استخدام برمجة نصية واحدة عبر الموقع لسرقة جميع البيانات الموجودة في هذه الكائنات ، لذا يوصى مرة أخرى بعدم تخزين المعلومات الحساسة في التخزين المحلي."

إليك Auth0: مكان تخزين الرموز و Tom Abbott: مكان تخزين JWTs - ملفات تعريف الارتباط مقابل تخزين الويب HTML5 .

فيما يلي مثال على الخادم الوكيل Nuxt.js + Express.js + خلفية Django. حيث يتم استخدام خادم Express للحصول على طلب مصادقة وكيل للخلفية الفعلية ويتعامل مع حماية CSRF عند استخدام تخزين رمز JWT في ملف تعريف ارتباط (يفرض بعض القيود على طول الرمز المميز / مقدار المعلومات التي يمكن تخزينها في رمز JWT المميز): https: / /github.com/danjac/nuxt-python-secure-example

timneutkens أحتاج إلى بعض المستندات حول كيفية إرسال رمز مميز من ملف تعريف الارتباط 🍪 إلى البرامج الوسيطة للإعادة المخصصة لـ SSR. أحصل على ملفات تعريف الارتباط داخل _app.js. ولكن كيف يمكنني تمريره إلى customApimiddleware. حيث كتبت طلبات جلب. شكرا

لقد كتبت مقالًا على موقع Medium على حسابات المستخدمين / المصادقة على Next.js.
إنه برنامج تعليمي مكثف وتفكيري عن التفكير في ما يقرب من عامين من التطوير والتفكير في وقت الفراغ ( تعليقي الأول على هذه المسألة هو من فبراير 2017).

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

أعتقد أن هذا هو أحد أفضل البرامج التعليمية للتعامل مع المصادقة في تطبيق nextj.js. لقد رأيت أشياء مثل تخزين الرموز المميزة في localStorage (XSS) ، وتخزين الرموز المميزة في ملفات تعريف الارتباط (دون التعامل مع CSRF) ، وحتى تخزين الرموز المميزة في ملفات تعريف الارتباط من المتصفح (كل من XSS و CSRF عرضة للخطر).

أنا معجب حقًا بحلك باستخدام الوكيل العكسي ومشاركة معلومات الجلسة بين الخدمات المختلفة. أود حقًا عدم إنشاء خادم مخصص لتطبيق next.js ، لكنني أعتقد أنه الطريقة الأكثر مباشرة للتعامل مع الجلسات ومنع csrf (وربما إضافة الوكيل العكسي). قد ينتهي بي الأمر بإنشاء مشروع مترابط (لكل من تقديم التطبيق والتعامل مع عمليات db وما إلى ذلك).

لقد رأيت أن بعض الأشخاص (بما في ذلك ZEIT) يحافظون على واجهات برمجة التطبيقات عديمة الحالة والسماح لتطبيق next.js بمعالجة الجلسة. يقوم بتمرير الرموز المميزة إلى واجهات برمجة التطبيقات. لكن الذهاب مع الجلسات يجعل الأمور أكثر إحكامًا وأقل تعقيدًا.

سيكون من الأفضل حقًا الحصول على مثال مصادقة كامل لـ next.js. باستخدام أشياء مثل المصادقة لواجهات برمجة التطبيقات الخارجية ، والاحتفاظ بالجلسة في تطبيق next.js ، ومشاركة الجلسة بين الخدمات أو تمرير الرموز المميزة إليها ، وربما تحديث الرموز المميزة إذا انتهت صلاحيتها. (يكتب الكثير من الأشخاص كثيرًا عن JWTs ويستخدمونها فقط في دروسهم التعليمية ، لكن في الغالب لا تنتهي صلاحيتها أو حتى تحديثها.)

على أي حال ، لقد كتبت أحد أكثر البرامج التعليمية اكتمالاً حول هذا الموضوع. إذا شكرا!

آمل حقًا أن تكون هناك أمثلة وتوثيق أكثر اكتمالًا ووضوحًا.

سيكون من الأفضل حقًا الحصول على مثال مصادقة كامل لـ next.js. باستخدام أشياء مثل المصادقة لواجهات برمجة التطبيقات الخارجية ، والاحتفاظ بالجلسة في تطبيق next.js ، ومشاركة الجلسة بين الخدمات أو تمرير الرموز المميزة إليها ، وربما تحديث الرموز المميزة إذا انتهت صلاحيتها. (يكتب الكثير من الأشخاص كثيرًا عن JWTs ويستخدمونها فقط في دروسهم التعليمية ، لكن في الغالب لا تنتهي صلاحيتها أو حتى تحديثها.)

أنا أيضًا في حيرة بشأن النهج الذي يجب اختياره.
شكرا جزيلا على رابط المقال لك.
حاليًا ، ما هي التطبيقات التي استقرت عليها؟
هل عثرت على مثال تفويض شامل للإصدار v9.3 + التالي؟

يستحق التحقق من نهج Auth0 الجديد القائم على ملفات تعريف الارتباط
(بالطبع هذا خاص بموفر هوية معين ، ولكن قد يكون النهج مفيدًا في رؤيته)
https://github.com/auth0/nextjs-auth0

  • من الرائع حقًا أنه يمكنك "إنشاء وكيل" لطلبات api عبر مسارات nextjs api (حتى عبر مسار ديناميكي واحد)
  • بعد ذلك ، لن تضطر أبدًا إلى كشف رموز الوصول وما إلى ذلك إلى جانب العميل (نظرًا لأن مسارات nextjs api تنفذ جانب الخادم فقط) ، يمكن لجانب الخادم الحصول على رموز الوصول وما إلى ذلك من خلال مكتبة auth وملف تعريف الارتباط بسر
  • سوف يقوم كود العميل الخاص بك باستدعاء مسارات nextjs api الخاصة بك ، وستقوم مسارات api بعد ذلك بتنفيذ طلب api الحقيقي

ضع في اعتبارك أنهم يقولون إن هذا النهج "تجريبي" في ReadMe

يستحق التحقق من نهج Auth0 الجديد القائم على ملفات تعريف الارتباط
(بالطبع هذا خاص بموفر هوية معين ، ولكن قد يكون النهج مفيدًا في رؤيته)
https://github.com/auth0/nextjs-auth0

  • من الرائع حقًا أنه يمكنك "إنشاء وكيل" لطلبات api عبر مسارات nextjs api (حتى عبر مسار ديناميكي واحد)
  • بعد ذلك ، لن تضطر أبدًا إلى كشف رموز الوصول وما إلى ذلك إلى جانب العميل (نظرًا لأن مسارات nextjs api تنفذ جانب الخادم فقط) ، يمكن لجانب الخادم الحصول على رموز الوصول وما إلى ذلك من خلال مكتبة auth وملف تعريف الارتباط بسر
  • سوف يقوم كود العميل الخاص بك باستدعاء مسارات nextjs api الخاصة بك ، وستقوم مسارات api بعد ذلك بتنفيذ طلب api الحقيقي

ضع في اعتبارك أنهم يقولون إن هذا النهج "تجريبي" في ReadMe

هذه المقالة مفيدة للغاية وتغطي الكثير من الهندسة المعمارية المختلفة.
https://auth0.com/blog/ultimate-guide-nextjs-authentication-auth0/

إن استخدام مسارات API كوكيل ، وتسجيل الدخول / تسجيل الخروج عبر مسارات API ، والحصول على الرمز المميز من API ، وتعيينه على أنه ملف تعريف ارتباط HttpOnly هو نهج قوي على ما أعتقد.
قد يكون أحد المخاوف هو CSRF ، ولكن يمكنك بسهولة إنشاء بعض الحلول باستخدام حزمة csrf npm (وليس csurf ، لكن هذا قد ينجح أيضًا).

onderonur ، شكرًا على article0.
وهذا يعني أنه يوجد حاليًا مثال موثوق به أو على الأقل مثال ضئيل للتنفيذ على Jwt خالص مع next.js؟
لا أريد إنشاء طبقة متقدمة مع ملفات تعريف الارتباط وإعدادها. في تطبيق csr ، قمنا ببساطة بتخزين الرمز المميز في التخزين المحلي وإرساله مع الطلب.

onderonur ، شكرًا على article0.
وهذا يعني أنه يوجد حاليًا مثال موثوق به أو على الأقل مثال ضئيل للتنفيذ على Jwt خالص مع next.js؟
لا أريد إنشاء طبقة متقدمة مع ملفات تعريف الارتباط وإعدادها. في تطبيق csr ، قمنا ببساطة بتخزين الرمز المميز في التخزين المحلي وإرساله مع الطلب.

لقد استخدمت هذه الطريقة لإحدى المستودعات الخاصة بي ولكنها لا تزال في المسودة ، لذا تأكد من اختبارها بنفسك :)
https://github.com/onderonur/post-gallery
في الواقع "طبقة ملف تعريف الارتباط" ليست شيئًا متقدمًا. ما عليك سوى الاتصال بنقطة نهاية تسجيل الدخول الخاصة بواجهة برمجة التطبيقات من خلال مسار واجهة برمجة التطبيقات /api/login وإذا نجح الطلب ، فقم بتعيين الرمز المميز في ملف تعريف ارتباط httpOnly .
يمكنك التحقق من الريبو الخاص بي للحصول على نفس التنفيذ بالضبط.

خيار آخر هو (إذا كنت تريد أن يكون لديك نفس التدفق تقريبًا مثل تعيين الرمز المميز في التخزين المحلي) ، يمكنك استخدام حزمة js-cookie npm ، واستدعاء نقطة نهاية تسجيل الدخول الخاصة بك مع طلب من جانب العميل ، وإنهاء إذا عاد رمز مميز ، قم بتعيينه في ملف تعريف ارتباط. وعندما تقدم طلبًا (من خلال معترض أكسيوس ، إلخ) ، اقرأ قيمة ملف تعريف الارتباط وقم بتمريرها إلى واجهة برمجة التطبيقات الخاصة بك كرأس طلب. لقد رأيت الكثير من (وحتى بعض التطبيقات الشائعة) تستخدم هذا الأسلوب. لكن هذا قليلاً غير آمن. لأنه لا يمكنك تعيين ملفات تعريف الارتباط httpOnly في المتصفح. لذلك ، سيكون JavaScript قادرًا على قراءة ملف تعريف الارتباط المميز الخاص بك. وبالتالي ، سيكون هناك ضعف XSS.

نقدر أن هذا الموضوع قديم (وموضوع طويل الأمد بشكل عام) ولكن بالنسبة لأولئك الذين يبحثون عن مراجع أو أمثلة إضافية ، فقد اخترنا العمل على NextAuth.js v2 مؤخرًا. لم أذكره كقابس - إنه مشروع مفتوح المصدر وقد ساعد فيه مجموعة من الأشخاص - ولكنه سهل الاستخدام للغاية وقد يكون الكود والنهج مفيدًا كمرجع للأشخاص.

بالنسبة إلى بعض الخلفيات ، مثل NextAuth v1 ، فإنه يستخدم ملفات تعريف الارتباط الموقعة والمسبقة و HTTP فقط ، لتجنب المزالق الأمنية الشائعة لاستخدام الرموز المميزة من جانب العميل.

يدعم NextAuth.js v2 تسجيل الدخول باستخدام Apple و Google و Facebook و Twitter و GitHub و Auth0 و Okta و Slack و Discord وموفري OAuth الآخرين (يدعم كلاً من 1.x و 2.x). يمكنك استخدامه مع MySQL و MariaDB و Postgres و MongoDB - أو لا توجد قاعدة بيانات جميعها (فقط OAuth و JSON Web Tokens للحصول على حل بدون خادم بنسبة 100٪).

الاستخدام بسيط للغاية ، هناك طريقة ثابتة عالمية تسمى session() وخطاف React يسمى useSession() يمكنك استخدامه في جانب عميل المكونات:

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

تم تصميمه لـ Next.js 9.x و Serverless ، ولا يحتوي على عناصر تابعة مثل Express أو PassportJS. يتضمن موفر مصادقة يمكنك استخدامه في _app.js لإضافة حالة المصادقة تلقائيًا إلى جميع الصفحات ؛ إنه يعمل من أجل تقديم جانب العميل والخادم.

لمزيد من المعلومات ، راجع next-auth.js.org أو تحقق من next-auth @ beta على NPM

لا يزال العمل قيد التقدم - ما زلنا نعمل على تحسين التوثيق ونموذج الحدث - مع تاريخ إصدار مستهدف في بداية ~ منتصف يونيو.

نقدر أن هذا الموضوع قديم (وموضوع طويل الأمد بشكل عام) ولكن بالنسبة لأولئك الذين يبحثون عن مراجع أو أمثلة إضافية ، فقد اخترنا العمل على NextAuth.js v2 مؤخرًا. لم أذكره كقابس - إنه مشروع مفتوح المصدر وقد ساعد فيه مجموعة من الأشخاص - ولكنه سهل الاستخدام للغاية وقد يكون الكود والنهج مفيدًا كمرجع للأشخاص.

بالنسبة إلى بعض الخلفيات ، مثل NextAuth v1 ، فإنه يستخدم ملفات تعريف الارتباط الموقعة والمسبقة و HTTP فقط ، لتجنب المزالق الأمنية الشائعة لاستخدام الرموز المميزة من جانب العميل.

يدعم NextAuth.js v2 تسجيل الدخول باستخدام Apple و Google و Facebook و Twitter و GitHub و Auth0 و Okta و Slack و Discord وموفري OAuth الآخرين (يدعم كلاً من 1.x و 2.x). يمكنك استخدامه مع MySQL و MariaDB و Postgres و MongoDB - أو لا توجد قاعدة بيانات جميعها (فقط OAuth و JSON Web Tokens للحصول على حل بدون خادم بنسبة 100٪).

الاستخدام بسيط للغاية ، هناك طريقة ثابتة عالمية تسمى session() وخطاف React يسمى useSession() يمكنك استخدامه في جانب عميل المكونات:

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

تم تصميمه لـ Next.js 9.x و Serverless ، ولا يحتوي على عناصر تابعة مثل Express أو PassportJS. يتضمن موفر مصادقة يمكنك استخدامه في _app.js لإضافة حالة المصادقة تلقائيًا إلى جميع الصفحات ؛ إنه يعمل من أجل تقديم جانب العميل والخادم.

لمزيد من المعلومات ، راجع next-auth.js.org أو تحقق من next-auth @ beta على NPM

لا يزال العمل قيد التقدم - ما زلنا نعمل على تحسين التوثيق ونموذج الحدث - مع تاريخ إصدار مستهدف في بداية ~ منتصف يونيو.

عمل عظيم هذا!
هل يمكن استخدام هذا من جانب العميل وحده؟ على سبيل المثال ، لدي تطبيق Rails API - واستخدم JS التالي من جانب العميل.

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات