Авторизация бустера в двух словах


Обзор

После нескольких успешных проектов с использованием Booster Framework для различных клиентов и внутренних проектов, часто возникает вопрос: «Как Booster работает с авторизацией?
В этой статье я пролью свет на эту тему, рассмотрев подход Booster к авторизации.

Стандарты, стандарты, стандарты

По своей конструкции Booster Framework является авторизованной системой на основе ролей, что означает, что команды и операции чтения выполняются определенными ролями, созданными пользователем, т.е. Admin, Customer, User, называйте как хотите. Если вы хотите сохранить свой API открытым, вы можете использовать предопределенную роль all, но это будет плохой идеей. Лучшей практикой будет ограничение доступа к API. Если вы хотите узнать больше о том, как определять роли в Booster, нажмите здесь.

Одним из широко распространенных и стандартных способов передачи защищенной информации и авторизации пользователей является использование JWT-токенов.

В этой статье я не хочу углубляться в детали стандарта JWT, но если говорить коротко, то вам понадобится провайдер JWT-авторизации или создать свой собственный, который будет генерировать действительные токены для ваших пользователей. Внутри этих токенов содержатся роли пользователей, которые нужны вам в качестве утверждений в вашем приложении Booster.

На ранних стадиях разработки Booster и поскольку мы использовали AWS в качестве нашего первого облачного провайдера, Booster предлагал конечные точки для создания, обновления и входа пользователей, используя AWS Cognito. Когда вы создавали пользователя, вы должны были указать его роль как часть сопутствующей информации. Когда пользователь входил в систему, Cognito возвращала JWT-токен со всей информацией, связанной с пользователем, включая роль.

Затем вы должны были использовать этот токен в заголовке Authorization в ваших запросах API в качестве маркера на предъявителя, а Booster внутренне снова обращался к Cognito, чтобы проверить, действителен ли токен и содержит ли он нужную роль для выполнения вызова API.

Такой подход работал некоторое время, пока некоторые пользователи Booster не захотели использовать Cognito. Некоторые хотели использовать свой аутентификатор, в то время как другие использовали другой аутентификатор, например Auth0, Firebase, Cognito, Okta или любой другой.

И снова на помощь пришли стандарты. Даже если мы использовали JWT, Booster был тесно связан с Cognito для проверки токена и получения информации, связанной с ним. Мы решили убрать эту часть и использовать стандартную проверку токенов внутри ядра Booster, которая работает с токенами JWT, независимо от того, какого провайдера вы используете.

Примечание: Мы удалили зависимость Cognito из Booster, но если вы все еще хотите использовать его, вы можете включить AWS Auth Rocket, который предоставляет наиболее распространенные функции Cognito «из коробки» для приложений Booster.

Верификаторы токенов

Стандарт JWT работает путем подписания токенов с помощью пар закрытых и открытых ключей с использованием асимметричной криптографии и различных алгоритмов (в основном RSA или ECDSA). То есть, по сути, открытый ключ хорошо известен клиентам, а закрытый ключ должен быть секретным и доступен только на стороне сервера.

Хорошо… но что мне нужно для использования auth в Booster?

В Booster вам нужно будет указать верификаторы токенов. Вы можете использовать более одного в зависимости от сценария использования, но в данный момент давайте сосредоточимся на использовании одного:

Booster.configure('production', (config: BoosterConfig): void => {   
  config.tokenVerifiers = [
    {
      jwksUri: 'https://demoapp.firebase.com/.well-known/jwks.json',
      issuer: 'https://securetoken.google.com/demoapp',
      rolesClaim: 'firebase:groups',
    }
  ]
}) 
Вход в полноэкранный режим Выход из полноэкранного режима

В приведенном выше примере мы используем Firebase в качестве провайдера для демонстрационного приложения. Свойство jwksUri содержит публичный URL, где Firebase раскрывает публичные ключи в виде JSON веб-ключей, issuer указывает, кто выпускает токены, а значение rolesClaim является утверждением, где Firebase добавляет роли.

Давайте создадим конфигурацию с помощью провайдера Cognito:

Booster.configure('production', (config: BoosterConfig): void => {   
  config.tokenVerifiers = [
    {
      jwksUri: 'https://cognito-idp.{region}.amazonaws.com/{userPoolId}/.well-known/jwks.json',
      issuer: 'https://cognito-idp.{region}.amazonaws.com/{userPoolId}',
      rolesClaim: 'cognito:groups',
    }
  ]
})  
Вход в полноэкранный режим Выход из полноэкранного режима

Здесь то же самое, ничего странного, кроме специфической конфигурации провайдера.

Это замечательно, но что если я хочу протестировать свои роли как часть процесса разработки и не хочу обходиться без какого-либо провайдера.

В Booster вы можете использовать потрясающий локальный провайдер для целей тестирования и настроить его вместе с локальным верификатором токенов.

Ваш локальный провайдер

Сначала нам нужно сгенерировать публичный и приватный ключи для локального генератора токенов JWT auth. Для этого вы можете использовать этот онлайн-инструмент. Внимание! Не используйте эти ключи в производственной среде.

После этого сохраните оба ключа в соответствующих файлах, таких как private.key и public.key, поскольку они понадобятся вам позже.

Чтобы сгенерировать токены для разных пользователей с разными ролями, давайте создадим простой скрипт node.js:

mkdir testToken;cd testToken;npm init -y;npm install jsonwebtoken
Вход в полноэкранный режим Выйти из полноэкранного режима

Переместите сохраненный вами в проекте private.key в папку внутри вашего проекта, т.е. в папку keys.

Затем скопируйте следующий код в index.js и измените его в зависимости от ваших потребностей.

const fs = require('fs')
const jwt = require('jsonwebtoken')
const path = require('path')

const privateKey = fs.readFileSync(path.join(__dirname, '.', 'keys', 'private.key'))

function forUser(email, role) {
 const keyid = 'booster'
 const issuer = 'booster'
 return jwt.sign(
   {
     id: email,
     demoRole: role,
     email,
   },
   privateKey,
   {
     algorithm: 'RS256',
     subject: email,
     issuer,
     keyid,
     expiresIn: 0
   }
 )
}

console.log('Here is your admin user token: ', forUser('test@boostercloud.com', 'Admin'))
Вход в полноэкранный режим Выйти из полноэкранного режима

Код выше не требует пояснений, но в основном он использует библиотеку jsonwebtoken для подписи токенов закрытым ключом и добавляет некоторые данные, такие как email и роль в свойстве demoRole.

Наконец, давайте запустим его:

node index.js
Here is your admin user token: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImJvb3N0ZXIifQ.eyJpZCI6InRlc3RAYm9vc3RlcmNsb3VkLmNvbSIsImRlbW9Sb2xlIjoiQWRtaW4iLCJlbWFpbCI6InRlc3RAYm9vc3RlcmNsb3VkLmNvbSIsImlhdCI6MTY1MjE5MDE1NiwiZXhwIjoxNjUyMTkwMTU2LCJpc3MiOiJib29zdGVyIiwic3ViIjoidGVzdEBib29zdGVyY2xvdWQuY29tIn0.HMBm_2MPVA_QHKr5hMTW_zmH9BFC5TplOOfSD34NrUUONzOU-1d6gKgNNRV_NX6Nem_4yksnUV64IhhLffmRNljBtIGQ-HaiVQ9S4MnNqyJCQRCArkK4xyu5EQd7RTNtLPS_xetn8kAJYzIlnO1KRNeQphplaeyEMCS5irjR9-A
Войдите в полноэкранный режим Выход из полноэкранного режима

Ух ты! Вы создали действительный JWT-токен для использования в Booster.

Чтобы использовать этот токен в Booster, в заголовках запросов API вам нужно будет настроить public.key в вашем верификаторе токенов:

Booster.configure('production', (config: BoosterConfig): void => {   
  config.tokenVerifiers = [
    {
      publicKey: fs.readFileSync(path.join(__dirname, '.', 'keys', 'public.key')),
      issuer: 'booster',
      rolesClaim: 'demoRole',

    }
  ]
})
Войти в полноэкранный режим Выйти из полноэкранного режима

Код выше будет использовать свойство publicKey вместо jwksUri, поскольку у нас нет публичного URL с ключами, как предлагают многие провайдеры.

Примите во внимание, что мы используем того же эмитента, которого мы использовали для подписи токена.

Дополнительно, дополнительно!

Некоторые пользователи спрашивали о валидации токенов, которая будет проверять другие данные, закодированные внутри токена, и на основании этого предоставлять или запрещать доступ. Для этого в конфигурации Booster есть функция свойства extraValidation, которая получает декодированный токен в качестве параметра, позволяя пользователям делать такие вещи, как:

Booster.configure('production', (config: BoosterConfig): void => {   
  config.tokenVerifiers = [
    {
      publicKey: fs.readFileSync(path.join(__dirname, '.', 'keys', 'public.key')),
      issuer: 'booster',
      rolesClaim: 'demoRole',
      extraValidation: (decodedToken) => {
         if (!decodedToken.payload.trust) {
            throw 'We don't trust on you'
         }
      }
    }
  ]
})
Войти в полноэкранный режим Выйти из полноэкранного режима

Выводы

Как вы видели, Booster предоставляет стандартный и простой способ аутентификации запросов на основе ролей пользователей, который покрывает большинство распространенных случаев использования, поскольку JWS широко распространен. Для тех случаев использования, которые не подходят по умолчанию, Booster предоставляет возможность расширения фреймворка благодаря использованию ракет, но это уже другая история. Если вы хотите узнать больше о том, как создавать ракеты, пожалуйста, обратитесь к официальной документации.

И последнее, но не менее важное: если у вас есть вопросы по Booster или по любой другой теме, мы будем рады выслушать ваши мысли на канале нашего сообщества.

Оцените статью
Procodings.ru
Добавить комментарий