验证令牌

This commit is contained in:
xmdhs 2023-09-04 15:41:19 +08:00
parent 48f05b4e95
commit 602cd3957c
No known key found for this signature in database
GPG Key ID: E809D6D43DEFCC95
4 changed files with 103 additions and 1 deletions

View File

@ -1,13 +1,35 @@
package yggdrasil package yggdrasil
import ( import (
"errors"
"net/http" "net/http"
"github.com/julienschmidt/httprouter" "github.com/julienschmidt/httprouter"
"github.com/xmdhs/authlib-skin/model/yggdrasil"
sutils "github.com/xmdhs/authlib-skin/service/utils"
"github.com/xmdhs/authlib-skin/utils"
) )
func (y *Yggdrasil) Validate() httprouter.Handle { func (y *Yggdrasil) Validate() httprouter.Handle {
return func(w http.ResponseWriter, r *http.Request, p httprouter.Params) { return func(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
cxt := r.Context()
a, err := utils.DeCodeBody[yggdrasil.ValidateToken](r.Body, y.validate)
if err != nil {
y.logger.DebugContext(cxt, err.Error())
handleYgError(cxt, w, yggdrasil.Error{ErrorMessage: err.Error()}, 400)
return
}
err = y.yggdrasilService.ValidateToken(cxt, a)
if err != nil {
if errors.Is(err, sutils.ErrTokenInvalid) {
y.logger.DebugContext(cxt, err.Error())
handleYgError(cxt, w, yggdrasil.Error{ErrorMessage: "Invalid token.", Error: "ForbiddenOperationException"}, 403)
return
}
y.logger.WarnContext(cxt, err.Error())
handleYgError(cxt, w, yggdrasil.Error{ErrorMessage: err.Error()}, 500)
return
}
w.WriteHeader(204)
} }
} }

View File

@ -34,3 +34,8 @@ type TokenUser struct {
ID string `json:"id"` ID string `json:"id"`
Properties []any `json:"properties"` Properties []any `json:"properties"`
} }
type ValidateToken struct {
AccessToken string `json:"accessToken" validate:"required,jwt"`
ClientToken string `json:"clientToken"`
}

58
service/utils/auth.go Normal file
View File

@ -0,0 +1,58 @@
package utils
import (
"context"
"errors"
"fmt"
"strconv"
"time"
"github.com/golang-jwt/jwt/v5"
"github.com/xmdhs/authlib-skin/db/ent"
"github.com/xmdhs/authlib-skin/db/ent/usertoken"
"github.com/xmdhs/authlib-skin/model"
"github.com/xmdhs/authlib-skin/model/yggdrasil"
)
var (
ErrTokenInvalid = errors.New("token 无效")
)
func Auth(ctx context.Context, t yggdrasil.ValidateToken, client *ent.Client, jwtKey string) error {
token, err := jwt.ParseWithClaims(t.AccessToken, &model.TokenClaims{}, func(t *jwt.Token) (interface{}, error) {
return []byte(jwtKey), nil
})
if err != nil {
return fmt.Errorf("Auth: %w", err)
}
claims, ok := token.Claims.(*model.TokenClaims)
if !ok || !token.Valid {
return fmt.Errorf("Auth: %w", ErrTokenInvalid)
}
if t.ClientToken != "" && t.ClientToken != claims.CID {
return fmt.Errorf("Auth: %w", ErrTokenInvalid)
}
it, err := claims.GetIssuedAt()
if err != nil {
return fmt.Errorf("Auth: %w", err)
}
et, err := claims.GetExpirationTime()
if err != nil {
return fmt.Errorf("Auth: %w", err)
}
invalidTime := it.Add(et.Time.Sub(it.Time))
if time.Now().After(invalidTime) {
return fmt.Errorf("Auth: %w", ErrTokenInvalid)
}
ut, err := client.UserToken.Query().Where(usertoken.UUIDEQ(claims.Subject)).First(ctx)
if err != nil {
return fmt.Errorf("Auth: %w", err)
}
if strconv.FormatUint(ut.TokenID, 10) != claims.Tid {
return fmt.Errorf("Auth: %w", ErrTokenInvalid)
}
return nil
}

View File

@ -0,0 +1,17 @@
package yggdrasil
import (
"context"
"fmt"
"github.com/xmdhs/authlib-skin/model/yggdrasil"
"github.com/xmdhs/authlib-skin/service/utils"
)
func (y *Yggdrasil) ValidateToken(ctx context.Context, t yggdrasil.ValidateToken) error {
err := utils.Auth(ctx, t, y.client, y.config.JwtKey)
if err != nil {
return fmt.Errorf("ValidateToken: %w", err)
}
return nil
}