package interceptors import ( "context" "gitea.benny.dog/torjus/ezshare/pb" "gitea.benny.dog/torjus/ezshare/store" "go.uber.org/zap" "google.golang.org/grpc" "google.golang.org/grpc/credentials" "google.golang.org/grpc/peer" ) type ContextKey string var ContextKeyRole ContextKey = "role" var ContextKeyUserID ContextKey = "userid" func NewAuthInterceptor(s store.UserStore, logger *zap.SugaredLogger) grpc.UnaryServerInterceptor { // TODO: Verify that cert is signed by our ca return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) { p, ok := peer.FromContext(ctx) if ok { tlsInfo, ok := p.AuthInfo.(credentials.TLSInfo) if ok { if len(tlsInfo.State.PeerCertificates) == 1 { cert := tlsInfo.State.PeerCertificates[0] id := cert.Subject.CommonName user, err := s.GetUser(id) if err == nil { newCtx := context.WithValue(ctx, ContextKeyRole, user.UserRole) newCtx = context.WithValue(newCtx, ContextKeyUserID, user.Id) logger.Debugw("Authenticated user.", "username", user.Username, "role", user.UserRole.String()) return handler(newCtx, req) } } } } newCtx := context.WithValue(ctx, ContextKeyRole, pb.User_UNKNOWN) return handler(newCtx, req) } } func RoleFromContext(ctx context.Context) pb.User_Role { value := ctx.Value(ContextKeyRole) if value == nil { return pb.User_UNKNOWN } role, ok := value.(pb.User_Role) if ok { return role } return pb.User_UNKNOWN } func UserIDFromContext(ctx context.Context) string { value := ctx.Value(ContextKeyUserID) if value == nil { return "" } id, ok := value.(string) if ok { return id } return "" }