I'm learning go and wanted to setup a simple application using auth0. Using their tutorials I was able to setup a basic authentication for my api endpoints. Now I wanted to add permission handling using the jwt token. So I activated RBAC for the api-endpoint and added a permission. I used the flow from the tutorial for custom claims, but wrote my own middleware with it and adjusted it to work with gin.
func NeedsPermission(expectedScope string) gin.HandlerFunc {
return func(context *gin.Context) {
token := context.Request.Context().Value(jwtmiddleware.ContextKey{}).(*validator.ValidatedClaims)
claims := token.CustomClaims.(*CustomClaims)
if !claims.HasScope(expectedScope) {
context.AbortWithStatus(403)
}
context.Next()
}
}
problem is that there are no custom claims in the token but only the default: openid, profile and email ones.
this is the token content:
{
"iss": "https://dev-****.us.auth0.com/",
"sub": "google-oauth2|****",
"aud": [
"localhost:3000/books",
"https://dev-****.us.auth0.com/userinfo"
],
"iat": 1701789297,
"exp": 1701875697,
"azp": "***",
"scope": "openid profile email",
"permissions": [
"read:books"
]
}
so it does have a field permissions, but how can I access that using the auth0/go-jwt-middleware or do I have to decode it first somehow?
Permissions is a custom claim, so you need to pass the WithCustomClaims
option with an implemention of the validator.CustomClaims
interface.
Then when you create the validator:
...
jwtValidator, _ := validator.New(
keyFunc,
validator.HS256,
issuer,
audience,
validator.WithCustomClaims(func() validator.CustomClaims {
return &MyClaims{}
}),
)
mw := jwtmiddleware.New(jwtValidator.ValidateToken)
...
Where MyClaims
is something like this. Note your HasScope
method:
type MyClaims struct {
Permissions []string `json:"permissions"`
}
func (c *MyClaims) Validate(ctx context.Context) error {
// Validate structure of permissions here, i.e. check for 400 not 403
return nil
}
func (c MyClaims) HasScope(requiredPerm string) bool {
for _, perm := range c.Permissions {
if perm == requiredPerm {
return true
}
}
return false
}