我正在尝试针对我们公司用于 SSO 的 MS 身份服务器检索令牌。我尝试了几种方法并继续得到 invalid_grant 错误响应。
这是我的脚本(敏感数据被隐藏):
<?php
//start the session to later store my verifier
session_start();
$client_id = 'my-client-id';
$client_secret = ''; //not using a secret because we are using PKCE
$access_token_url = "https://my-server-address/connect/token";
$redirect_uri = 'http://localhost/test.php';
$scope = 'openid and other scope items';
if (!isset($_SESSION['verifier']) && !isset($_GET['code'])) {
$code_verifier = substr(str_shuffle(str_repeat($x = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', ceil(50 / strlen($x)))), 1, 50);
$_SESSION['verifier'] = $code_verifier;
$hash = hash('sha256', $code_verifier);
$code_challenge = base64_encode(pack('H*', $hash));
$dialog_url = "https://my-server-address/Account/Login?ReturnUrl=" . urlencode('/id-server-2fa/connect/authorize/callback?client_id=' . $client_id . '&redirect_uri=' . $redirect_uri . '&code_challenge=' . $code_challenge . '&code_challenge_method=S256&response_type=code&scope=openid other scope items&response_mode=query&acr_values=' . urlencode('tenant:companyidused'));
}
if (isset($_GET['code'])) {
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $access_token_url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($curl, CURLOPT_ENCODING, '');
curl_setopt($curl, CURLOPT_MAXREDIRS, 10);
curl_setopt($curl, CURLOPT_TIMEOUT, 30);
curl_setopt($curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($curl, CURLOPT_POSTFIELDS, array(
'code' => $_GET['code'],
'code_verifier' => $_SESSION['verifier'],
'client_id' => $client_id,
'client_secret' => '',
'grant_type' => 'authorization_code',
'redirect_uri' => $redirect_uri
));
$data = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
die;
} else {
echo "Data" . $data . "<br/>";
}
$auth_string = json_decode($data, true); // token will be with in this json
$apiToken = $auth_string['access_token'];
$_SESSION['token'] = $apiToken;
echo $auth_string['access_token'];
}
if (!isset($_SESSION['token'])) {
echo "VERIFIER: " . $_SESSION['verifier'] . "<br/>";
echo '<a href="' . $dialog_url . '">Click here to login</a>';
}
我也尝试过,根据这篇文章(https://auth0.com/docs/get-started/authentication-and-authorization-flow/call-your-api-using-the-authorization-code-flow-with-pkce#-response),对我的 redirect_url value 进行 urlcode 并使用 curl HTTPHEADER 发送 "content-type: application/x-www-form-urlencoded"
。
有没有人用这种方法成功过,如果是这样,你能看出我做错了什么吗?
谢谢!
回答1
好的,我发现了我自己的问题并让它工作。
$code_challenge = base64_encode(pack('H*', $hash)); //base64_encode
实际上应该是:
$code_challenge = base64url_encode(pack('H*', $hash)); //base64url_encode
然后,我必须添加这个函数来正确编码字符串:
function base64url_encode($plainText)
{
$base64 = base64_encode($plainText);
$base64 = trim($base64, "=");
$base64url = strtr($base64, '+/', '-_');
return ($base64url);
}