github.com/infraboard/keyauth@v0.8.1/common/interceptor/grpc/auther.go (about)

     1  package auther
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  
     7  	"github.com/infraboard/mcube/app"
     8  	"github.com/infraboard/mcube/logger"
     9  	"github.com/infraboard/mcube/logger/zap"
    10  	"google.golang.org/grpc"
    11  	"google.golang.org/grpc/codes"
    12  	"google.golang.org/grpc/metadata"
    13  	"google.golang.org/grpc/status"
    14  
    15  	"github.com/infraboard/keyauth/apps/micro"
    16  	"github.com/infraboard/keyauth/common/header"
    17  )
    18  
    19  // GrpcAuthUnaryServerInterceptor returns a new unary server interceptor for auth.
    20  func GrpcAuthUnaryServerInterceptor() grpc.UnaryServerInterceptor {
    21  	return newGrpcAuther().Auth
    22  }
    23  
    24  func newGrpcAuther() *grpcAuther {
    25  	return &grpcAuther{
    26  		log:   zap.L().Named("Grpc Auther"),
    27  		micro: app.GetGrpcApp(micro.AppName).(micro.ServiceServer),
    28  	}
    29  }
    30  
    31  // internal todo
    32  type grpcAuther struct {
    33  	log   logger.Logger
    34  	micro micro.ServiceServer
    35  }
    36  
    37  func (a *grpcAuther) Auth(
    38  	ctx context.Context, req interface{},
    39  	info *grpc.UnaryServerInfo,
    40  	handler grpc.UnaryHandler,
    41  ) (resp interface{}, err error) {
    42  	// 重上下文中获取认证信息
    43  	md, ok := metadata.FromIncomingContext(ctx)
    44  	if !ok {
    45  		return nil, fmt.Errorf("ctx is not an grpc incoming context")
    46  	}
    47  
    48  	clientId, clientSecret := a.GetClientCredentialsFromMeta(md)
    49  
    50  	// 校验调用的客户端凭证是否有效
    51  	if err := a.validateServiceCredential(clientId, clientSecret); err != nil {
    52  		return nil, err
    53  	}
    54  
    55  	resp, err = handler(ctx, req)
    56  	return resp, err
    57  }
    58  
    59  func (a *grpcAuther) GetClientCredentialsFromMeta(md metadata.MD) (
    60  	clientId, clientSecret string) {
    61  	cids := md.Get(header.ClientHeaderKey)
    62  	sids := md.Get(header.ClientSecretKey)
    63  	if len(cids) > 0 {
    64  		clientId = cids[0]
    65  	}
    66  	if len(sids) > 0 {
    67  		clientSecret = sids[0]
    68  	}
    69  	return
    70  }
    71  
    72  func (a *grpcAuther) validateServiceCredential(clientId, clientSecret string) error {
    73  	if clientId == "" && clientSecret == "" {
    74  		return status.Errorf(codes.Unauthenticated, "client_id or client_secret is \"\"")
    75  	}
    76  
    77  	vsReq := micro.NewValidateClientCredentialRequest(clientId, clientSecret)
    78  	_, err := a.micro.ValidateClientCredential(context.Background(), vsReq)
    79  	if err != nil {
    80  		return status.Errorf(codes.Unauthenticated, "service auth error, %s", err)
    81  	}
    82  
    83  	return nil
    84  }