habityzer/kinde-bundle 问题修复 & 功能扩展

解决BUG、新增功能、兼容多环境部署,快速响应你的开发需求

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

habityzer/kinde-bundle

最新稳定版本:v2.0.0

Composer 安装命令:

composer require habityzer/kinde-bundle

包简介

Symfony bundle for Kinde authentication integration with JWT validation, webhooks, and user sync

README 文档

README

Symfony bundle for Kinde authentication integration with JWT validation, webhooks, and user synchronization.

Features

  • JWT Token Validation - Validates Kinde tokens using JWKS with automatic caching
  • Symfony Security Integration - Custom authenticator for seamless integration
  • User Synchronization - Sync users from Kinde to your database
  • Webhook Support - Handle Kinde webhook events (user updates, subscriptions)
  • Event-Driven - Dispatch Symfony events for business logic
  • Fully Decoupled - Uses interfaces for app-specific logic
  • Debug Command - CLI tool to inspect and debug JWT tokens

Requirements

  • PHP 8.2 or higher
  • Symfony 6.4 or 7.x
  • Kinde account with configured application

Installation

composer require habityzer/kinde-bundle

The bundle installs successfully without configuration, but you must configure it before using:

1. Set Environment Variables

Add to your .env file:

KINDE_DOMAIN=https://your-business.kinde.com
KINDE_CLIENT_ID=your-client-id-from-kinde
KINDE_CLIENT_SECRET=your-client-secret
KINDE_WEBHOOK_SECRET=your-webhook-secret

Get these values from your Kinde Dashboard. See Kinde Setup Guide for detailed instructions.

2. Create Configuration File

Create config/packages/habityzer_kinde.yaml:

habityzer_kinde:
    domain: '%env(KINDE_DOMAIN)%'
    client_id: '%env(KINDE_CLIENT_ID)%'
    client_secret: '%env(KINDE_CLIENT_SECRET)%'
    webhook_secret: '%env(KINDE_WEBHOOK_SECRET)%'

3. Clear Cache

php bin/console cache:clear

Note: The bundle will throw helpful runtime errors if you try to use authentication without proper configuration.

Configuration Reference

# config/packages/habityzer_kinde.yaml
habityzer_kinde:
    # Required: Your Kinde domain (e.g., https://your-business.kinde.com)
    domain: '%env(KINDE_DOMAIN)%'
    
    # Required: Kinde application client ID
    client_id: '%env(KINDE_CLIENT_ID)%'
    
    # Optional: Kinde application client secret (for server-side flows)
    client_secret: '%env(KINDE_CLIENT_SECRET)%'
    
    # Required for webhooks: Secret for webhook signature verification
    webhook_secret: '%env(KINDE_WEBHOOK_SECRET)%'
    
    # Optional: JWKS cache duration in seconds (default: 3600 = 1 hour)
    jwks_cache_ttl: 3600
    
    # Optional: Auto-register webhook route at /api/webhooks/kinde (default: true)
    enable_webhook_route: true

Quick Start

1. Implement the User Provider Interface

Create a class that implements KindeUserProviderInterface to handle user management:

namespace App\Kinde;

use Habityzer\KindeBundle\Contract\KindeUserProviderInterface;
use App\Entity\User;
use App\Repository\UserRepository;
use Doctrine\ORM\EntityManagerInterface;

class UserProvider implements KindeUserProviderInterface
{
    public function __construct(
        private readonly UserRepository $userRepository,
        private readonly EntityManagerInterface $em
    ) {}

    public function findByKindeId(string $kindeId): ?object
    {
        return $this->userRepository->findOneBy(['kindeId' => $kindeId]);
    }
    
    public function syncUser(array $kindeUserData): object
    {
        $user = new User();
        $user->setKindeId($kindeUserData['kinde_id']);
        $user->setEmail($kindeUserData['email']);
        $user->setName($kindeUserData['name'] ?? '');
        
        $this->em->persist($user);
        $this->em->flush();
        
        return $user;
    }
    
    public function updateUser(object $user, array $kindeUserData): void
    {
        $user->setEmail($kindeUserData['email']);
        $user->setName($kindeUserData['name'] ?? '');
        $this->em->flush();
    }
    
    public function handleUserDeletion(object $user): void
    {
        $user->setKindeId(null); // Soft delete approach
        $this->em->flush();
    }
}

Register it as a service:

# config/services.yaml
services:
    App\Kinde\UserProvider:
        tags:
            - { name: 'habityzer_kinde.user_provider' }

2. Configure Security

# config/packages/security.yaml
security:
    firewalls:
        # Allow public access to Kinde webhook
        kinde_webhook:
            pattern: ^/api/webhooks/kinde$
            stateless: true
            security: false
        
        # API firewall with Kinde authentication
        api:
            pattern: ^/api/
            stateless: true
            custom_authenticators:
                - Habityzer\KindeBundle\Security\KindeTokenAuthenticator

3. Token Format

When making API requests, prefix your Kinde JWT tokens with kinde_:

Authorization: Bearer kinde_eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImtpZF8xMjM0In0...

This prefix allows the authenticator to identify Kinde tokens and coexist with other authentication methods. The authenticator automatically removes the kinde_ prefix before validating the JWT.

Client-side example (JavaScript):

// Prepend kinde_ to your JWT token
const kindeToken = 'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImtpZF8xMjM0In0...';
const authHeader = `Bearer kinde_${kindeToken}`;

fetch('/api/protected-endpoint', {
    headers: {
        'Authorization': authHeader
    }
});

4. Subscribe to Webhook Events

namespace App\EventSubscriber;

use Habityzer\KindeBundle\Event\KindeEvents;
use Habityzer\KindeBundle\Event\KindeSubscriptionUpdatedEvent;
use Habityzer\KindeBundle\Event\KindeUserDeletedEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

class KindeWebhookSubscriber implements EventSubscriberInterface
{
    public static function getSubscribedEvents(): array
    {
        return [
            KindeEvents::SUBSCRIPTION_UPDATED => 'onSubscriptionUpdated',
            KindeEvents::USER_DELETED => 'onUserDeleted',
        ];
    }
    
    public function onSubscriptionUpdated(KindeSubscriptionUpdatedEvent $event): void
    {
        $userId = $event->getUserId();
        $planName = $event->getPlanName();
        // Your business logic here
    }
    
    public function onUserDeleted(KindeUserDeletedEvent $event): void
    {
        $kindeId = $event->getKindeId();
        // Your cleanup logic here
    }
}

Events

The bundle dispatches the following Symfony events:

Event Constant Event Name Description
KindeEvents::USER_UPDATED kinde.user.updated User information updated in Kinde
KindeEvents::USER_DELETED kinde.user.deleted User deleted from Kinde
KindeEvents::USER_AUTHENTICATED kinde.user.authenticated User authenticated via webhook
KindeEvents::SUBSCRIPTION_CREATED kinde.subscription.created New subscription created
KindeEvents::SUBSCRIPTION_UPDATED kinde.subscription.updated Subscription plan changed
KindeEvents::SUBSCRIPTION_CANCELLED kinde.subscription.cancelled Subscription cancelled
KindeEvents::SUBSCRIPTION_REACTIVATED kinde.subscription.reactivated Subscription reactivated

📖 See Events Reference for complete event documentation with all available methods.

Debug Command

Debug JWT tokens to inspect claims and troubleshoot issues:

# Accepts tokens with or without kinde_ prefix
php bin/console kinde:debug-token YOUR_JWT_TOKEN
php bin/console kinde:debug-token kinde_YOUR_JWT_TOKEN
php bin/console kinde:debug-token "Bearer kinde_YOUR_JWT_TOKEN"

The command automatically strips Bearer and kinde_ prefixes if present.

Output includes:

  • Token header (algorithm, type)
  • All payload claims
  • Email presence check with fix suggestions
  • Token expiration status

Documentation

Document Description
Installation Guide Detailed step-by-step installation
Events Reference Complete event classes documentation
Services API Services and their public methods
Kinde Setup Configure Kinde dashboard for this bundle
Advanced Usage Advanced scenarios and customization

Architecture

┌─────────────────┐     ┌──────────────────────┐     ┌─────────────────┐
│  HTTP Request   │────▶│ KindeTokenAuthenticator │────▶│  Your User     │
│  (Bearer Token) │     └──────────────────────┘     │   Entity        │
└─────────────────┘              │                   └─────────────────┘
                                 │
                    ┌────────────┴────────────┐
                    ▼                         ▼
          ┌─────────────────┐      ┌─────────────────┐
          │ KindeTokenValidator │      │  KindeUserSync   │
          │  (JWKS validation)  │      │ (User provider)  │
          └─────────────────┘      └─────────────────┘
                    │                         │
                    ▼                         ▼
          ┌─────────────────┐      ┌─────────────────────┐
          │ KindeUserInfoService │      │ KindeUserProviderInterface │
          │ (Fallback for email) │      │   (Your implementation)    │
          └─────────────────┘      └─────────────────────┘

License

MIT

Support

For issues and questions: https://github.com/habityzer/kinde-bundle/issues

统计信息

  • 总下载量: 11
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 0
  • 点击次数: 0
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2025-10-14