В этом руководстве описывается, как использовать Github в качестве поставщика единого входа (SSO) OAuth для одностраничного приложения (SPA), написанного на JavaScript с использованием библиотеки React. Используется поток предоставления кода авторизации. (Чтобы узнать больше о типах грантов в OAuth, прочтите Руководство по грантам OAuth 2.0.)

Зрительская аудитория

Чтобы получить максимальную отдачу от этого руководства, вы должны быть знакомы с грантами JavaScript, React, Redux, Node.js, Koa, Passport и OAuth.

Проблема

В потоке предоставления авторизации OAuth пользователь перенаправляется на другую страницу для завершения процесса входа. В описанной ниже последовательности операций в качестве поставщика единого входа используется Github. сервер относится к внутреннему серверу SPA.

  1. Пользователь посещает https://example.com/, и SPA загружается в браузере.
  2. Пользователь щелкает ссылку для входа, которая открывает https://example.com/auth/login в браузере.
  3. Сервер перенаправляет браузер на https://github.com/login/oauth/authorize. Откроется страница входа Github OAuth.
  4. Пользователь входит в систему.
  5. Github перенаправляет браузер на https://example.com/login/oauth/callback.
  6. Сервер отправляет HTTP POST в Github.
  7. Github отвечает полезной нагрузкой JSON, которая содержит токен доступа, тип токена, срок действия токена и токен обновления.
  8. Сервер использует токен доступа для запроса профиля пользователя Github.
  9. Сервер заполняет сеанс пользователя.
  10. Сервер перенаправляет браузер на страницу успеха.

Решение

Используя новую вкладку браузера и метод window.postMessage (), вы можете избежать перенаправления пользователя на другую страницу для завершения процесса входа. В следующей измененной последовательности операций сервер относится к внутреннему серверу SPA. клиент - это браузер пользователя.

  1. Пользователь посещает https://example.com/, и SPA загружается в браузере.
  2. Пользователь нажимает кнопку входа в SPA. Откроется новая вкладка браузера и отобразится https://example.com/auth/login.
  3. Сервер перенаправляет браузер на https://github.com/login/oauth/authorize.
  4. Пользователь получает страницу входа на Github OAuth и выполняет вход.
  5. Github перенаправляет браузер на https://example.com/login/oauth/callback.
  6. Сервер отправляет HTTP POST в Github.
  7. Github отправляет ответ JSON, содержащий токен доступа, тип токена, срок действия токена и токен обновления.
  8. Сервер использует токен доступа для отправки GET HTTP-запроса для профиля пользователя Github.
  9. Github отправляет ответ JSON с профилем пользователя.
  10. Сервер заполняет сеанс пользователя и возвращает страницу успеха HTML с полезной нагрузкой JavaScript, содержащей вызов window.postMessage() с объектом пользователя.
  11. Клиент выполняет полезную нагрузку JavaScript на открытой вкладке браузера. Вызов window.postMessage() передает объект пользователя на исходную вкладку браузера, на которой запущен SPA.

После завершения последовательности операций SPA на исходной вкладке браузера имеет копию объекта пользователя.

Реализация

В следующем коде измененная последовательность потоков показана как для SPA, так и для сервера.

СПА

Следующие файлы определяют SPA.

App.js

В App.js определены две функции-обработчики: handleLogIn и handleLogOut. В handleLogIn вызов loginTab создает новую вкладку. В возвращенном обещании объект user передается injectUser, который является создателем действия Redux. Функция handleLogOut отправляет действие logoutUser.

В функции render() isAuthenticated и currentUser обеспечивают доступ к статусу аутентификации пользователя и, если пользователь вошел в систему, к объекту пользователя. Кнопка входа отображается только в том случае, если пользователь не вошел в систему. В противном случае отображается кнопка выхода.

Функции mapStateToProps и mapDispatchToProps определяют, какое состояние передается в реквизитах для этого компонента и какие действия могут быть отправлены.

userActions.js, userActionTypes.js, userReducer.js

Состояние Redux настраивается в следующих файлах:

  • userActions.js: определяет injectUser и logoutUser
  • userActionTypes.js: определяет константы действия Redux
  • userReducer.js: Определяет редуктор для пользовательского объекта.

openWindow.js

Функция, определенная в loginTab(), открывает новую вкладку с myUrl в качестве цели и возвращает обещание. Обещание преобразуется в значение, переданное из window.postMessage().

Сервер

Следующие файлы определяют сервер приложений для SPA.

userRoutes.js

Сервер должен определить несколько маршрутов для потока предоставления кода авторизации OAuth. Для модуля Паспорт необходимо определить следующие конечные точки:

  • / auth / github: Запрошено клиентом для начала потока OAuth.
  • / auth / github / callback: запрашивается Github во время потока OAuth.

В функции обратного вызова для маршрута /auth/github/callback вызывается ctx.render(), чтобы вернуть страницу успеха.

success.html

Когда страница success.html загружается, она вызывает window.postMessage() с внедренным объектом пользователя.

Заключение

Подход, описанный в этом руководстве, показывает, как использовать поток предоставления кода авторизации, предлагаемый Github OAuth, избегая при этом перенаправления HTTP.