Auth0 — Как доверять и сохранять информацию о пользователе в пользовательском API или серверной части?

#node.js #express #security #authentication #auth0

#node.js #экспресс #Безопасность #аутентификация #auth0

Вопрос:

Я пытаюсь выяснить, как «доверять» пользовательской информации (таким вещам, как имя, электронная почта и sub претензия) на моем сервере API для приложения react native. Я следовал официальному руководству по быстрому запуску react native от auth0 здесь:

https://auth0.com/docs/quickstart/native/react-native/

и я видел 4 или 5 итераций этого способа в Интернете. Да, это здорово, у нас есть метод аутентификации во внешнем интерфейсе, при котором мы получаем id_token и access_token возвращаемый нам во внешнем интерфейсе. access_token Все в порядке, и я это полностью понимаю, т. Е. я сохраняю ее в локальном хранилище на устройстве, добавляю в Authorization заголовок и использую промежуточное программное обеспечение jwt для защиты маршрутов (также предоставляется auth0 на странице пользовательских API):

 var express = require('express');
var app = express();
var jwt = require('express-jwt');
var jwks = require('jwks-rsa');

var port = process.env.PORT || 8080;

var jwtCheck = jwt({
      secret: jwks.expressJwtSecret({
          cache: true,
          rateLimit: true,
          jwksRequestsPerMinute: 5,
          jwksUri: 'https://<myauth0domain>/.well-known/jwks.json'
    }),
    audience: '<myapiendpoing>',
    issuer: '<myauth0domain>',
    algorithms: ['RS256']
});

app.use(jwtCheck);

app.get('/authorized', function (req, res) {
    res.send('Secured Resource');
});

app.listen(port);
  

Теперь, наконец, к тому, где я застрял: что касается id_token , как мне сохранить любую информацию об идентификаторе пользователя на моем сервере и быть уверенным, что это действительно этот пользователь?Я хочу сохранить такие вещи, как их имя и адрес электронной почты, поскольку в моем приложении также есть таблица пользовательских настроек, где пользователи могут изменять информацию своего профиля.

Конечно, я не могу просто переслать id_token для использования в качестве «доверенного» сервера идентификации. В тот момент, когда происходит этап подключения между сервером auth0, затем устройством, а затем моим API, злоумышленник может подделать значения в id_token — это, в конце концов, просто JSON.

Мое текущее решение вызывает встроенную /userinfo конечную точку auth0 из моей серверной части — вы передаете access_token и получаете информацию о пользователе обратно, но, очевидно, это не очень эффективно. Чтобы попытаться избежать проблем с производительностью, я делаю это один раз, чтобы настроить информацию об учетной записи, а затем использую sub утверждение (которое является идентификатором пользователя) из access_token , чтобы идентифицировать пользователя во всех последующих конечных точках, связанных с пользовательскими настройками. sub Утверждению можно доверять после прохождения промежуточного программного обеспечения JWT, верно?

Единственным другим решением, которое я мог придумать, было изменение URI обратного вызова авторизации в моем приложении react на конечную точку в моем API, а не на URI, ведущий обратно в приложение react native, но тогда, я думаю, это означает реализацию всего сеанса пользователя и истории паспорта в express. Возможно, мне все равно придется это сделать, если я хочу выполнить какое-либо пользовательское действие в API?

Говорят, что OAuth значительно упрощает работу, но на данный момент я просто очень-очень смущен, доверяя, действительно ли пользователь тот, за кого они себя выдают на стороне сервера. На самом деле, какой вообще смысл иметь id_token на стороне пользовательского интерфейса? Насколько я понимаю, значениям в id_token можно «доверять» только для чисто демонстрационных целей. Вы никогда не сможете использовать их в качестве идентифицирующих ключей в запросах к серверу.

Ответ №1:

Ответ заключается в использовании ключа подтверждения для потока обмена кодами (PKCE). В этом потоке вы генерируете средство проверки кода и претендент и получаете одноразовый код, который можно использовать для получения токена аутентификации, токена обновления и токена идентификатора. Этот запрос может быть выполнен на стороне клиента.

Используя этот код одноразового использования, мы можем сделать второй запрос, для реальных токенов, с наших собственных серверов. Поскольку этот запрос выполняется с вашего доверенного сервера (не на клиенте, и Auth0 не позволяет вам отправлять запрос на клиенте!), мы можем быть уверены, что содержимое возвращенного токена id не было изменено. (т.е. это межмашинное соединение вашего сервера API с Auth0)

Это также отличный момент времени, чтобы проверить, существует ли пользователь уже (и если нет, сгенерируйте учетную запись на стороне сервера или информацию о пользователе, используя содержимое токена id). В идеальной ситуации пользователь должен аутентифицироваться только один раз (таким образом, попадая в эту конечную точку один раз), и мы можем постоянно обновлять токены авторизации с помощью токена обновления, который мы надежно сохранили в их учетной записи.

Единственным исключением является истечение срока действия самого токена обновления, при котором мы просим их повторно пройти аутентификацию.


Редактировать:

Для очень любопытных, я столкнулся с дополнительной, хотя и немного не связанной проблемой при реализации PKCE конкретно с проектами React Native Expo. Решение этой проблемы можно посмотреть здесь и здесь.