Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue: Achieve different authorization in different HTTP HandlerFunc #20

Open
JiSuanSiWeiShiXun opened this issue Oct 29, 2024 · 3 comments

Comments

@JiSuanSiWeiShiXun
Copy link

Description

The current implementation of the JWT middleware applies the same authorization logic to all route functions under a specific route prefix. This approach lacks the flexibility required in production environments where different API endpoints often need different authorization checks.

Current Behavior

The registered Authorizator is called before the execution of any route function that uses the JWT middleware. This results in uniform authorization logic across all functions under the same route prefix.

Desired Behavior

Implement a mechanism to apply different authorization logic to different HTTP handlers, allowing for more granular and specific access control. For example:

  • For an endpoint that operates on a document, check if the current user has permission to edit that specific document.
  • For an endpoint that updates a group name, verify if the current user has the appropriate group admin role.

The method I can think of is to construct multiple JWT middleware objects, one for each authorization logic. These JWT objects would have the same Authenticator, PayloadFunc, and IdentityHandler, with only the Authorizator being different. Then, use the corresponding JWT middleware object for specific route functions. I think this approach looks a bit messy. Is there a more elegant way to implement this requirement?

@GuangmingLuo
Copy link

@bodhisatan @justlorain please take a look

@justlorain
Copy link
Member

justlorain commented Oct 30, 2024

A possible solution is to create a simple custom middleware for grouped access control, refer to appleboy/gin-jwt#25:

func GroupAuthorizator(group string) app.HandlerFunc {
	return func(ctx context.Context, c *app.RequestContext) {
		switch group {
		case "product":
			usr, _ := c.Get(JwtMiddleware.IdentityKey)
			fmt.Println(usr.(*models.User).UserName)
			c.Next(ctx)
			return
		default:
			JwtMiddleware.Unauthorized(ctx, c, http.StatusForbidden, JwtMiddleware.HTTPStatusMessageFunc(jwt.ErrForbidden, ctx, c))
		}
	}
}
auth := r.Group("/product", mw.JwtMiddleware.MiddlewareFunc(), mw.GroupAuthorizator("product"))
auth.GET("/get", handler.GetProduct)

However, this approach doesn’t solve the fundamental issue with the JWT middleware. Another solution I thought of is to perform access control inside the Authorizator by using the FullPath or Path method of app.RequestContext:

Authorizator: func(data interface{}, ctx context.Context, c *app.RequestContext) bool {
	group := strings.Split(c.FullPath(), "/")[1]
	switch group {
	case "product":
		if v, ok := data.(*User); ok && v.UserName == "product-admin" {
			return true
		}
	case "account":
		if v, ok := data.(*User); ok && v.UserName == "account-admin" {
			return true
		}
	}
	return false
},

I hope this helps solve your problem.

@justlorain
Copy link
Member

BTW, if you want more fine-grained access control, you can consider using the casbin middleware supported by Hertz.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants