You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular+PHP项目Azure SSO添加证书认证的前后端实现步骤咨询

Azure SSO证书认证:Angular+PHP 具体实现步骤

一、Azure AD 前置配置(必须完成)

  • 在Azure AD应用注册中上传证书公钥(替代客户端密钥),确保应用的API权限保留原有的https://graph.microsoft.com/.default配置。

二、前端Angular 调整(几乎无改动)

证书认证属于后端与Azure的交互环节,前端授权码流程无需核心修改:

  • 保持原有配置不变,继续通过授权码流程获取ID Token/Access Token。
  • 确保传递给PHP后端的是完整的ID Token(而非仅Access Token),后端需用它做签名验证。

三、后端PHP 核心实现(证书认证核心)

3.1 准备证书文件

将Azure AD下载的证书公钥文件(.cer/.pem格式)放在PHP项目非Web可访问的安全目录下,设置严格文件权限(如chmod 600)。

3.2 验证前端传入的ID Token

使用firebase/php-jwt库结合证书验证Token签名与有效性:

  1. 安装依赖:
composer require firebase/php-jwt
  1. 验证逻辑代码:
use Firebase\JWT\JWT;
use Firebase\JWT\Key;

// 从前端请求获取ID Token
$idToken = $_POST['id_token'];

// 读取Azure证书公钥
$publicKey = file_get_contents('/path/to/secure-directory/azure-cert.pem');

try {
    // 验证Token并校验关键字段
    $decoded = JWT::decode(
        $idToken,
        new Key($publicKey, 'RS256'),
        [
            'iss' => 'https://login.microsoftonline.com/{tenant-id}/v2.0',
            'aud' => '{your-client-id}', // 应用注册的Client ID
            'exp' => true // 校验过期时间
        ]
    );

    // 提取用户信息完成登录流程
    $userInfo = [
        'userId' => $decoded->oid,
        'email' => $decoded->email ?? $decoded->upn,
        'name' => $decoded->name
    ];

    echo json_encode(['success' => true, 'user' => $userInfo]);
} catch (Exception $e) {
    echo json_encode(['success' => false, 'error' => $e->getMessage()]);
}

注意:iss和aud必须与Azure应用注册配置完全匹配,否则验证失败。

3.3 可选:后端用证书调用Graph API

若后端需独立调用Graph API,可通过证书认证的客户端凭证流获取令牌:

$tenantId = '{your-tenant-id}';
$clientId = '{your-client-id}';
$certPath = '/path/to/secure-directory/private-cert.pem';
$certPassword = '{your-cert-password}'; // 证书有密码时填写

// 读取证书私钥
$privateKey = openssl_pkey_get_private(
    file_get_contents($certPath),
    $certPassword
);

// 生成JWT断言
$now = time();
$assertion = [
    'aud' => "https://login.microsoftonline.com/$tenantId/oauth2/v2.0/token",
    'iss' => $clientId,
    'sub' => $clientId,
    'exp' => $now + 3600,
    'iat' => $now,
    'jti' => uniqid()
];

// 签名断言
$jwt = JWT::encode($assertion, $privateKey, 'RS256');

// 请求Azure获取访问令牌
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://login.microsoftonline.com/$tenantId/oauth2/v2.0/token");
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query([
    'grant_type' => 'client_credentials',
    'client_id' => $clientId,
    'client_assertion_type' => 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer',
    'client_assertion' => $jwt,
    'scope' => 'https://graph.microsoft.com/.default'
]));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);

$tokenData = json_decode($response, true);
$accessToken = $tokenData['access_token'] ?? '';

// 使用令牌调用Graph API示例
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://graph.microsoft.com/v1.0/users/{target-user-id}');
curl_setopt($ch, CURLOPT_HTTPHEADER, ["Authorization: Bearer $accessToken"]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$userData = curl_exec($ch);
curl_close($ch);

四、关键注意事项

  • 证书文件必须严格保密:私钥绝不能暴露到Web可访问目录,定期轮换证书。
  • 完整校验Token字段:除签名外,必须校验exp(过期时间)、nbf(生效时间)等字段,避免非法Token。

内容的提问来源于stack exchange,提问作者Lovitha

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 16:50:22