验证令牌
This commit is contained in:
parent
48f05b4e95
commit
602cd3957c
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
58
service/utils/auth.go
Normal 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
|
||||||
|
}
|
17
service/yggdrasil/validate.go
Normal file
17
service/yggdrasil/validate.go
Normal 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
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user