When dealing with API authorization based on access tokens, permissions (user can see a list, can create an item, can delete one etc) and/or account types (administrator, moderator, normal user etc), I’ve seen the approach of checking requirements inside the HTTP handlers functions.
This post and attached source code do not handle security, API design, data storage patterns or any other best practices that do not aim directly at the main subject: Authorization through middlewares. All other code is just for illustrating the idea as a whole.
A classical way of dealing various authorization checks is to verify everything inside the handler function.
type User struct { Username string Type string Permissions uint8 } var CanDoAction uint8 = 1 func tokenIsValid(token string) bool { // ... return true } func getUserHandler(c echo.Context) error { // Check authorization token token := c.Get("token").(string) if !tokenIsValid(token) { return c.NoContent(http.StatusUnauthorized) } user := c.Get("user").(User) // Check account type if user.Type != "admin" { return c.NoContent(http.StatusForbidden) } // Check permission for handler if user.Permissions&CanDoAction == 0 { return c.NoContent(http.StatusForbidden) } // Get data and send it as response data := struct { Username string `json:"username"` }{ Username: user.Username, } return c.JSON(http.StatusOK, data) }
The handler is doing more than its purpose. Continue reading API authorization through middlewares