@@ -2,6 +2,7 @@ use std::convert::TryInto;
22use std:: error:: Error ;
33use std:: time:: Duration ;
44
5+ use libwebauthn:: proto:: CtapError ;
56use rand:: { thread_rng, Rng } ;
67use tracing_subscriber:: { self , EnvFilter } ;
78
@@ -10,8 +11,8 @@ use libwebauthn::ops::webauthn::{
1011} ;
1112use libwebauthn:: pin:: { PinProvider , StdinPromptPinProvider } ;
1213use libwebauthn:: proto:: ctap2:: {
13- Ctap2CredentialType , Ctap2PublicKeyCredentialDescriptor , Ctap2PublicKeyCredentialRpEntity ,
14- Ctap2PublicKeyCredentialUserEntity ,
14+ Ctap2CredentialType , Ctap2PinUvAuthProtocol , Ctap2PublicKeyCredentialDescriptor ,
15+ Ctap2PublicKeyCredentialRpEntity , Ctap2PublicKeyCredentialUserEntity ,
1516} ;
1617use libwebauthn:: transport:: hid:: list_devices;
1718use libwebauthn:: transport:: Device ;
@@ -36,7 +37,7 @@ pub async fn main() -> Result<(), Box<dyn Error>> {
3637 let user_id: [ u8 ; 32 ] = thread_rng ( ) . gen ( ) ;
3738 let challenge: [ u8 ; 32 ] = thread_rng ( ) . gen ( ) ;
3839
39- let pin_provider: Box < dyn PinProvider > = Box :: new ( StdinPromptPinProvider :: new ( ) ) ;
40+ let mut pin_provider: Box < dyn PinProvider > = Box :: new ( StdinPromptPinProvider :: new ( ) ) ;
4041
4142 for mut device in devices {
4243 println ! ( "Selected HID authenticator: {}" , & device) ;
@@ -60,7 +61,7 @@ pub async fn main() -> Result<(), Box<dyn Error>> {
6061
6162 let response = loop {
6263 match channel
63- . webauthn_make_credential ( & make_credentials_request, & pin_provider)
64+ . webauthn_make_credential ( & make_credentials_request, & mut pin_provider)
6465 . await
6566 {
6667 Ok ( response) => break Ok ( response) ,
@@ -77,6 +78,14 @@ pub async fn main() -> Result<(), Box<dyn Error>> {
7778 . unwrap ( ) ;
7879 println ! ( "WebAuthn MakeCredential response: {:?}" , response) ;
7980
81+ // PUAP-version 2 has random IV, so the auth_token isn't reusable
82+ if matches ! (
83+ pin_provider. get_uv_auth_token( ) ,
84+ Some ( ( _, Ctap2PinUvAuthProtocol :: Two ) )
85+ ) {
86+ pin_provider. set_uv_auth_token ( None ) ;
87+ }
88+
8089 let credential: Ctap2PublicKeyCredentialDescriptor = ( & response) . try_into ( ) . unwrap ( ) ;
8190 let get_assertion = GetAssertionRequest {
8291 relying_party_id : "example.org" . to_owned ( ) ,
@@ -89,10 +98,13 @@ pub async fn main() -> Result<(), Box<dyn Error>> {
8998
9099 let response = loop {
91100 match channel
92- . webauthn_get_assertion ( & get_assertion, & pin_provider)
101+ . webauthn_get_assertion ( & get_assertion, & mut pin_provider)
93102 . await
94103 {
95104 Ok ( response) => break Ok ( response) ,
105+ Err ( WebAuthnError :: Ctap ( CtapError :: PINAuthInvalid ) ) => {
106+ pin_provider. set_uv_auth_token ( None ) ;
107+ }
96108 Err ( WebAuthnError :: Ctap ( ctap_error) ) => {
97109 if ctap_error. is_retryable_user_error ( ) {
98110 println ! ( "Oops, try again! Error: {}" , ctap_error) ;
0 commit comments