Cognito php 密码 SRP 验证程序质询返回不正确的用户名和密码 [英] Cognito php password SRP verifier challenge returns incorrect username and password

查看:45
本文介绍了Cognito php 密码 SRP 验证程序质询返回不正确的用户名和密码的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 PHP 网页,我在其中配置了 aws sdk 并实例化了 Cognito 客户端客户端也配置了客户端密钥,并且启用了身份验证流 USER_PASSWORD_AUTH、USER_SRP_AUTH.具有基本身份验证流类型 USER_PASSWORD_AUTH 的initialAuth 对我来说很好用.以下是我尝试的示例用法 -

$result = $cognito->initiateAuth(['AuthFlow' =>'USER_PASSWORD_AUTH','ClientId' =>'','UserPoolId' =>'','AuthParameters' =>['用户名' =>'<用户名>','密码' =><密码>",'SECRET_HASH' =>base64_encode(hash_hmac('sha256', '' .'', '', true))]]);

有了这个,我们得到了一个带有访问和 id 令牌的成功响应,但是当我们像这样使用 USER_SRP_AUTH 方法尝试使用相同的参数时 -

$srp = new srp();$a = $srp->getRandomSeed();$A = $srp->generateA($a);$result = $cognito->initiateAuth(['AuthFlow' =>'USER_SRP_AUTH','ClientId' =>'','UserPoolId' =>'','AuthParameters' =>['用户名' =>'<用户名>','SRP_A' =>$A,'SECRET_HASH' =>base64_encode(hash_hmac('sha256', '' .'', '', true))]]);$date = date('D M d H:i:s')."UTC 2021";$challengeParameters = $result->get(ChallengeParameters");$s = $srp->getRandomSeed();$x = $srp->generateX($s, $challengeParameters['USER_ID_FOR_SRP'], '');$S = $srp->generateS_Client($A, $challengeParameters['SRP_B'], $a, $x);$K = $srp->generateK($S);$response = $cognito->respondToAuthChallenge([挑战名称"=>密码验证器",客户 ID"=>'',挑战响应"=>[时间戳"=>$日期,用户名"=>$challengeParameters['USER_ID_FOR_SRP'],PASSWORD_CLAIM_SECRET_BLOCK"=>$challengeParameters['SECRET_BLOCK'],PASSWORD_CLAIM_SIGNATURE"=>hash_hmac('sha256', $K, $challengeParameters['SALT']),'SECRET_HASH' =>base64_encode(hash_hmac('sha256', $challengeParameters['USER_ID_FOR_SRP'] .'<client_id>', '<client_secret>', true))]]);

但是用这种方法我总是得到这个错误 -

NotAuthorizedException 执行RespondToAuthChallenge"时出错;在https://cognito-idp.us-east-1.amazonaws.com"上;AWS HTTP 错误:客户端错误:POST https://cognito-idp.us-east-1.amazonaws.com"导致400 Bad Request"响应:{__type":NotAuthorizedException","消息":不正确的用户名或密码."} NotAuthorizedException(客户端):不正确的用户名或密码.- {__type":NotAuthorizedException",message":不正确的用户名或密码."}

现在我也尝试用 <username> 替换 challengeParams['USER_ID_FOR_SRP'] 但我仍然遇到同样的错误.

那么,这里的任何人都可以帮我弄清楚问题是什么,并可能也尝试帮助解决它吗?

解决方案

Cognito 中 SRP 的问题在于它不是根据 RFC5054.

如果您使用任何标准库来处理用于 Cognito 的 SRP,则它不会起作用.另外,PHP 的 SDK 不支持 SRP.

以下是根据 RFC5054 的 SRP 的工作原理(非常简化):

客户:

  • 计算 SRP A
  • 将用户名和 SRP_A 发送到服务器

服务器:

  • 计算 SRP_B
  • 向客户端发送 SRP_B 和盐

客户:

  • 计算会话密钥
  • 向服务器发送会话密钥证明

服务器:

  • 计算会话密钥
  • 比较服务器会话密钥和客户端会话密钥的证明
  • 将服务器的会话密钥证明发送给客户端

客户:

  • 验证服务器的会话密钥证明

当双方都能够确认他们拥有的会话密钥有效时,就假定用户通过了身份验证.

这是在 Cognito 中的样子:

客户:

  • 计算 SRP_A
  • 将用户名和 SRP_A 发送到服务器

服务器:

  • 计算 SRP_B
  • 向客户端发送 SRP_B、salt 和 SECRET_BLOCK

此时我们已经可以看到这与 RFC 不同.这个秘密块是特定于 Cognito 而不是 RFC 的.因此,接下来的任何计算都需要以不同的方式进行.

实现过程相当冗长,所以我将粘贴一个指向 Gist 的链接.这是 Lynh 的一个端口,来自 Python 又基于 适用于 Java 的 AWS SDK 示例:

https://gist.github.com/jenky/a4465f73adf90206b3e6a98cbed43c

I have a PHP webpage in which I have configured the aws sdk and instantiated the cognito client The client is configured with a client secret as well and the auth flows USER_PASSWORD_AUTH, USER_SRP_AUTH are enabled. The initiateAuth with the basic auth flow type USER_PASSWORD_AUTH works fine for me. Below is the sample usage I tried -

$result = $cognito->initiateAuth([
'AuthFlow' => 'USER_PASSWORD_AUTH',
'ClientId' => '<client_id>',
'UserPoolId' => '<pool_id>',
'AuthParameters' => [
'USERNAME' => '<username>',
'PASSWORD' => "<password>",
'SECRET_HASH' => base64_encode(hash_hmac('sha256', '<username>' . '<client_id>', '<client_secret>', true))
]
]);

With this we are getting a successful response with access and id token, but when we try with the same parameters with the USER_SRP_AUTH method like this -

$srp = new srp();
$a = $srp->getRandomSeed();
$A = $srp->generateA($a);
$result = $cognito->initiateAuth([
'AuthFlow' => 'USER_SRP_AUTH',
'ClientId' => '<client_id>',
'UserPoolId' => '<pool_id>',
'AuthParameters' => [
'USERNAME' => '<username>',
'SRP_A' => $A,
'SECRET_HASH' => base64_encode(hash_hmac('sha256', '<username>' . '<client_id>', '<client_secret>', true))
]
]);
$date = date('D M d H:i:s')." UTC 2021";
$challengeParameters = $result->get("ChallengeParameters");
$s = $srp->getRandomSeed();
$x = $srp->generateX($s, $challengeParameters['USER_ID_FOR_SRP'], '<password>');
$S = $srp->generateS_Client($A, $challengeParameters['SRP_B'], $a, $x);
$K = $srp->generateK($S);
$response = $cognito->respondToAuthChallenge([
"ChallengeName" => "PASSWORD_VERIFIER",
"ClientId" => '<client_id>',
"ChallengeResponses" => [
"TIMESTAMP" => $date,
"USERNAME" => $challengeParameters['USER_ID_FOR_SRP'],
"PASSWORD_CLAIM_SECRET_BLOCK" => $challengeParameters['SECRET_BLOCK'],
"PASSWORD_CLAIM_SIGNATURE" => hash_hmac('sha256', $K, $challengeParameters['SALT']),
'SECRET_HASH' => base64_encode(hash_hmac('sha256', $challengeParameters['USER_ID_FOR_SRP'] . '<client_id>', '<client_secret>', true))
]
]);

But with this approach I always get this error -

NotAuthorizedException Error executing "RespondToAuthChallenge" on "https://cognito-idp.us-east-1.amazonaws.com"; AWS HTTP error: Client error: `POST https://cognito-idp.us-east-1.amazonaws.com` resulted in a `400 Bad Request` response: {"__type":"NotAuthorizedException","message":"Incorrect username or password."} NotAuthorizedException (client): Incorrect username or password. - {"__type":"NotAuthorizedException","message":"Incorrect username or password."}

Now I have also tried replacing challengeParams['USER_ID_FOR_SRP'] with <username> but still I get the same error.

So, can anyone here help me figure out what the issue is and probably try to help solve it as well ?

解决方案

The problem with SRP in Cognito is that it's not the SRP according to RFC5054.

If you are using any standard library to deal with SRP for Cognito purposes, it's not going to work. Also, the PHP's SDK does not have support fro SRP.

Here is how SRP according to RFC5054 works (very simplified):

Client:

  • calculate SRP A
  • send username and SRP_A to the Server

Server:

  • calculate SRP_B
  • send SRP_B and salt to the Client

Client:

  • calculate session key
  • send proof of session key to the Server

Server:

  • calculate session key
  • compare proof of Server's session key with Client's session key
  • send Server's proof of session key to the Client

Client:

  • Validate Server's proof of session key

When both parties are able to confirm that the session key they have is valid, the user is assumed to be authenticated.

And here is how it looks like in Cognito:

Client:

  • calculate SRP_A
  • send username and SRP_A to the server

Server:

  • calculate SRP_B
  • send SRP_B, salt and SECRET_BLOCK to the Client

At this point we can already see this is different than the RFC. This secret block is something specific to Cognito and not to RFC. And therefore any calculations that will follow need to be done differently.

The implementation is rather lengthy so I'm going to paste a link to Gist. It's a port by Lynh from Python which in turn is based on AWS SDK sample for Java:

https://gist.github.com/jenky/a4465f73adf90206b3e98c3d36a3be4f

这篇关于Cognito php 密码 SRP 验证程序质询返回不正确的用户名和密码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆