You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Open-IM-Server/pkg/common/tokenverify/jwt_token.go

118 lines
3.8 KiB

// Copyright © 2023 OpenIM. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package tokenverify
import (
"context"
"fmt"
"github.com/OpenIMSDK/Open-IM-Server/pkg/common/config"
"github.com/OpenIMSDK/Open-IM-Server/pkg/common/mcontext"
"github.com/OpenIMSDK/Open-IM-Server/pkg/errs"
"github.com/OpenIMSDK/Open-IM-Server/pkg/utils"
"github.com/golang-jwt/jwt/v4"
"time"
)
type Claims struct {
UserID string
PlatformID int //login platform
jwt.RegisteredClaims
}
func BuildClaims(uid string, platformID int, ttl int64) Claims {
now := time.Now()
before := now.Add(-time.Minute * 5)
return Claims{
UserID: uid,
PlatformID: platformID,
RegisteredClaims: jwt.RegisteredClaims{
ExpiresAt: jwt.NewNumericDate(now.Add(time.Duration(ttl*24) * time.Hour)), //Expiration time
IssuedAt: jwt.NewNumericDate(now), //Issuing time
NotBefore: jwt.NewNumericDate(before), //Begin Effective time
}}
}
func secret() jwt.Keyfunc {
return func(token *jwt.Token) (interface{}, error) {
return []byte(config.Config.TokenPolicy.AccessSecret), nil
}
}
func GetClaimFromToken(tokensString string) (*Claims, error) {
token, err := jwt.ParseWithClaims(tokensString, &Claims{}, secret())
if err != nil {
if ve, ok := err.(*jwt.ValidationError); ok {
if ve.Errors&jwt.ValidationErrorMalformed != 0 {
return nil, utils.Wrap(errs.ErrTokenMalformed, "")
} else if ve.Errors&jwt.ValidationErrorExpired != 0 {
return nil, utils.Wrap(errs.ErrTokenExpired, "")
} else if ve.Errors&jwt.ValidationErrorNotValidYet != 0 {
return nil, utils.Wrap(errs.ErrTokenNotValidYet, "")
} else {
return nil, utils.Wrap(errs.ErrTokenUnknown, "")
}
} else {
return nil, utils.Wrap(errs.ErrTokenUnknown, "")
}
} else {
if claims, ok := token.Claims.(*Claims); ok && token.Valid {
return claims, nil
}
return nil, utils.Wrap(errs.ErrTokenUnknown, "")
}
}
func CheckAccessV3(ctx context.Context, ownerUserID string) (err error) {
opUserID := mcontext.GetOpUserID(ctx)
if utils.IsContain(opUserID, config.Config.Manager.UserID) {
return nil
}
if opUserID == ownerUserID {
return nil
}
return errs.ErrIdentity.Wrap(utils.GetSelfFuncName())
}
func IsAppManagerUid(ctx context.Context) bool {
return utils.IsContain(mcontext.GetOpUserID(ctx), config.Config.Manager.UserID)
}
func CheckAdmin(ctx context.Context) error {
if utils.IsContain(mcontext.GetOpUserID(ctx), config.Config.Manager.UserID) {
return nil
}
return errs.ErrIdentity.Wrap(fmt.Sprintf("user %s is not admin userID", mcontext.GetOpUserID(ctx)))
}
func ParseRedisInterfaceToken(redisToken interface{}) (*Claims, error) {
return GetClaimFromToken(string(redisToken.([]uint8)))
}
func IsManagerUserID(opUserID string) bool {
return utils.IsContain(opUserID, config.Config.Manager.UserID)
}
func WsVerifyToken(token, userID string, platformID int) error {
claim, err := GetClaimFromToken(token)
if err != nil {
return err
}
if claim.UserID != userID {
return errs.ErrTokenInvalid.Wrap(fmt.Sprintf("token uid %s != userID %s", claim.UserID, userID))
}
if claim.PlatformID != platformID {
return errs.ErrTokenInvalid.Wrap(fmt.Sprintf("token platform %d != %d", claim.PlatformID, platformID))
}
return nil
}