How can I use middleware JWT with 2 user author #1944
Unanswered
thienlhhe130847
asked this question in
Q&A
Replies: 1 comment 7 replies
-
You distinguish admin from user by claims? This is example how to guard routes with privileges (using basic auth) but you can modify it for JWT as KeyAuth and JWT middlewares are pretty much the same. Just extract claims from token and check them with // Try with:
// curl -v -H "Authorization: Basic YWRtaW46c2VjcmV0" http://localhost:8082/admin-only
// curl -v -H "Authorization: Basic dXNlcjpUMHBTM2NyM3Q=" http://localhost:8082/admin-only
// curl -v http://localhost:8082/admin-only
// curl -v -H "Authorization: Basic dXNlcjpUMHBTM2NyM3Q=" http://localhost:8082/posts
func main() {
e := echo.New()
e.Use(Authentication(NewAuthProvider()))
h := func(c echo.Context) error {
sc := c.Get(SecurityContextKey).(AuthContext) // for simplicity
return c.String(http.StatusOK, fmt.Sprintf("user: %v with privileges: %v\n", sc.UserID, sc.Privileges))
}
e.GET("/admin-only", h, Authorization(IsAdmin))
e.GET("/posts", h, Authorization(IsAdmin, ViewPosts))
if err := e.Start(":8082"); err != http.ErrServerClosed {
log.Fatal(err)
}
}
type Privilege string
const (
IsAdmin Privilege = "IS_ADMIN"
ViewPosts Privilege = "VIEW_POSTS"
AddPosts Privilege = "ADD_POSTS"
EditPosts Privilege = "EDIT_POSTS"
)
func Authentication(authProvider *AuthenticationProvider) echo.MiddlewareFunc {
return middleware.KeyAuthWithConfig(middleware.KeyAuthConfig{
KeyLookup: "header:Authorization",
AuthScheme: "Basic",
Validator: func(rawAuth string, c echo.Context) (bool, error) {
auth, err := base64.StdEncoding.DecodeString(rawAuth)
if err != nil {
return false, echo.NewHTTPError(http.StatusUnauthorized, "invalid base64 auth value")
}
parts := strings.Split(string(auth), ":")
if len(parts) != 2 {
return false, echo.NewHTTPError(http.StatusUnauthorized, "invalid auth")
}
sc, ok := authProvider.Authorize(parts[0], parts[1])
if !ok {
return false, echo.NewHTTPError(http.StatusUnauthorized, "invalid auth")
}
c.Set(SecurityContextKey, sc)
return true, nil
},
})
}
// AuthContext holds information about user who has been authenticated for request
type AuthContext struct {
UserID int64
Privileges []Privilege
}
type AuthenticationProvider struct {
usersInMemory map[string]struct {
ID int64
Username string
Password string // NB: raw password for simplicity. use hashed password in real life
Privileges []Privilege
}
}
func NewAuthProvider() *AuthenticationProvider {
usersInMemory := map[string]struct {
ID int64
Username string
Password string
Privileges []Privilege
}{
// admin:secret => YWRtaW46c2VjcmV0
"admin": {ID: 1, Username: "admin", Password: "secret", Privileges: []Privilege{IsAdmin, EditPosts}},
// user:T0pS3cr3t => dXNlcjpUMHBTM2NyM3Q=
"user": {ID: 2, Username: "user", Password: "T0pS3cr3t", Privileges: []Privilege{ViewPosts, AddPosts}},
}
return &AuthenticationProvider{
usersInMemory: usersInMemory,
}
}
func (a *AuthenticationProvider) Authorize(username string, password string) (AuthContext, bool) {
user, ok := a.usersInMemory[username]
if !ok {
return AuthContext{}, false
}
if user.Password != password {
return AuthContext{}, false
}
return AuthContext{
UserID: user.ID,
Privileges: append([]Privilege{}, user.Privileges...),
}, true
}
const (
SecurityContextKey = "__SecurityContextKey__"
)
// Authorization checks if context contains at least one given privilege (OR check) on failure request ends with 401 unauthorized error
func Authorization(privileges ...Privilege) echo.MiddlewareFunc {
return func(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
raw := c.Get(SecurityContextKey)
if raw == nil {
return echo.ErrUnauthorized
}
authContext, ok := raw.(AuthContext)
if !ok {
return echo.ErrUnauthorized
}
if !authContext.CheckPrivilege(privileges...) {
return echo.NewHTTPError(http.StatusUnauthorized, "missing privilege")
}
return next(c)
}
}
}
// CheckPrivilege checks if user in AuthContext has at least one (OR) of given privilege
func (s *AuthContext) CheckPrivilege(privileges ...Privilege) bool {
for _, priv := range s.Privileges {
for _, check := range privileges {
if priv == check {
return true
}
}
}
return false
} |
Beta Was this translation helpful? Give feedback.
7 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
for example I have an API /getProduct, i want to put two signkey (admin, user) to middleware JWT, It mean both user and admin can to access the API. HELP ME PLEASE
Beta Was this translation helpful? Give feedback.
All reactions