package auth import ( "context" "fmt" "github.com/sirupsen/logrus" "go-micro.dev/v4/auth" "go-micro.dev/v4/metadata" "sghgogs.com/micro/common" "sghgogs.com/micro/common/errorcode" "sghgogs.com/micro/shopping-service/domain/service" pb "sghgogs.com/micro/shopping-service/proto" "sghgogs.com/micro/shopping-service/utils/authutil" "strconv" "strings" "time" ) type Auth struct { Service service.IService Namespace string } func (svc *Auth) Login(ctx context.Context, query *pb.LoginRequest, rsp *pb.LoginResponse) error { login, GroupID, err := svc.Service.Login(query) if err != nil { return err } md := map[string]string{} md["username"] = login.Username md["user_id"] = fmt.Sprintf("%d", login.Id) md["phone_number"] = login.PhoneNumber md["code"] = query.Code md["group_id"] = fmt.Sprintf("%d", GroupID) var roles []string for _, role := range login.Roles { roles = append(roles, strings.ToLower(role.Key)) } expiry := time.Second * time.Duration(72*3600) md["timestamp"] = fmt.Sprintf("%d", 72*3600) md["expiry"] = fmt.Sprintf("%d", expiry) token, err := authutil.JWTAuthService.GenerateToken(login.Id, "system", "user", login.PhoneNumber, roles, md) if err != nil { return errorcode.BadRequest(svc.Namespace, common.ErrorMessage[common.FailedToGenerateTokenErrorCode]) } a, err := authutil.JWTAuthService.Token(login.Id, token.Secret, expiry) if err != nil { return errorcode.BadRequest(svc.Namespace, common.ErrorMessage[common.FailedToGenerateTokenErrorCode]) } if err = authutil.JWTAuthService.StoreToken(ctx, login.Id, login.Username, a.AccessToken); err != nil { return errorcode.BadRequest(svc.Namespace, common.ErrorMessage[common.FailedToStoreTokenErrorCode]) } rsp.Data = login rsp.Token = a.AccessToken return nil } func (svc *Auth) Logout(ctx context.Context, request *pb.LogoutRequest, rsp *pb.LogoutResponse) error { md, b := metadata.FromContext(ctx) if !b { return errorcode.Unauthorized(svc.Namespace, common.ErrorMessage[common.UnauthorizedErrorCode]) } authHeader, ok := md["Authorization"] if !ok || !strings.HasPrefix(authHeader, auth.BearerScheme) { logrus.Error("no auth token provided") return errorcode.Unauthorized(svc.Namespace, common.ErrorMessage[common.UnauthorizedErrorCode]) } // Extract auth token. token := strings.TrimPrefix(authHeader, auth.BearerScheme) token = strings.TrimSpace(token) if err := authutil.JWTAuthService.Blacklist(token); err != nil { return errorcode.Unauthorized(svc.Namespace, common.ErrorMessage[common.FailedRedisInternalServerErrorCode]) } return nil } func (svc *Auth) Profile(ctx context.Context, request *pb.ProfileRequest, rsp *pb.ProfileResponse) error { md, b := metadata.FromContext(ctx) if !b { return errorcode.Unauthorized(svc.Namespace, common.ErrorMessage[common.UnauthorizedErrorCode]) } authHeader, ok := md["Authorization"] if !ok || !strings.HasPrefix(authHeader, auth.BearerScheme) { logrus.Error("no auth token provided") return errorcode.Unauthorized(svc.Namespace, common.ErrorMessage[common.UnauthorizedErrorCode]) } // Extract auth token. token := strings.TrimPrefix(authHeader, auth.BearerScheme) token = strings.TrimSpace(token) inspect, errE := authutil.JWTAuthService.Inspect(token) if errE != nil { return errorcode.Unauthorized(svc.Namespace, common.ErrorMessage[common.TokenInvalidErrorCode]) } if value, isOk := inspect.Metadata["user_id"]; isOk { userID, _ := strconv.ParseInt(value, 10, 64) groupID, _ := strconv.ParseInt(inspect.Metadata["group_id"], 10, 64) if profile, err := svc.Service.Profile(groupID, userID); err != nil { return err } else { rsp.Data = profile } } return nil }