gpt4 book ai didi

python - 带有 djoser 的 django 上的 webauthn 签名问题

转载 作者:行者123 更新时间:2023-12-05 05:30:36 26 4
gpt4 key购买 nike

我目前正在为一个项目实现 webauthn。重点是让用户可以在网站上的手机上使用 FaceId 或指纹扫描。

我尝试了 webauthn 的 djoser 版本,但我想为已经拥有帐户的用户提供这种可能性,所以我实现了 djoser 的 webauthn 并更新了它,使其可以与已经创建的帐户一起使用。

我可以请求 webauthn token 的注册请求,并在我使用 @simplewebauthn/browser ("@simplewebauthn/browser": "^6.3.0-alpha.1") 。那里一切正常。

我通过拉动 git 使用最新版本的 djoser,webauthn 的版本是 0.4.7 链接到 djoser。

djoser @git+https://github.com/sunscrapers/djoser.git@abdf622f95dfa2c6278c4bd6d50dfe69559d90c0
webauthn==0.4.7

但是当我把注册的结果发回后台时,报错:

身份验证被拒绝。错误:收到无效签名..

这是 SignUpView:

    permission_classes = (AllowAny,)

def post(self, request, ukey):
co = get_object_or_404(CredentialOptions, ukey=ukey)

webauthn_registration_response = WebAuthnRegistrationResponse(
rp_id=settings.DJOSER["WEBAUTHN"]["RP_ID"],
origin=settings.DJOSER["WEBAUTHN"]["ORIGIN"],
registration_response=request.data,
challenge=co.challenge,
none_attestation_permitted=True,
)
try:
webauthn_credential = webauthn_registration_response.verify()
except RegistrationRejectedException as e:
return Response(
{api_settings.NON_FIELD_ERRORS_KEY: format(e)},
status=status.HTTP_400_BAD_REQUEST,
)
user = User.objects.get(username=request.data["username"])
user_serializer = CustomUserSerializer(user)
co.challenge = ""
co.user = user
co.sign_count = webauthn_credential.sign_count
co.credential_id = webauthn_credential.credential_id.decode()
co.public_key = webauthn_credential.public_key.decode()
co.save()


return Response(user_serializer.data, status=status.HTTP_201_CREATED)

我的工作基于 https://github.com/sunscrapers/djoser/blob/abdf622f95dfa2c6278c4bd6d50dfe69559d90c0/djoser/webauthn/views.py#L53

这里还有 SignUpRequesrtView,我在其中编辑了一些小东西以使其按我想要的方式工作:

class SignupRequestView(APIView):
permission_classes = (AllowAny,)

def post(self, request):
CredentialOptions.objects.filter(username=request.data["username"]).delete()

serializer = WebauthnSignupSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
co = serializer.save()

credential_registration_dict = WebAuthnMakeCredentialOptions(
challenge=co.challenge,
rp_name=settings.DJOSER["WEBAUTHN"]["RP_NAME"],
rp_id=settings.DJOSER["WEBAUTHN"]["RP_ID"],
user_id=co.ukey,
username=co.username,
display_name=co.display_name,
icon_url="",
)

return Response(credential_registration_dict.registration_dict)

我还更新了 WebAuthnSignupSerializer 以检查是否存在具有给定用户名的帐户,如果是,则创建 CredentialOptions:

class WebauthnSignupSerializer(serializers.ModelSerializer):
class Meta:
model = CredentialOptions
fields = ("username", "display_name")

def create(self, validated_data):
validated_data.update(
{
"challenge": create_challenge(
length=settings.DJOSER["WEBAUTHN"]["CHALLENGE_LENGTH"]
),
"ukey": create_ukey(length=settings.DJOSER["WEBAUTHN"]["UKEY_LENGTH"]),
}
)
return super().create(validated_data)

def validate_username(self, username):
if User.objects.filter(username=username).exists():
return username
else:
raise serializers.ValidationError(f"User {username} does not exist.")```

最佳答案

编辑:长话短说;

@simplewebauthn/browser 将签名编码为 base64url,而 duo-labs/py_webauthn 需要十六进制编码的签名。


嗯,这不是真正的答案,而是一点“帮助”。

您可以使用这个小工具(在页面底部)检查签名是否有效:https://webauthn.passwordless.id/demos/playground.html

至少,使用它,您将知道您的数据是否正确或是否存储有误。从字节到 base64url 的转换如此之多,以至于跟踪起来并不总是那么容易。也许这是数据格式/转换问题?比如不转换为字节,或者不小心将编码双重编码为​​ base64url。

最后,存储的公钥根据算法有不同的格式。 “原始”或“ASN.1”包装,以防您对 key 本身有疑问。

祝你好运!


编辑:

在深入研究 sunscrapers/djoser 的源代码时,我注意到了一些非常奇怪的事情。虽然所有数据都编码为 base64,但签名似乎是十六进制编码,请参阅他们的 test app

这似乎是因为它使用 duo-labs/py_webauthn 作为需要 hex encoded signature 的依赖项.另一方面,@simplewebauthn/browser lib encodes it into base64url ,就像所有其他数据一样。

关于python - 带有 djoser 的 django 上的 webauthn 签名问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74615858/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com