visin/laravel-entra-auth 问题修复 & 功能扩展

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

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

visin/laravel-entra-auth

Composer 安装命令:

composer require visin/laravel-entra-auth

包简介

Shared Microsoft Entra ID client-credentials JWT validation and token acquisition for Laravel services.

README 文档

README

Latest Version on Packagist Tests Total Downloads License

Shared Microsoft Entra ID client-credentials auth for Laravel services.

One central implementation of both halves of service-to-service auth, so every backend validates and acquires tokens the exact same way:

  • Resource server: validate incoming Entra client-credentials JWTs (signature via tenant JWKS, expiry, audience, tenant, issuer, app roles), with the OpenID discovery document and JWKS cached in the app cache so validation does not call login.microsoftonline.com on every request.
  • Client: acquire app-only access tokens with the OAuth2 client credentials flow, cached until shortly before expiry.

Battle-tested in production service-to-service auth, so validation behavior mirrors what Entra actually emits for client-credentials tokens rather than only what the docs describe.

Why a shared package

Every service hand-rolling JWT validation is a drift risk: small differences (audience forms, tenant pinning, caching, role extraction) creep in per service and are invisible until one of them becomes a security hole. This package centralizes the logic behind one tested implementation:

  • Accepts both audience forms Entra emits for the same app registration: the app ID URI (api://<guid>) and the bare app/client guid.
  • Pins the token to the configured tenant (tid) and validates the issuer against the tenant's published OpenID configuration.
  • Extracts the application client id from azp/appid/client_id.
  • Extracts app roles from the roles claim, optionally filtered against a configured whitelist.

Installation

The package is available on Packagist:

composer require visin/laravel-entra-auth

The service provider is auto-discovered. Publish the config if you need to override defaults:

php artisan vendor:publish --tag=entra-auth-config

Configuration

# Resource server (incoming token validation)
ENTRA_AUTH_TENANT_ID=<entra-tenant-guid>
ENTRA_AUTH_AUDIENCE=api://<this-api-app-registration-guid>

# Client (outgoing token acquisition), only needed when calling other APIs
ENTRA_AUTH_CLIENT_ID=<this-service-app-registration-guid>
ENTRA_AUTH_CLIENT_SECRET=<client-secret>
ENTRA_AUTH_SCOPE=api://<target-api-app-registration-guid>/.default

The protected API's app registration must issue v2 access tokens ("api": { "requestedAccessTokenVersion": 2 } in the app manifest).

Protecting routes (resource server)

Two middleware aliases are registered: entra.auth validates the bearer token, entra.role:<role> requires an app role from the token's roles claim.

Route::middleware(['entra.auth', 'entra.role:invoices.write'])
    ->post('/v1/invoices', [InvoiceController::class, 'store']);

The validated token is available on the request:

use Visin\EntraAuth\AccessToken;
use Visin\EntraAuth\Http\Middleware\AuthenticateEntraToken;

/** @var AccessToken $token */
$token = $request->attributes->get(AuthenticateEntraToken::REQUEST_ATTRIBUTE);

$token->tenantId;   // issuing tenant guid
$token->clientId;   // calling app registration guid
$token->roles;      // app roles from the token
$token->claims;     // full decoded claims (stdClass)

Services that map callers to database records (client registries, audit logging, per-client authorization) can skip the middleware and consume the validator directly:

use Visin\EntraAuth\Contracts\AccessTokenValidator;
use Visin\EntraAuth\Exceptions\InvalidAccessToken;

$accessToken = app(AccessTokenValidator::class)->validate($bearerToken);
// then e.g. look up the caller by ($accessToken->tenantId, $accessToken->clientId)

To restrict which roles are ever passed through, set a whitelist in config/entra-auth.php:

'allowed_roles' => ['invoices.read', 'invoices.write', 'invoices.delete'],

Calling another Entra-protected API (client)

use Illuminate\Support\Facades\Http;
use Visin\EntraAuth\Client\ClientCredentialsTokenProvider;

$token = app(ClientCredentialsTokenProvider::class)->token();

$response = Http::withToken($token)->post('https://api.example.com/v1/invoices', [
    'number' => 'INV-2026-001',
    'amount' => 1250,
]);

Tokens are cached in the app cache and refreshed 60 seconds before expiry.

Testing your app against this package

Bind a fake validator in your tests instead of faking HTTP:

use Visin\EntraAuth\AccessToken;
use Visin\EntraAuth\Contracts\AccessTokenValidator;

$this->app->singleton(AccessTokenValidator::class, fn () => new class implements AccessTokenValidator {
    public function validate(string $token): AccessToken
    {
        return new AccessToken('tenant', 'client-a', ['invoices.read'], new \stdClass);
    }
});

Running the package tests

composer install
vendor/bin/phpunit

Without host PHP, via Docker:

docker run --rm -v "$PWD":/app -w /app composer:2 sh -c 'composer install && vendor/bin/phpunit'

Requirements

  • PHP 8.3+
  • Laravel 12 or 13
  • firebase/php-jwt 6.10+ or 7.x

License

MIT

统计信息

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

GitHub 信息

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

其他信息

  • 授权协议: MIT
  • 更新时间: 2026-07-14

承接程序开发

PHP开发

VUE

Vue开发

前端开发

小程序开发

公众号开发

系统定制

数据库设计

云部署

网站建设

安全加固