#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. Решение этой проблемы можно посмотреть здесь и здесь.