-
Notifications
You must be signed in to change notification settings - Fork 1.7k
RBAC middleware support #2144
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
base: development
Are you sure you want to change the base?
RBAC middleware support #2144
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We would like to keep RBAC as a separate module. Hence add go.mod in it. So that it does not get added in the binary of the gofr framework.
examples/rbac/config.json
Outdated
{ | ||
"roles": { | ||
"admin": ["*"], | ||
"editor": ["/posts/*", "/dashboard"], | ||
"user": ["/profile", "/home", "/sayhello*","/greet"] | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Roles should be defined at route level, not the other way around. That would allow clarity on who all can access a given route.
pkg/gofr/rbac/match.go
Outdated
"strings" | ||
) | ||
|
||
func isPathAllowed(role, route string, config *Config) bool { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We shouldn't reinvent the path matching, utilise existing packages.
pkg/gofr/rbac/helper.go
Outdated
return expRole == role | ||
} | ||
|
||
func IsAdmin(ctx *gofr.Context) bool { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Roles should not be hardcoded into the framework. They are just strings, should not have a literal meaning defined in the framework.
return HasRole(ctx, "admin") | ||
} | ||
|
||
func GetUserRole(ctx *gofr.Context) string { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Errors should not be silently ignored
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it returns a bool, so have ignored it
gofrCtx := &gofr.Context{Context: baseCtx} | ||
|
||
got := HasRole(gofrCtx, tt.checkRole) | ||
if got != tt.expectedRes { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider using assert.Equal/Equalf to make it more concise
} | ||
|
||
func extractor(req *http.Request, _ ...any) (string, error) { | ||
return req.Header.Get("X-USER-ROLE"), nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
User role passed in the header cannot be trusted as is. While this may have been added as an example only, it'd be better to have a proper example.
app.UseMiddleware(rbac.Middleware(rbacConfigs)) | ||
|
||
app.GET("/sayhello/123", handler) | ||
app.GET("/greet", rbac.RequireRole("user1", handler)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is defeating the purpose of middleware if every route needs to add this RequireRole
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
requireRole is not needed for every route, can be directly used as app.GET("/sayhello/123", handler)
@coolwednesday What's the advantage of having RBAC in another module, unless we move the auth middlewares into a separate module as well? |
@goginenibhavani2000 please go ahead and resolve the review comments given by the reviewer. While we decide whether to keep it inside or outside like a separate module i think we can focus on completing the implementation, testing, documentation etc. Please let us know if you know any more help. |
@akshat-kumar-singhal We see RBAC as a layer beneath Auth—more specialized and not universally required. Auth is core to GoFr and widely used, which is why its middlewares are bundled. RBAC, on the other hand, is optional and domain-specific, so we’re keeping it modular to avoid unnecessary coupling and binary weight. |
Won’t it be taken care of by the dead code elimination done during build?
I agree that RBAC shouldn’t be a default, but an easy to include
module/package. What we could consider is having the interface for RBAC
within gofr and the external module implementing that interface.
…On Wed, 20 Aug 2025 at 16:58, Umang Mundhra ***@***.***> wrote:
*Umang01-hash* left a comment (gofr-dev/gofr#2144)
<#2144 (comment)>
We would like to keep RBAC as a separate module. Hence add go.mod in it.
So that it does not get added in the binary of the gofr framework.
@coolwednesday <https://github.com/coolwednesday> What's the advantage of
having RBAC in another module, unless we move the auth middlewares into a
separate module as well?
@akshat-kumar-singhal <https://github.com/akshat-kumar-singhal> We see
RBAC as a layer beneath Auth—more specialized and not universally required.
Auth is core to GoFr and widely used, which is why its middlewares are
bundled. RBAC, on the other hand, is optional and domain-specific, so we’re
keeping it modular to avoid unnecessary coupling and binary weight.
—
Reply to this email directly, view it on GitHub
<#2144 (comment)>, or
unsubscribe
<https://github.com/notifications/unsubscribe-auth/APUGM5WLZAMQTTVY4YHXRRD3ORLXVAVCNFSM6AAAAACDUPRBZSVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZTEMBVG44DMNJTHE>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
|
Yes that makes sense. WE can have the interface in GoFr and implementation outside. |
@goginenibhavani2000 Are you still working on the issue. Please let us know in case you need any further help for the same. |
Description:
Breaking Changes (if applicable):
Additional Information:
Checklist:
goimport
andgolangci-lint
.