Введение

Аутентификация и авторизация являются важнейшими элементами построения безопасного веб-приложения. Веб-токены JSON (JWT) стали популярным методом реализации аутентификации в современных веб-приложениях. В этой статье мы обсудим, как реализовать JWT-аутентификацию в Go с использованием фреймворка Iris и промежуточной библиотеки Auth0 JWT.

Цель

Цель этого технического блога — объяснить реализацию промежуточного программного обеспечения аутентификации JWT (JSON Web Token) в Go с использованием пакета «auth0/go-jwt-middleware». Блог проведет читателей через предоставленный код, объяснив каждый компонент и его функциональность. К концу блога читатели должны иметь четкое представление о том, как использовать промежуточное ПО аутентификации JWT для защиты своих приложений и API Go, гарантируя, что только авторизованные пользователи могут получить доступ к защищенным ресурсам.

Выполнение

Чтобы запустить процесс внедрения, я сослался на https://github.com/auth0/go-jwt-middleware.
Основной загвоздкой здесь была реализация для поддержки фреймворка iris. Изучив пример, представленный для фреймворка gin в репозитории, я смог сделать необходимые подключения и разработать промежуточное ПО, поддерживающее iris.

Код

  1. Инициализация переменных
var (
 // The signing key for the token.
 signingKey = []byte("secret")

 // The issuer of our token.
 issuer = "go-jwt-middleware-example"

 // The audience of our token.
 audience = []string{"audience-example"}

 // Our token must be signed using this data.
 keyFunc = func(ctx context.Context) (interface{}, error) {
  return signingKey, nil
 }

 // We want this struct to be filled in with
 // our custom claims from the token.
 customClaims = func() validator.CustomClaims {
  return &CustomClaims{}
 }
)

Несколько переменных инициализируются для настройки промежуточного программного обеспечения JWT. «signingKey» представляет секретный ключ, используемый для подписи токена, «эмитент» представляет эмитента токена, а «аудитория» указывает ожидаемую аудиторию для токена. «keyFunc» определяет функцию, которая извлекает ключ подписи, а «customClaims» указывает структуру для хранения пользовательских утверждений из токена.

2. Проверка JWT
Функция «checkJWT» — это основная функция промежуточного программного обеспечения, отвечающая за проверку JWT.

2.1 Проверьте настройку JWT Validator

jwtValidator, err := validator.New(
  keyFunc,
  validator.HS256,
  issuer,
  audience,
  validator.WithCustomClaims(customClaims),
  validator.WithAllowedClockSkew(30*time.Second),
 )

Валидатор JWT создается с помощью пакета «auth0/go-jwt-middleware/validator». Он настраивает валидатор с функцией извлечения ключа, алгоритмом подписи (HS256), эмитентом, аудиторией, пользовательскими утверждениями и устойчивостью к перекосу часов.

2.2 Обработчик ошибок

errorHandler := func(w http.ResponseWriter, r *http.Request, err error) {
  log.Printf("Encountered error while validating JWT: %v", err)
 }

Функция обработчика ошибок определена для обработки любых ошибок, возникающих во время проверки JWT.

2.3 Создание промежуточного ПО

middleware := jwtmiddleware.New(
  jwtValidator.ValidateToken,
  jwtmiddleware.WithErrorHandler(errorHandler),
 )

Промежуточное ПО JWT создается с использованием пакета «auth0/go-jwt-middleware». В качестве входных данных он принимает валидатор JWT и обработчик ошибок.

2.4 Выполнение промежуточного ПО

return func(ctx iris.Context) {
  encounteredError := true
  var handler http.HandlerFunc = func(w http.ResponseWriter, r *http.Request) {
   encounteredError = false
   ctx.ResetRequest(r)
   ctx.Next()
  }

  middleware.CheckJWT(handler).ServeHTTP(ctx.ResponseWriter(), ctx.Request())

  if encounteredError {
   ctx.StopWithJSON(
    iris.StatusUnauthorized,
    map[string]string{"message": "JWT is invalid."},
   )
  }
 }

Промежуточное программное обеспечение выполняется путем обертывания анонимной функции вокруг контекста Iris. Эта функция действует как мост между инфраструктурой Iris и промежуточным программным обеспечением. Это гарантирует, что JWT проверен и подтвержден, прежде чем разрешать дальнейшую обработку запроса. Если проверка JWT не пройдена, возвращается неавторизованный ответ JSON.

3. Пользовательские утверждения
Это расширяет функциональные возможности ПО промежуточного слоя аутентификации JWT, позволяя выполнять дополнительные проверки и проверки извлеченных пользовательских утверждений.

3.1 Структура пользовательских утверждений

type CustomClaims struct {
 Name         string `json:"name"`
 Username     string `json:"username"`
 ShouldReject bool   `json:"shouldReject,omitempty"`
}

Добавленный блок кода вводит структуру CustomClaims, которая представляет настраиваемые утверждения, которые мы хотим извлечь из JWT. Он включает такие поля, как Name, Username и ShouldReject.

3.2 Проверить метод

func (c *CustomClaims) Validate(ctx context.Context) error {
 if c.ShouldReject {
  return errors.New("should reject was set to true")
 }
 return nil
}

Метод Validate определен для структуры CustomClaims. Этот метод вызывается во время процесса проверки и позволяет использовать дополнительную пользовательскую логику проверки. В этом случае метод проверяет, установлено ли для поля ShouldReject значение true, и возвращает ошибку, если это так.
Реализуя метод Validate, вы можете применить определенные правила проверки к пользовательским утверждениям JWT. Это дает вам детальный контроль над принятием или отклонением JWT на основе их настраиваемых значений утверждений.

Заключение

В этом сообщении блога мы рассмотрели реализацию промежуточного ПО для аутентификации JWT в Go с использованием пакета «auth0/go-jwt-middleware». Промежуточное ПО предоставляет удобный способ проверки и авторизации JWT в приложениях Go. Включив это промежуточное ПО в свои проекты Go, вы сможете повысить безопасность и целостность своих API и веб-приложений.

Исходный код этого примера доступен по адресу mehulgohil/go-bffauth
Я поднял PR, чтобы добавить этот пример в репозиторий go-jwt-middleware.