Go의 Auth0 JWT 미들웨어 - Gin 웹 프레임워크

27803 단어 securityauth0go
오늘의 블로그 게시물에서는 Gin Web Framework를 사용하여 Auth0 Golang JWT 미들웨어를 사용하여 JWT를 검증하는 방법을 살펴보겠습니다. Gin은 Go(Golang)로 작성된 웹 프레임워크입니다. 심층 분석에서는 Auth0 Golang JWT 미들웨어를 통합하여 비밀 및 JWK를 사용하여 HS256 및 RS256을 모두 사용하여 생성된 JWT를 확인하는 방법을 볼 것입니다.

Auth0 Golang JWT 미들웨어 안정 버전 v2.0.0 2022년 1월 19일 출시

Release v2.0.0 · auth0/go-jwt-middleware

진 웹 프레임워크



Gin은 웹 애플리케이션과 마이크로서비스를 구축할 수 있는 고성능 마이크로 프레임워크입니다. 재사용 가능한 모듈식 조각에서 요청 처리 파이프라인을 간단하게 구축할 수 있습니다. 하나 이상의 요청 처리기 또는 요청 처리기 그룹에 연결할 수 있는 미들웨어를 작성할 수 있도록 하여 이를 수행합니다.

Golang Gin Web Framework를 사용하여 간단한 API를 만들어 봅시다.
  • 진 패키지 설치

  •   go get -u github.com/gin-gonic/gin
    


  • 코드에서 가져오고 간단한 API 실행

  •   package main
    
      import (
        "context"
        "net/http"
        "github.com/gin-gonic/gin"
      )
    
      type Product struct {
        ID    int     `json:"id"`
        Title string  `json:"title"`
        Code  string  `json:"code"`
        Price float32 `json:"price"`
      }
    
      func main() {
        r := gin.Default()
    
        r.GET("/products", func(c *gin.Context) {
            products := []Product{
                {ID: 1, Title: "Product 1", Code: "p1", Price: 100.0},
                {ID: 2, Title: "Product 2", Code: "p2", Price: 200.0},
                {ID: 3, Title: "Product 3", Code: "p3", Price: 300.0},
            }
            c.JSON(http.StatusOK, products)
        })
    
        // Listen and Server in 0.0.0.0:5000
        r.Run(":5000")
      }
    


    JWT 미들웨어 추가



    Auth0 API를 구성하기 전에 Auth0 Golang JWT 미들웨어를 통합합시다.

    GitHub - auth0/go-jwt-middleware: A Middleware for Go Programming Language to check for JWTs on HTTP requests

    go get github.com/auth0/go-jwt-middleware/v2
    


    Auth0 Golang JWT 미들웨어는 HTTP 미들웨어 핸들러입니다. Gin 웹 프레임워크에서 사용하려면 일반 HTTP 미들웨어를 Gin 미들웨어 처리기로 래핑하는 래퍼가 필요합니다. 이를 위해 Gareth Watts의 Gin Adapter를 사용하고 있습니다. https://github.com/gwatts/gin-adapter

    package main
    
    import (
        "context"
        "net/http"
    
        jwtmiddleware "github.com/auth0/go-jwt-middleware/v2"
        "github.com/auth0/go-jwt-middleware/v2/validator"
        "github.com/gin-gonic/gin"
        "github.com/gwatts/gin-adapter"
    )
    
    type Product struct {
        ID    int     `json:"id"`
        Title string  `json:"title"`
        Code  string  `json:"code"`
        Price float32 `json:"price"`
    }
    
    func main() {
        r := gin.Default()
    
        keyFunc := func(ctx context.Context) (interface{}, error) {
            return []byte("secret"), nil
        }
    
        jwtValidator, _ := validator.New(keyFunc, validator.HS256, "http://localhost:5000", []string{"api:read"})
        jwtMiddleware := jwtmiddleware.New(jwtValidator.ValidateToken)
    
        // Wrap the http handler with gin adapter
        r.Use(adapter.Wrap(jwtMiddleware.CheckJWT))
    
        r.GET("/products", func(c *gin.Context) {
            products := []Product{
                {ID: 1, Title: "Product 1", Code: "p1", Price: 100.0},
                {ID: 2, Title: "Product 2", Code: "p2", Price: 200.0},
                {ID: 3, Title: "Product 3", Code: "p3", Price: 300.0},
            }
            c.JSON(http.StatusOK, products)
        })
    
        // Listen and Server in 0.0.0.0:5000
        r.Run(":5000")
    }
    


    JWT URL을 사용하여 이 API를 테스트해 보겠습니다.

    curl --location --request GET 'http://localhost:5000/products' \
    --header 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjUwMDAiLCJhdWQiOiJhcGk6cmVhZCJ9.hbgwKW_RILeXXDDUv5bVK3WgjtvqoK5IiuisgnFWefY'
    


    공유 비밀[http://localhost:5000](http://localhost:5000)이 있는 HS256 알고리즘을 사용하여 발급자api:read 및 대상secret이 있는 새 JWT를 생성할 수 있습니다.

    ➜  ~  curl --location --request GET 'http://localhost:5000/products' \
    --header 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjUwMDAiLCJhdWQiOiJhcGk6cmVhZCJ9.hbgwKW_RILeXXDDUv5bVK3WgjtvqoK5IiuisgnFWefY' | jq
      % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                     Dload  Upload   Total   Spent    Left  Speed
    100   160  100   160    0     0   6011      0 --:--:-- --:--:-- --:--:-- 20000
    [
      {
        "id": 1,
        "title": "Product 1",
        "code": "p1",
        "price": 100
      },
      {
        "id": 2,
        "title": "Product 2",
        "code": "p2",
        "price": 200
      },
      {
        "id": 3,
        "title": "Product 3",
        "code": "p3",
        "price": 300
      }
    ]
    


    Auth0 API 구성



    이제 Auth0을 사용하여 API에 권한 부여를 추가할 차례입니다. 서명 알고리즘 RS256으로 Auth0 API를 구성하고 RS256을 지원하도록 Auth0 Golang 미들웨어 코드를 변경해 보겠습니다.



    API에서 권한read:products 추가



    RS256 서명 JWT 토큰의 유효성을 검사하도록 Auth0 미들웨어를 변경합니다.

    issuerURL, _ := url.Parse(os.Getenv("AUTH0_ISSUER_URL"))
    audience := os.Getenv("AUTH0_AUDIENCE")
    
    provider := jwks.NewCachingProvider(issuerURL, time.Duration(5*time.Minute))
    
    jwtValidator, _ := validator.New(provider.KeyFunc,
        validator.RS256,
        issuerURL.String(),
        []string{audience},
    )
    
    jwtMiddleware := jwtmiddleware.New(jwtValidator.ValidateToken)
    r.Use(adapter.Wrap(jwtMiddleware.CheckJWT))
    


    전체 코드는 아래와 같습니다.

    package main
    
    import (
        "log"
        "net/http"
        "net/url"
        "os"
        "time"
    
        adapter "github.com/gwatts/gin-adapter"
    
        jwtmiddleware "github.com/auth0/go-jwt-middleware/v2"
        "github.com/auth0/go-jwt-middleware/v2/jwks"
        "github.com/auth0/go-jwt-middleware/v2/validator"
    
        "github.com/gin-gonic/gin"
        "github.com/joho/godotenv"
    )
    
    type Product struct {
        ID    int     `json:"id"`
        Title string  `json:"title"`
        Code  string  `json:"code"`
        Price float32 `json:"price"`
    }
    
    func main() {
        err := godotenv.Load()
        if err != nil {
            log.Fatal("Error loading .env file")
        }
    
        r := gin.Default()
    
        issuerURL, _ := url.Parse(os.Getenv("AUTH0_ISSUER_URL"))
        audience := os.Getenv("AUTH0_AUDIENCE")
    
        provider := jwks.NewCachingProvider(issuerURL, time.Duration(5*time.Minute))
    
        jwtValidator, _ := validator.New(provider.KeyFunc,
            validator.RS256,
            issuerURL.String(),
            []string{audience},
        )
    
        jwtMiddleware := jwtmiddleware.New(jwtValidator.ValidateToken)
        r.Use(adapter.Wrap(jwtMiddleware.CheckJWT))
    
        r.GET("/products", func(c *gin.Context) {
            products := []Product{
                {ID: 1, Title: "Product 1", Code: "p1", Price: 100.0},
                {ID: 2, Title: "Product 2", Code: "p2", Price: 200.0},
                {ID: 3, Title: "Product 3", Code: "p3", Price: 300.0},
            }
            c.JSON(http.StatusOK, products)
        })
    
        // Listen and Server in 0.0.0.0:5000
        r.Run(":5000")
    }
    


    Auth0 JWT 확인



    API 테스트 페이지에서 테스트 JWT를 만듭니다. 테스트 토큰으로 API를 호출합니다.

    ➜  auth0-go-gin-middleware  curl --location --request GET 'http://localhost:5000/products' \
    --header 'authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InVUT0ktNGhrSDBWNU9YUGxKV0xpXyJ9.eyJpc3MiOiJodHRwczovL3NpdmEtZGVtby1hcHAudXMuYXV0aDAuY29tLyIsInN1YiI6Inl2N1NDekVueUxTWGdMZ1d3b2pJODZvNk5ZMzh0cmNtQGNsaWVudHMiLCJhdWQiOiJodHRwczovL3Byb2R1Y3RzLWFwaS8iLCJpYXQiOjE2NDM0MzM4NTYsImV4cCI6MTY0MzUyMDI1NiwiYXpwIjoieXY3U0N6RW55TFNYZ0xnV3dvakk4Nm82TlkzOHRyY20iLCJndHkiOiJjbGllbnQtY3JlZGVudGlhbHMifQ.yH13H5XxLEABu3o8s2HZUs8Q9PXHeLGUcELQdlrYoClKP3k3B_WdUpaH2_c-UpA1ZjB_Is71-hSt3iqQN_OaMV_fFqpnt0qJQNXsoWSHBE5CzDDAclRlFf5XaWVbcA072rzUAtrJuPzHYf8kdR91243lJFA_13V5vlQuWxqFxas4FonVR5OLGcXYHqLfBI76DPfFaOBwOzefSYSI_jxKrrQtnux4Ktkqrgo7tpFckY6UfD6fXPeRvk4xLSb_SteAwcpCQrWJVyt7gTWv4_KkSNEyZduEbMTrnkU_jdQjHuKOLaTBc4t7t3MK_2_tmrda5xn0QXf-1y6P2M4zQu2mWA' | jq
      % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                     Dload  Upload   Total   Spent    Left  Speed
    100   160  100   160    0     0   8045      0 --:--:-- --:--:-- --:--:-- 40000
    [
      {
        "id": 1,
        "title": "Product 1",
        "code": "p1",
        "price": 100
      },
      {
        "id": 2,
        "title": "Product 2",
        "code": "p2",
        "price": 200
      },
      {
        "id": 3,
        "title": "Product 3",
        "code": "p3",
        "price": 300
      }
    ]
    


    결론



    이 블로그 게시물에서는 Auth0 Golang 미들웨어 v2.0.0을 사용하여 HS256 및 RS256 서명 모두에서 JWT를 확인하는 방법을 살펴보았습니다. 이 데모 프로젝트를 확장하여 JWT 등에서 사용자 지정 클레임을 확인할 수 있습니다. 다음 블로그 게시물에서 더 자세히 살펴보겠습니다.

    좋은 웹페이지 즐겨찾기