123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799 |
- package jwtauth
- import (
- "crypto/rsa"
- "errors"
- "github.com/dgrijalva/jwt-go"
- "github.com/gin-gonic/gin"
- "github.com/go-redis/redis/v7"
- "io/ioutil"
- "net/http"
- "strings"
- "time"
- )
- const JwtPayloadKey = "JWT_PAYLOAD"
- type MapClaims map[string]interface{}
- // GinJWTMiddleware provides a Json-Web-Token authentication implementation. On failure, a 401 HTTP response
- // is returned. On success, the wrapped middleware is called, and the userID is made available as
- // c.Get("userID").(string).
- // Users can get a token by posting a json request to LoginHandler. The token then needs to be passed in
- // the Authentication header. Example: Authorization:Bearer XXX_TOKEN_XXX
- type GinJWTMiddleware struct {
- // Realm name to display to the user. Required.
- Realm string
- // signing algorithm - possible values are HS256, HS384, HS512
- // Optional, default is HS256.
- SigningAlgorithm string
- // Secret key used for signing. Required.
- Key []byte
- // Duration that a jwt token is valid. Optional, defaults to one hour.
- Timeout time.Duration
- // This field allows clients to refresh their token until MaxRefresh has passed.
- // Note that clients can refresh their token in the last moment of MaxRefresh.
- // This means that the maximum validity timespan for a token is TokenTime + MaxRefresh.
- // Optional, defaults to 0 meaning not refreshable.
- MaxRefresh time.Duration
- // Callback function that should perform the authentication of the user based on login info.
- // Must return user data as user identifier, it will be stored in Claim Array. Required.
- // Check error (e) to determine the appropriate error message.
- Authenticator func(c *gin.Context) (interface{}, error)
- // Callback function that should perform the authorization of the authenticated user. Called
- // only after an authentication success. Must return true on success, false on failure.
- // Optional, default to success.
- Authorizator func(data interface{}, c *gin.Context) bool
- // Callback function that will be called during login.
- // Using this function it is possible to add additional payload data to the webtoken.
- // The data is then made available during requests via c.Get("JWT_PAYLOAD").
- // Note that the payload is not encrypted.
- // The attributes mentioned on jwt.io can't be used as keys for the map.
- // Optional, by default no additional data will be set.
- PayloadFunc func(data interface{}) MapClaims
- // User can define own Unauthorized func.
- Unauthorized func(*gin.Context, int, string)
- // User can define own LoginResponse func.
- LoginResponse func(*gin.Context, int, string, time.Time)
- // User can define own RefreshResponse func.
- RefreshResponse func(*gin.Context, int, string, time.Time)
- // Set the identity handler function
- IdentityHandler func(*gin.Context) interface{}
- // Set the identity key
- IdentityKey string
- // username
- NiceKey string
- DataScopeKey string
- // rolekey
- RKey string
- // roleId
- RoleIdKey string
- //deptId
- DeptIdKey string
- DeptNameKey string
- RoleKey string
- // roleName
- RoleNameKey string
- SingleKey bool
- // TokenLookup is a string in the form of "<source>:<name>" that is used
- // to extract token from the request.
- // Optional. Default value "header:Authorization".
- // Possible values:
- // - "header:<name>"
- // - "query:<name>"
- // - "cookie:<name>"
- TokenLookup string
- // TokenHeadName is a string in the header. Default value is "Bearer"
- TokenHeadName string
- // TimeFunc provides the current time. You can override it to use another time value. This is useful for testing or if your server uses a different time zone than your tokens.
- TimeFunc func() time.Time
- // HTTP Status messages for when something in the JWT middleware fails.
- // Check error (e) to determine the appropriate error message.
- HTTPStatusMessageFunc func(e error, c *gin.Context) string
- // Private key file for asymmetric algorithms
- PrivKeyFile string
- // Public key file for asymmetric algorithms
- PubKeyFile string
- // Private key
- privKey *rsa.PrivateKey
- // Public key
- pubKey *rsa.PublicKey
- // Optionally return the token as a cookie
- SendCookie bool
- // Allow insecure cookies for development over http
- SecureCookie bool
- // Allow cookies to be accessed client side for development
- CookieHTTPOnly bool
- // Allow cookie domain change for development
- CookieDomain string
- // SendAuthorization allow return authorization header for every request
- SendAuthorization bool
- // Disable abort() of context.
- DisabledAbort bool
- // CookieName allow cookie name change for development
- CookieName string
- // 保存token的key
- SaveNewestToken func(c *gin.Context, userId int64, token string, expire int64) error
- GetNewestToken func(c *gin.Context, userId int64) (string, error)
- SetEnterDeptId func(c *gin.Context, newTToken string,userId int64) error
- }
- var (
- // ErrMissingSecretKey indicates Secret key is required
- ErrMissingSecretKey = errors.New("secret key is required")
- // ErrForbidden when HTTP status 403 is given
- ErrForbidden = errors.New("you don't have permission to access this resource")
- // ErrMissingAuthenticatorFunc indicates Authenticator is required
- ErrMissingAuthenticatorFunc = errors.New("ginJWTMiddleware.Authenticator func is undefined")
- // ErrMissingLoginValues indicates a user tried to authenticate without username or password
- ErrMissingLoginValues = errors.New("missing Username or Password or Code")
- // ErrFailedAuthentication indicates authentication failed, could be faulty username or password
- //ErrFailedAuthentication = errors.New("incorrect Username or Password")
- ErrFailedAuthentication = errors.New("用户名或密码不正确")
- ErrFailedSmsVerifyCode = errors.New("短信验证码错误")
- ErrAccountDeactivated = errors.New("账号已停用")
- ErrSingleLogin = errors.New("您的账号已在其他地方登录,请重新登录或退出")
- // ErrFailedTokenCreation indicates JWT Token failed to create, reason unknown
- ErrFailedTokenCreation = errors.New("failed to create JWT Token")
- // ErrExpiredToken indicates JWT token has expired. Can't refresh.
- ErrExpiredToken = errors.New("Token is expired")
- // ErrEmptyAuthHeader can be thrown if authing with a HTTP header, the Auth header needs to be set
- ErrEmptyAuthHeader = errors.New("auth header is empty")
- // ErrMissingExpField missing exp field in token
- ErrMissingExpField = errors.New("missing exp field")
- // ErrWrongFormatOfExp field must be float64 format
- ErrWrongFormatOfExp = errors.New("exp must be float64 format")
- // ErrInvalidAuthHeader indicates auth header is invalid, could for example have the wrong Realm name
- ErrInvalidAuthHeader = errors.New("auth header is invalid")
- // ErrEmptyQueryToken can be thrown if authing with URL Query, the query token variable is empty
- ErrEmptyQueryToken = errors.New("query token is empty")
- // ErrEmptyCookieToken can be thrown if authing with a cookie, the token cokie is empty
- ErrEmptyCookieToken = errors.New("cookie token is empty")
- // ErrEmptyParamToken can be thrown if authing with parameter in path, the parameter in path is empty
- ErrEmptyParamToken = errors.New("parameter token is empty")
- // ErrInvalidSigningAlgorithm indicates signing algorithm is invalid, needs to be HS256, HS384, HS512, RS256, RS384 or RS512
- ErrInvalidSigningAlgorithm = errors.New("invalid signing algorithm")
- ErrInvalidVerificationCode = errors.New("验证码错误")
- // ErrNoPrivKeyFile indicates that the given private key is unreadable
- ErrNoPrivKeyFile = errors.New("private key file unreadable")
- // ErrNoPubKeyFile indicates that the given public key is unreadable
- ErrNoPubKeyFile = errors.New("public key file unreadable")
- // ErrInvalidPrivKey indicates that the given private key is invalid
- ErrInvalidPrivKey = errors.New("private key invalid")
- // ErrInvalidPubKey indicates the the given public key is invalid
- ErrInvalidPubKey = errors.New("public key invalid")
- UUIDKey = "uuid"
- // IdentityKey default identity key
- IdentityKey = "identity"
- UserNameKey = "username"
- DataScopeKey = "dataScope"
- // RoleIdKey 角色id Old
- RoleIdKey = "roleId"
- // RoleKey 角色key Old
- RoleKey = "roleKey"
- // RoleNameKey 角色名称 Old
- RoleNameKey = "roleName"
- // 单一登录标识
- SingleKey = "single"
- // DeptIdKey 部门 Old
- DeptIdKey = "deptId"
- DeptNameKey = "deptName"
- RandomKey = "randomName"
- )
- // New for check error with GinJWTMiddleware
- func New(m *GinJWTMiddleware) (*GinJWTMiddleware, error) {
- if err := m.MiddlewareInit(); err != nil {
- return nil, err
- }
- return m, nil
- }
- func (mw *GinJWTMiddleware) readKeys() error {
- err := mw.privateKey()
- if err != nil {
- return err
- }
- err = mw.publicKey()
- if err != nil {
- return err
- }
- return nil
- }
- func (mw *GinJWTMiddleware) privateKey() error {
- keyData, err := ioutil.ReadFile(mw.PrivKeyFile)
- if err != nil {
- return ErrNoPrivKeyFile
- }
- key, err := jwt.ParseRSAPrivateKeyFromPEM(keyData)
- if err != nil {
- return ErrInvalidPrivKey
- }
- mw.privKey = key
- return nil
- }
- func (mw *GinJWTMiddleware) publicKey() error {
- keyData, err := ioutil.ReadFile(mw.PubKeyFile)
- if err != nil {
- return ErrNoPubKeyFile
- }
- key, err := jwt.ParseRSAPublicKeyFromPEM(keyData)
- if err != nil {
- return ErrInvalidPubKey
- }
- mw.pubKey = key
- return nil
- }
- func (mw *GinJWTMiddleware) usingPublicKeyAlgo() bool {
- switch mw.SigningAlgorithm {
- case "RS256", "RS512", "RS384":
- return true
- }
- return false
- }
- // MiddlewareInit initialize jwt configs.
- func (mw *GinJWTMiddleware) MiddlewareInit() error {
- if mw.TokenLookup == "" {
- mw.TokenLookup = "header:Authorization"
- }
- if mw.SigningAlgorithm == "" {
- mw.SigningAlgorithm = "HS256"
- }
- if mw.TimeFunc == nil {
- mw.TimeFunc = time.Now
- }
- mw.TokenHeadName = strings.TrimSpace(mw.TokenHeadName)
- if len(mw.TokenHeadName) == 0 {
- mw.TokenHeadName = "Bearer"
- }
- if mw.Authorizator == nil {
- mw.Authorizator = func(data interface{}, c *gin.Context) bool {
- return true
- }
- }
- if mw.Unauthorized == nil {
- mw.Unauthorized = func(c *gin.Context, code int, message string) {
- c.JSON(http.StatusOK, gin.H{
- "code": code,
- "message": message,
- })
- }
- }
- if mw.LoginResponse == nil {
- mw.LoginResponse = func(c *gin.Context, code int, token string, expire time.Time) {
- c.JSON(http.StatusOK, gin.H{
- "code": http.StatusOK,
- "token": token,
- "expire": expire.Format(time.RFC3339),
- })
- }
- }
- if mw.RefreshResponse == nil {
- mw.RefreshResponse = func(c *gin.Context, code int, token string, expire time.Time) {
- c.JSON(http.StatusOK, gin.H{
- "code": http.StatusOK,
- "token": token,
- "expire": expire.Format(time.RFC3339),
- })
- }
- }
- if mw.IdentityKey == "" {
- mw.IdentityKey = IdentityKey
- }
- if mw.IdentityHandler == nil {
- mw.IdentityHandler = func(c *gin.Context) interface{} {
- claims := ExtractClaims(c)
- return claims
- }
- }
- if mw.HTTPStatusMessageFunc == nil {
- mw.HTTPStatusMessageFunc = func(e error, c *gin.Context) string {
- return e.Error()
- }
- }
- if mw.Realm == "" {
- mw.Realm = "gin jwt"
- }
- if mw.CookieName == "" {
- mw.CookieName = "jwt"
- }
- if mw.usingPublicKeyAlgo() {
- return mw.readKeys()
- }
- if mw.Key == nil {
- return ErrMissingSecretKey
- }
- return nil
- }
- // MiddlewareFunc makes GinJWTMiddleware implement the Middleware interface.
- func (mw *GinJWTMiddleware) MiddlewareFunc() gin.HandlerFunc {
- return func(c *gin.Context) {
- mw.middlewareImpl(c)
- }
- }
- func (mw *GinJWTMiddleware) middlewareImpl(c *gin.Context) {
- claims, err := mw.GetClaimsFromJWT(c)
- if err != nil {
- if err.Error() == ErrExpiredToken.Error() {
- mw.unauthorized(c, 6401, mw.HTTPStatusMessageFunc(ErrExpiredToken, c))
- return
- } else {
- mw.unauthorized(c, http.StatusUnauthorized, mw.HTTPStatusMessageFunc(err, c))
- return
- }
- }
- if claims["exp"] == nil {
- mw.unauthorized(c, http.StatusBadRequest, mw.HTTPStatusMessageFunc(ErrMissingExpField, c))
- return
- }
- if _, ok := claims["exp"].(float64); !ok {
- mw.unauthorized(c, http.StatusBadRequest, mw.HTTPStatusMessageFunc(ErrWrongFormatOfExp, c))
- return
- }
- if int64(claims["exp"].(float64)) < mw.TimeFunc().Unix() {
- mw.unauthorized(c, 6401, mw.HTTPStatusMessageFunc(ErrExpiredToken, c))
- return
- }
- c.Set(JwtPayloadKey, claims)
- identity := mw.IdentityHandler(c)
- if identity != nil {
- c.Set(mw.IdentityKey, identity)
- }
- if !mw.Authorizator(identity, c) {
- mw.unauthorized(c, http.StatusForbidden, mw.HTTPStatusMessageFunc(ErrForbidden, c))
- return
- }
- if claims["single"].(bool) {
- token, err := mw.GetNewestToken(c, int64(claims["identity"].(float64)))
- if err != nil && errors.Is(err, redis.Nil) {
- // 没有获取到最新的token
- mw.unauthorized(c, http.StatusUnauthorized, mw.HTTPStatusMessageFunc(ErrEmptyQueryToken, c))
- return
- }
- if token != GetToken(c) {
- mw.unauthorized(c, http.StatusUnauthorized, mw.HTTPStatusMessageFunc(ErrSingleLogin, c))
- return
- }
- }
- c.Next()
- }
- // GetClaimsFromJWT get claims from JWT token
- func (mw *GinJWTMiddleware) GetClaimsFromJWT(c *gin.Context) (MapClaims, error) {
- token, err := mw.ParseToken(c)
- if err != nil {
- return nil, err
- }
- if mw.SendAuthorization {
- if v, ok := c.Get("JWT_TOKEN"); ok {
- c.Header("Authorization", mw.TokenHeadName+" "+v.(string))
- }
- }
- claims := MapClaims{}
- for key, value := range token.Claims.(jwt.MapClaims) {
- claims[key] = value
- }
- return claims, nil
- }
- // LoginHandler can be used by clients to get a jwt token.
- // Payload needs to be json in the form of {"username": "USERNAME", "password": "PASSWORD"}.
- // Reply will be of the form {"token": "TOKEN"}.
- func (mw *GinJWTMiddleware) LoginHandler(c *gin.Context) {
- if mw.Authenticator == nil {
- mw.unauthorized(c, http.StatusInternalServerError, mw.HTTPStatusMessageFunc(ErrMissingAuthenticatorFunc, c))
- return
- }
- data, err := mw.Authenticator(c)
- if err != nil {
- mw.unauthorized(c, 400, mw.HTTPStatusMessageFunc(err, c))
- return
- }
- // Create the token
- token := jwt.New(jwt.GetSigningMethod(mw.SigningAlgorithm))
- claims := token.Claims.(jwt.MapClaims)
- if mw.PayloadFunc != nil {
- for key, value := range mw.PayloadFunc(data) {
- claims[key] = value
- }
- }
- expire := mw.TimeFunc().Add(mw.Timeout)
- // 登录类型 手机登录
- if v, ok := data.(map[string]interface{}); ok {
- if t, ok2 := v["mobile"].(bool); ok2 {
- if t {
- expire = mw.TimeFunc().Add(time.Duration(876000/2) * time.Hour)
- //mw.Timeout = time.Duration(876000) * time.Hour
- }
- }
- }
- claims["exp"] = expire.Unix()
- claims["orig_iat"] = mw.TimeFunc().Unix()
- tokenString, err := mw.signedString(token)
- if err != nil {
- mw.unauthorized(c, http.StatusInternalServerError, mw.HTTPStatusMessageFunc(ErrFailedTokenCreation, c))
- return
- }
- // set cookie
- if mw.SendCookie {
- maxage := int(expire.Unix() - time.Now().Unix())
- c.SetCookie(
- mw.CookieName,
- tokenString,
- maxage,
- "/",
- mw.CookieDomain,
- mw.SecureCookie,
- mw.CookieHTTPOnly,
- )
- }
- if claims["single"].(bool) {
- _ = mw.SaveNewestToken(c, int64(claims["identity"].(int)), tokenString, int64(mw.Timeout)/3600)
- }
- mw.LoginResponse(c, http.StatusOK, tokenString, expire)
- }
- func (mw *GinJWTMiddleware) signedString(token *jwt.Token) (string, error) {
- var tokenString string
- var err error
- if mw.usingPublicKeyAlgo() {
- tokenString, err = token.SignedString(mw.privKey)
- } else {
- tokenString, err = token.SignedString(mw.Key)
- }
- return tokenString, err
- }
- func (mw *GinJWTMiddleware) RefreshHandler(c *gin.Context) {
- tokenString, expire, err := mw.RefreshToken(c)
- if err != nil {
- mw.unauthorized(c, http.StatusUnauthorized, mw.HTTPStatusMessageFunc(err, c))
- return
- }
- mw.RefreshResponse(c, http.StatusOK, tokenString, expire)
- }
- // RefreshToken refresh token and check if token is expired
- func (mw *GinJWTMiddleware) RefreshToken(c *gin.Context) (string, time.Time, error) {
- claims, err := mw.CheckIfTokenExpire(c)
- if err != nil {
- return "", time.Now(), err
- }
- // Create the token
- newToken := jwt.New(jwt.GetSigningMethod(mw.SigningAlgorithm))
- newClaims := newToken.Claims.(jwt.MapClaims)
- for key := range claims {
- newClaims[key] = claims[key]
- }
- expire := mw.TimeFunc().Add(mw.Timeout)
- newClaims["exp"] = expire.Unix()
- newClaims["orig_iat"] = mw.TimeFunc().Unix()
- tokenString, err := mw.signedString(newToken)
- if err != nil {
- return "", time.Now(), err
- }
- // set cookie
- if mw.SendCookie {
- maxage := int(expire.Unix() - time.Now().Unix())
- c.SetCookie(
- mw.CookieName,
- tokenString,
- maxage,
- "/",
- mw.CookieDomain,
- mw.SecureCookie,
- mw.CookieHTTPOnly,
- )
- }
- if mw.SetEnterDeptId != nil {
- mw.SetEnterDeptId(c,tokenString,int64(claims["identity"].(float64)))
- }
- if claims["single"].(bool) {
- _ = mw.SaveNewestToken(c, int64(claims["identity"].(float64)), tokenString, int64(mw.Timeout)/3600)
- }
- return tokenString, expire, nil
- }
- // CheckIfTokenExpire check if token expire
- func (mw *GinJWTMiddleware) CheckIfTokenExpire(c *gin.Context) (jwt.MapClaims, error) {
- token, err := mw.ParseToken(c)
- if err != nil {
- // If we receive an error, and the error is anything other than a single
- // ValidationErrorExpired, we want to return the error.
- // If the error is just ValidationErrorExpired, we want to continue, as we can still
- // refresh the token if it's within the MaxRefresh time.
- // (see https://github.com/appleboy/gin-jwt/issues/176)
- validationErr, ok := err.(*jwt.ValidationError)
- if !ok || validationErr.Errors != jwt.ValidationErrorExpired {
- return nil, err
- }
- }
- claims := token.Claims.(jwt.MapClaims)
- origIat := int64(claims["orig_iat"].(float64))
- if origIat < mw.TimeFunc().Add(-mw.MaxRefresh).Unix() {
- return nil, ErrExpiredToken
- }
- return claims, nil
- }
- // TokenGenerator method that clients can use to get a jwt token.
- func (mw *GinJWTMiddleware) TokenGenerator(data interface{}) (string, time.Time, error) {
- token := jwt.New(jwt.GetSigningMethod(mw.SigningAlgorithm))
- claims := token.Claims.(jwt.MapClaims)
- if mw.PayloadFunc != nil {
- for key, value := range mw.PayloadFunc(data) {
- claims[key] = value
- }
- }
- expire := mw.TimeFunc().UTC().Add(mw.Timeout)
- claims["exp"] = expire.Unix()
- claims["orig_iat"] = mw.TimeFunc().Unix()
- tokenString, err := mw.signedString(token)
- if err != nil {
- return "", time.Time{}, err
- }
- return tokenString, expire, nil
- }
- func (mw *GinJWTMiddleware) jwtFromHeader(c *gin.Context, key string) (string, error) {
- authHeader := c.Request.Header.Get(key)
- if authHeader == "" {
- return "", ErrEmptyAuthHeader
- }
- parts := strings.SplitN(authHeader, " ", 2)
- if !(len(parts) == 2 && parts[0] == mw.TokenHeadName) {
- return "", ErrInvalidAuthHeader
- }
- return parts[1], nil
- }
- func (mw *GinJWTMiddleware) jwtFromQuery(c *gin.Context, key string) (string, error) {
- token := c.Query(key)
- if token == "" {
- return "", ErrEmptyQueryToken
- }
- return token, nil
- }
- func (mw *GinJWTMiddleware) jwtFromCookie(c *gin.Context, key string) (string, error) {
- cookie, _ := c.Cookie(key)
- if cookie == "" {
- return "", ErrEmptyCookieToken
- }
- return cookie, nil
- }
- func (mw *GinJWTMiddleware) jwtFromParam(c *gin.Context, key string) (string, error) {
- token := c.Param(key)
- if token == "" {
- return "", ErrEmptyParamToken
- }
- return token, nil
- }
- // ParseToken parse jwt token from gin context
- func (mw *GinJWTMiddleware) ParseToken(c *gin.Context) (*jwt.Token, error) {
- var token string
- var err error
- methods := strings.Split(mw.TokenLookup, ",")
- for _, method := range methods {
- if len(token) > 0 {
- break
- }
- parts := strings.Split(strings.TrimSpace(method), ":")
- k := strings.TrimSpace(parts[0])
- v := strings.TrimSpace(parts[1])
- switch k {
- case "header":
- token, err = mw.jwtFromHeader(c, v)
- case "query":
- token, err = mw.jwtFromQuery(c, v)
- case "cookie":
- token, err = mw.jwtFromCookie(c, v)
- case "param":
- token, err = mw.jwtFromParam(c, v)
- }
- }
- if err != nil {
- return nil, err
- }
- return jwt.Parse(token, func(t *jwt.Token) (interface{}, error) {
- if jwt.GetSigningMethod(mw.SigningAlgorithm) != t.Method {
- return nil, ErrInvalidSigningAlgorithm
- }
- if mw.usingPublicKeyAlgo() {
- return mw.pubKey, nil
- }
- c.Set("JWT_TOKEN", token)
- return mw.Key, nil
- })
- }
- // ParseTokenString parse jwt token string
- func (mw *GinJWTMiddleware) ParseTokenString(token string) (*jwt.Token, error) {
- return jwt.Parse(token, func(t *jwt.Token) (interface{}, error) {
- if jwt.GetSigningMethod(mw.SigningAlgorithm) != t.Method {
- return nil, ErrInvalidSigningAlgorithm
- }
- if mw.usingPublicKeyAlgo() {
- return mw.pubKey, nil
- }
- return mw.Key, nil
- })
- }
- func (mw *GinJWTMiddleware) unauthorized(c *gin.Context, code int, message string) {
- c.Header("WWW-Authenticate", "JWT realm="+mw.Realm)
- if !mw.DisabledAbort {
- c.Abort()
- }
- mw.Unauthorized(c, code, message)
- }
- // ExtractClaims help to extract the JWT claims
- func ExtractClaims(c *gin.Context) MapClaims {
- claims, exists := c.Get(JwtPayloadKey)
- if !exists {
- return make(MapClaims)
- }
- return claims.(MapClaims)
- }
- // ExtractClaimsFromToken help to extract the JWT claims from token
- func ExtractClaimsFromToken(token *jwt.Token) MapClaims {
- if token == nil {
- return make(MapClaims)
- }
- claims := MapClaims{}
- for key, value := range token.Claims.(jwt.MapClaims) {
- claims[key] = value
- }
- return claims
- }
- // GetToken help to get the JWT token string
- func GetToken(c *gin.Context) string {
- token, exists := c.Get("JWT_TOKEN")
- if !exists {
- return ""
- }
- return token.(string)
- }
|