php - 具有 OpenID Connect 和 PKCE 的 Azure B2C

标签 php azure azure-devops azure-active-directory azure-web-app-service

我正在尝试使用 Laravel 进行 Azure B2C 登录,现在已经完成一半了。

Laravel 部分是一个 API,客户端是 Angular。我计划把整个过程都放在BE上。当用户单击“使用 Microsoft 登录”以重定向到 BE 服务器端页面时,我会在 BE 上施展魔法。最后,我想重定向到某个 FE 页面并在 cookie 中设置访问 token 。

我定义了两个 web.php(服务器端)路由。第一个用于重定向到 Azure 登录,第二个用于回调。

这是代码:

public function redirect()
{
    $length = mt_rand(43, 128);
    $bytes = random_bytes($length);
    $codeVerifier = rtrim(strtr(base64_encode($bytes), '+/', '-_'), '=');

    $state = Str::random(40);

    $query = http_build_query([
        'p' => 'B2C_1A_SIGNIN',
        'client_id' => config('services.azureadb2c.client_id'),
        'redirect_uri' => config('services.azureadb2c.redirect'),
        'response_type' => 'code',
        'scope' => 'openid',
        'state' => $state,
        'prompt' => 'login',
        'code_challenge' => $this->generateCodeChallenge($codeVerifier),
        'code_challenge_method' => 'S256',
    ]);

    session(['state' => $state, 'code_verifier' => $codeVerifier]);

    return redirect('https://' . config('services.azureadb2c.domain') . '.b2clogin.com/' . config('services.azureadb2c.domain') . '.onmicrosoft.com/b2c_1a_signin/oauth2/v2.0/authorize?' . $query);
}

public function callback(Request $request)
{
    $client = new Client();
    $response = $client->post("https://" . config('services.azureadb2c.domain') . ".b2clogin.com/" . config('services.azureadb2c.domain') . ".onmicrosoft.com/b2c_1a_signin/oauth2/v2.0/token?p=B2C_1A_SIGNIN", [
        'form_params' => [
            'grant_type' => 'authorization_code',
            'client_id' => config('services.azureadb2c.client_id'),
            'client_secret' => config('services.azureadb2c.client_secret'),
            'code' => $request->get('code'),
            'redirect_uri' => config('services.azureadb2c.redirect'),
            'code_verifier' => session('code_verifier'),
            'scope' => 'openid',
        ],
    ]);
    var_dump(json_decode($response->body()));
    exit;
}

private function generateCodeChallenge($codeVerifier) {
    $hash = hash('sha256', $codeVerifier, true);
    $codeChallenge = rtrim(strtr(base64_encode($hash), '+/', '-_'), '=');
    return $codeChallenge;
}

在这里,我面临下一个问题。重定向运行良好,用户被正确重定向,并且他可以很好地输入凭据等。在回调的最后,我收到了授权代码,但是当我发出 POST 请求来获取访问 token 时,我收到了下一个错误

`400 Bad Request` response: {"error":"invalid_grant","error_description":"AADB2C90085: The service has encountered an internal error. Please reauthe (truncated...)

您知道什么会导致此错误吗?

最佳答案

我尝试通过 Postman 在我的环境中重现相同的结果,并得到以下结果:

我通过在重定向 URI 中选择 SPA 注册了一个 Azure AD B2C 应用程序,如下所示:

enter image description here

我从 blog 中运行了 Bac Hoang [MSFT] 的 c# 代码,并成功获取了 code_challengecode_verifier 的值,如下所示:

using IdentityModel;
using System.Security.Cryptography;
using System.Text;
 
namespace PKCEConsoleApp2
{
    class Program
    {
        static void Main(string[] args)
        {
            var random = new Random();
            int cvlength = random.Next(43, 128);
            const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~";
            var codeVerifier = new string (Enumerable.Repeat(chars, cvlength).Select(s => s[random.Next(s.Length)]).ToArray());
 
            string codeChallenge;
            using (var sha256 = SHA256.Create())
            {
                var a = Encoding.UTF8.GetBytes(codeVerifier);
                var challengeBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(codeVerifier));
                codeChallenge = Base64Url.Encode(challengeBytes);
            }
 
            Console.WriteLine("codeVerifier " + codeVerifier + "\n");
            Console.WriteLine("codeChallenge " + codeChallenge + "\n");
 
            Console.ReadLine();
        }
    }
}

回应:

enter image description here

现在,我在浏览器中运行了以下授权请求,并成功获取了代码,如下所示:

https://sritenantb2c.b2clogin.com/sritenantb2c.onmicrosoft.com/B2C_1_Signin/oauth2/v2.0/authorize?
client_id=742978eb-ccb4-4b82-8140-3526417d4d09
&response_type=code
&redirect_uri=https://jwt.ms
&response_mode=query
&scope=openid
&code_challenge=l-kik2UPt2cInWJK6liasiRBhdpNm3qeOqUma_4Ih7E
&code_challenge_method=S256

回应:

enter image description here

当我尝试使用以下参数通过 Postman 生成 token 时,我只得到 id_tokenrefresh_token 而没有访问 token ,如下所示:

POST https://sritenantb2c.b2clogin.com/sritenantb2c.onmicrosoft.com/B2C_1_Signin/oauth2/v2.0/token

client_id:742978eb-ccb4-4b82-8140-xxxxxxxxxx
grant_type:authorization_code
scope:openid
code: <paste code from above step>
redirect_uri: https://jwt.ms
code_verifier:hMl0zyCvyUKJxS1gjOPqFNf1LPQ~tcvekFJeWsfzFGSFMi5~QkpCAq1QHMDT3N

回应:

enter image description here

要获取访问 token ,请通过公开 API 添加新范围,如下所示:

enter image description here

现在,在您的应用程序中添加此范围,该范围将受到委派权限的约束,如下所示:

enter image description here

确保向上述范围授予管理员同意,如下所示:

enter image description here

现在,通过在浏览器中运行以下授权请求再次生成代码

https://sritenantb2c.b2clogin.com/sritenantb2c.onmicrosoft.com/B2C_1_Signin/oauth2/v2.0/authorize?
client_id=742978eb-ccb4-4b82-8140-xxxxxxxxxx
&response_type=code
&redirect_uri=https://jwt.ms
&response_mode=query
&scope=https://sritenantb2c.onmicrosoft.com/742978eb-ccb4-4b82-8140-xxxxxxxxxx/.default
&code_challenge=l-kik2UPt2cInWJK6liasiRBhdpNm3qeOqUma_4Ih7E
&code_challenge_method=S256

回应:

enter image description here

我通过 Postman 使用以下参数成功生成了访问 token ,如下所示:

POST https://sritenantb2c.b2clogin.com/sritenantb2c.onmicrosoft.com/B2C_1_Signin/oauth2/v2.0/token

client_id:742978eb-ccb4-4b82-8140-xxxxxxxxxx
grant_type:authorization_code
scope: https://sritenantb2c.onmicrosoft.com/742978eb-ccb4-4b82-8140-xxxxxxxxxxx/Admin.Read openid
code: <paste code from above step>
redirect_uri: https://jwt.ms
code_verifier:hMl0zyCvyUKJxS1gjOPqFNf1LPQ~tcvekFJeWsfzFGSFMi5~QkpCAq1QHMDT3N

回应:

enter image description here

当我在 jwt.ms 中解码上述访问 token 时,我得到了 scp 声明,如下所示:

enter image description here

关于php - 具有 OpenID Connect 和 PKCE 的 Azure B2C,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/75460287/

相关文章:

php - cloneNode 与 namespace 不一致 - 跨环境?

php - 根据搜索值按值排序

android - 从 Play 商店下载应用程序时,Azure MSAL 集成不起作用

azure-devops - 将图像添加到 Azure Devops 仪表板

azure-devops - Azure DevOps 将 Nuget 发布到托管源

php - 如何使用 php 从 Web 浏览器启动程序

php - Crontab/每月第一个星期日运行cronjob

azure - 在 OpenAI Azure 上找不到 GPT3.5-Turbo-16k

azure - 同时运行多个复制操作时如何限制连接数?

npm 发布天蓝色工件