Last active
September 27, 2019 13:47
-
-
Save LouisHrg/336c22cd13b8638f8d747a3d53def761 to your computer and use it in GitHub Desktop.
Middleware the works (REALLY) with gin
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package middleware | |
| import ( | |
| "net/http" | |
| "errors" | |
| "time" | |
| "strings" | |
| "github.com/dgrijalva/jwt-go" | |
| "github.com/gin-gonic/gin" | |
| ) | |
| type UnsignedResponse struct { | |
| Message interface{} `json:"message"` | |
| } | |
| type SignedResponse struct { | |
| Token string `json:"token"` | |
| Message string `json:"message"` | |
| } | |
| func index(c *gin.Context) { | |
| c.JSON(200, gin.H{"msg": "index"}) | |
| } | |
| // LoginHandler : The login handler, set it for a /login route for example | |
| func LoginHandler(c *gin.Context) { | |
| type login struct { | |
| Username string `json:"email,omitempty"` | |
| Password string `json:"password,omitempty"` | |
| } | |
| loginParams := login{} | |
| c.ShouldBindJSON(&loginParams) | |
| if loginParams.Username == "test@gmail.com" && loginParams.Password == "test" { | |
| token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{ | |
| "user": loginParams.Username, | |
| "nbf": time.Date(2018, 01, 01, 12, 0, 0, 0, time.UTC).Unix(), | |
| }) | |
| tokenStr, err := token.SignedString([]byte("supersaucysecret")) | |
| if err != nil { | |
| c.JSON(http.StatusInternalServerError, UnsignedResponse{ | |
| Message: err.Error(), | |
| }) | |
| return | |
| } | |
| c.JSON(http.StatusOK, SignedResponse{ | |
| Token: tokenStr, | |
| Message: "logged in", | |
| }) | |
| return | |
| } | |
| c.JSON(http.StatusBadRequest, UnsignedResponse{ | |
| Message: "bad username", | |
| }) | |
| } | |
| func extractBearerToken(header string) (string, error) { | |
| if header == "" { | |
| return "", errors.New("bad header value given") | |
| } | |
| jwtToken := strings.Split(header, " ") | |
| if len(jwtToken) != 2 { | |
| return "", errors.New("incorrectly formatted authorization header") | |
| } | |
| return jwtToken[1], nil | |
| } | |
| func parseToken(jwtToken string) (*jwt.Token, error) { | |
| token, err := jwt.Parse(jwtToken, func(token *jwt.Token) (interface{}, error) { | |
| if _, OK := token.Method.(*jwt.SigningMethodHMAC); !OK { | |
| return nil, errors.New("bad signed method received") | |
| } | |
| return []byte("supersaucysecret"), nil | |
| }) | |
| if err != nil { | |
| return nil, errors.New("bad jwt token") | |
| } | |
| return token, nil | |
| } | |
| // JwtTokenCheck : the middleware, register it for a group of routes | |
| func JwtTokenCheck(c *gin.Context) { | |
| jwtToken, err := extractBearerToken(c.GetHeader("Authorization")) | |
| if err != nil { | |
| c.AbortWithStatusJSON(http.StatusBadRequest, UnsignedResponse{ | |
| Message: err.Error(), | |
| }) | |
| return | |
| } | |
| token, err := parseToken(jwtToken) | |
| if err != nil { | |
| c.AbortWithStatusJSON(http.StatusBadRequest, UnsignedResponse{ | |
| Message: "bad jwt token", | |
| }) | |
| return | |
| } | |
| _, OK := token.Claims.(jwt.MapClaims) | |
| if !OK { | |
| c.AbortWithStatusJSON(http.StatusInternalServerError, UnsignedResponse{ | |
| Message: "unable to parse claims", | |
| }) | |
| return | |
| } | |
| c.Next() | |
| } | |
| func privateACLCheck(c *gin.Context) { | |
| jwtToken, err := extractBearerToken(c.GetHeader("Authorization")) | |
| if err != nil { | |
| c.AbortWithStatusJSON(http.StatusBadRequest, UnsignedResponse{ | |
| Message: err.Error(), | |
| }) | |
| return | |
| } | |
| token, err := parseToken(jwtToken) | |
| if err != nil { | |
| c.AbortWithStatusJSON(http.StatusBadRequest, UnsignedResponse{ | |
| Message: "bad jwt token", | |
| }) | |
| return | |
| } | |
| claims, OK := token.Claims.(jwt.MapClaims) | |
| if !OK { | |
| c.AbortWithStatusJSON(http.StatusInternalServerError, UnsignedResponse{ | |
| Message: "unable to parse claims", | |
| }) | |
| return | |
| } | |
| claimedUID, OK := claims["user"].(string) | |
| if !OK { | |
| c.AbortWithStatusJSON(http.StatusBadRequest, UnsignedResponse{ | |
| Message: "no user property in claims", | |
| }) | |
| return | |
| } | |
| uid := c.Param("uid") | |
| if claimedUID != uid { | |
| c.AbortWithStatusJSON(http.StatusBadRequest, UnsignedResponse{ | |
| Message: "token uid does not match resource uid", | |
| }) | |
| return | |
| } | |
| c.Next() | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
ok