支持OpenID连接和PKCE的Azure B2C

k5hmc34c  于 2023-02-16  发布在  其他
关注(0)|答案(1)|浏览(141)

我正在尝试使用Laravel进行Azure B2C登录,我现在已经成功了一半。
Laravel部分是一个API,客户端是Angular的,我计划在BE上完成整个过程,当用户点击"Sign in with Microsoft"被重定向到BE服务器端页面时,我在BE上做了魔术,最后我想重定向到某个FE页面,并在cookie中设置访问令牌。
我定义了两个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;
}

这里,我面临着下一个问题。Redirect运行良好,用户被正确地重定向,他可以很好地输入凭据和所有内容。在回调结束时,我收到了授权码,但当我发出POST请求以获取访问令牌时,我收到了下一个错误

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

你知道是什么导致了这个错误吗?

zkure5ic

zkure5ic1#

我尝试通过Postman在我的环境中重现相同的问题,结果如下:

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

我从这个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();
        }
    }
}
    • 答复:**

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

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
    • 答复:**

当我尝试使用以下参数通过Postman生成令牌时,我只得到id_tokenrefresh_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
    • 答复:**

要获取访问令牌,请通过公开API添加新作用域,如下所示:

现在,将此scope添加到您的应用程序中,该应用程序将具有Delegated权限,如下所示:

确保授予管理员许可以上范围,如下所示:

现在,通过在浏览器中运行以下授权请求再次生成**code**,如下所示

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
    • 答复:**

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

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
    • 答复:**

当我在jwt.ms中解码上面的访问令牌时,我得到了如下所示的**scp**声明:

相关问题