-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
a284266
commit bd9a322
Showing
5 changed files
with
212 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
package gofiberauth0middleware | ||
|
||
import ( | ||
"errors" | ||
"fmt" | ||
"net/url" | ||
"strings" | ||
"time" | ||
|
||
"github.com/auth0/go-jwt-middleware/v2/jwks" | ||
"github.com/auth0/go-jwt-middleware/v2/validator" | ||
"github.com/gofiber/fiber/v2" | ||
) | ||
|
||
type Config struct { | ||
// Filter defines a function to skip middleware. | ||
// Optional. Default: nil | ||
Filter func(*fiber.Ctx) bool | ||
|
||
// SuccessHandler defines a function which is executed for a valid token. | ||
// Optional. Default: nil | ||
SuccessHandler fiber.Handler | ||
|
||
// ErrorHandler defines a function which is executed for an invalid token. | ||
// It may be used to define a custom JWT error. | ||
// Optional. Default: 401 Invalid or expired JWT | ||
ErrorHandler fiber.ErrorHandler | ||
|
||
Issuer string `yaml:"issuer"` | ||
Audience []string `yaml:"audience"` | ||
SignatureAlgorithm string `yaml:"signature_algorithm"` | ||
CacheDuration time.Duration `yaml:"cache_duration"` | ||
} | ||
|
||
func makeCfg(config []Config) (cfg Config) { | ||
if len(config) > 0 { | ||
cfg = config[0] | ||
} | ||
if cfg.SuccessHandler == nil { | ||
cfg.SuccessHandler = func(c *fiber.Ctx) error { | ||
return c.Next() | ||
} | ||
} | ||
if cfg.ErrorHandler == nil { | ||
cfg.ErrorHandler = func(c *fiber.Ctx, err error) error { | ||
if err.Error() == "Missing or malformed JWT" { | ||
return c.Status(fiber.StatusBadRequest).SendString("Missing or malformed JWT") | ||
} | ||
return c.Status(fiber.StatusUnauthorized).SendString("Invalid or expired JWT") | ||
} | ||
} | ||
|
||
if cfg.CacheDuration == 0 { | ||
cfg.CacheDuration = 5 * time.Minute | ||
} | ||
|
||
if cfg.SignatureAlgorithm == "" { | ||
cfg.SignatureAlgorithm = "RS256" | ||
} | ||
|
||
return cfg | ||
} | ||
|
||
// jwtFromHeader returns a function that extracts token from the request header. | ||
func jwtFromHeader(header string, authScheme string) func(c *fiber.Ctx) (string, error) { | ||
return func(c *fiber.Ctx) (string, error) { | ||
auth := c.Get(header) | ||
l := len(authScheme) | ||
if len(auth) > l+1 && strings.EqualFold(auth[:l], authScheme) { | ||
return auth[l+1:], nil | ||
} | ||
return "", errors.New("Missing or malformed JWT") | ||
} | ||
} | ||
|
||
func New(config ...Config) fiber.Handler { | ||
|
||
cfg := makeCfg(config) | ||
|
||
// Return middleware handler | ||
return func(c *fiber.Ctx) error { | ||
// Filter request to skip middleware | ||
if cfg.Filter != nil && cfg.Filter(c) { | ||
return c.Next() | ||
} | ||
|
||
issuerURL, err := url.Parse(cfg.Issuer) | ||
if err != nil { | ||
return cfg.ErrorHandler(c, err) | ||
} | ||
|
||
provider := jwks.NewCachingProvider(issuerURL, cfg.CacheDuration) | ||
|
||
// Set up the validator. | ||
jwtValidator, err := validator.New( | ||
provider.KeyFunc, | ||
validator.SignatureAlgorithm(cfg.SignatureAlgorithm), | ||
issuerURL.String(), | ||
cfg.Audience, | ||
) | ||
if err != nil { | ||
return cfg.ErrorHandler(c, err) | ||
} | ||
|
||
token, err := jwtFromHeader("Authorization", "Bearer")(c) | ||
if err != nil { | ||
return cfg.ErrorHandler(c, err) | ||
} | ||
|
||
// Get the JWT token from the request header. | ||
claims, err := jwtValidator.ValidateToken(c.Context(), token) | ||
if err != nil { | ||
fmt.Println(err) | ||
return cfg.ErrorHandler(c, err) | ||
} | ||
|
||
// Store user information from token into context. | ||
c.Locals("claims", claims) | ||
return cfg.SuccessHandler(c) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
AUTH0_AUDIENCE=https://example.auth0.com/api/v2/ | ||
AUTH0_ISSUER=https://example.auth0.com/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
package main | ||
|
||
import ( | ||
"log" | ||
"net/http" | ||
"os" | ||
|
||
"github.com/auth0/go-jwt-middleware/v2/validator" | ||
"github.com/gofiber/fiber/v2" | ||
auth0 "github.com/satishbabariya/go-fiber-auth0-middleware" | ||
) | ||
|
||
func main() { | ||
app := fiber.New() | ||
|
||
app.Use(auth0.New(auth0.Config{ | ||
Issuer: os.Getenv("AUTH0_ISSUER"), | ||
Audience: []string{os.Getenv("AUTH0_AUDIENCE")}, | ||
ErrorHandler: func(c *fiber.Ctx, err error) error { | ||
return fiber.NewError(http.StatusUnauthorized, err.Error()) | ||
}, | ||
})) | ||
|
||
app.Get("/", func(c *fiber.Ctx) error { | ||
claims := c.Locals("claims").(*validator.ValidatedClaims) | ||
return c.JSON(claims) | ||
}) | ||
|
||
log.Fatal(app.Listen(":1203")) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
module github.com/satishbabariya/go-fiber-auth0-middleware | ||
|
||
go 1.18 | ||
|
||
require ( | ||
github.com/auth0/go-jwt-middleware/v2 v2.0.1 | ||
github.com/gofiber/fiber/v2 v2.31.0 | ||
) | ||
|
||
require ( | ||
github.com/andybalholm/brotli v1.0.4 // indirect | ||
github.com/klauspost/compress v1.15.0 // indirect | ||
github.com/pkg/errors v0.9.1 // indirect | ||
github.com/valyala/bytebufferpool v1.0.0 // indirect | ||
github.com/valyala/fasthttp v1.34.0 // indirect | ||
github.com/valyala/tcplisten v1.0.0 // indirect | ||
golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd // indirect | ||
golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9 // indirect | ||
gopkg.in/square/go-jose.v2 v2.6.0 // indirect | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY= | ||
github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= | ||
github.com/auth0/go-jwt-middleware/v2 v2.0.1 h1:zAgDKL7nsfVBFl31GGxsSXkhuRzYe1fVtJcO3aMSrFU= | ||
github.com/auth0/go-jwt-middleware/v2 v2.0.1/go.mod h1:kDt7JgUuDEp1VutfUmO4ZxBLL51vlNu/56oDfXc5E0Y= | ||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= | ||
github.com/gofiber/fiber/v2 v2.31.0 h1:M2rWPQbD5fDVAjcoOLjKRXTIlHesI5Eq7I5FEQPt4Ow= | ||
github.com/gofiber/fiber/v2 v2.31.0/go.mod h1:1Ega6O199a3Y7yDGuM9FyXDPYQfv+7/y48wl6WCwUF4= | ||
github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o= | ||
github.com/klauspost/compress v1.15.0 h1:xqfchp4whNFxn5A4XFyyYtitiWI8Hy5EW59jEwcyL6U= | ||
github.com/klauspost/compress v1.15.0/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= | ||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= | ||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= | ||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= | ||
github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= | ||
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= | ||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= | ||
github.com/valyala/fasthttp v1.34.0 h1:d3AAQJ2DRcxJYHm7OXNXtXt2as1vMDfxeIcFvhmGGm4= | ||
github.com/valyala/fasthttp v1.34.0/go.mod h1:epZA5N+7pY6ZaEKRmstzOuYJx9HI8DI1oaCGZpdH4h0= | ||
github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8= | ||
github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= | ||
golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= | ||
golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd h1:XcWmESyNjXJMLahc3mqVQJcgSTDxFxhETVlfk9uGc38= | ||
golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= | ||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= | ||
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= | ||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||
golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9 h1:nhht2DYV/Sn3qOayu8lM+cU1ii9sTLUeBQwQQfUHtrs= | ||
golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= | ||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= | ||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= | ||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= | ||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | ||
gopkg.in/square/go-jose.v2 v2.6.0 h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI= | ||
gopkg.in/square/go-jose.v2 v2.6.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= | ||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= |