@@ -5,7 +5,7 @@ use std::time::Duration;
55
66use libwebauthn:: pin:: PinRequestReason ;
77use libwebauthn:: transport:: cable:: known_devices:: {
8- CableKnownDeviceInfoStore , EphemeralDeviceInfoStore ,
8+ self , CableKnownDevice , CableKnownDeviceId , CableKnownDeviceInfoStore , EphemeralDeviceInfoStore ,
99} ;
1010use libwebauthn:: transport:: cable:: qr_code_device:: { CableQrCodeDevice , QrCodeOperationHint } ;
1111use libwebauthn:: UxUpdate ;
@@ -14,6 +14,7 @@ use qrcode::QrCode;
1414use rand:: { thread_rng, Rng } ;
1515use text_io:: read;
1616use tokio:: sync:: mpsc:: Receiver ;
17+ use tokio:: time:: sleep;
1718use tracing_subscriber:: { self , EnvFilter } ;
1819
1920use libwebauthn:: ops:: webauthn:: {
@@ -79,68 +80,71 @@ async fn handle_updates(mut state_recv: Receiver<UxUpdate>) {
7980pub async fn main ( ) -> Result < ( ) , Box < dyn Error > > {
8081 setup_logging ( ) ;
8182
82- let device_info_store: Arc < dyn CableKnownDeviceInfoStore > =
83- Arc :: new ( EphemeralDeviceInfoStore :: default ( ) ) ;
84-
85- // Create QR code
86- let mut device: CableQrCodeDevice = CableQrCodeDevice :: new_persistent (
87- QrCodeOperationHint :: MakeCredential ,
88- device_info_store. clone ( ) ,
89- ) ;
90-
91- println ! ( "Created QR code, awaiting for advertisement." ) ;
92- let qr_code = QrCode :: new ( device. qr_code . to_string ( ) ) . unwrap ( ) ;
93- let image = qr_code
94- . render :: < unicode:: Dense1x2 > ( )
95- . dark_color ( unicode:: Dense1x2 :: Light )
96- . light_color ( unicode:: Dense1x2 :: Dark )
97- . build ( ) ;
98- println ! ( "{}" , image) ;
99-
100- // Connect to a known device
101- let ( mut channel, state_recv) = device. channel ( ) . await . unwrap ( ) ;
102- println ! ( "Tunnel established {:?}" , channel) ;
103-
104- tokio:: spawn ( handle_updates ( state_recv) ) ;
105-
83+ let device_info_store = Arc :: new ( EphemeralDeviceInfoStore :: default ( ) ) ;
10684 let user_id: [ u8 ; 32 ] = thread_rng ( ) . gen ( ) ;
10785 let challenge: [ u8 ; 32 ] = thread_rng ( ) . gen ( ) ;
10886
109- // Make Credentials ceremony
110- let make_credentials_request = MakeCredentialRequest {
111- origin : "example.org" . to_owned ( ) ,
112- hash : Vec :: from ( challenge) ,
113- relying_party : Ctap2PublicKeyCredentialRpEntity :: new ( "example.org" , "example.org" ) ,
114- user : Ctap2PublicKeyCredentialUserEntity :: new ( & user_id, "mario.rossi" , "Mario Rossi" ) ,
115- require_resident_key : false ,
116- user_verification : UserVerificationRequirement :: Preferred ,
117- algorithms : vec ! [ Ctap2CredentialType :: default ( ) ] ,
118- exclude : None ,
119- extensions : None ,
120- timeout : TIMEOUT ,
121- } ;
87+ let credential: Ctap2PublicKeyCredentialDescriptor = {
88+ // Create QR code
89+ let mut device: CableQrCodeDevice = CableQrCodeDevice :: new_persistent (
90+ QrCodeOperationHint :: MakeCredential ,
91+ device_info_store. clone ( ) ,
92+ ) ;
93+
94+ println ! ( "Created QR code, awaiting for advertisement." ) ;
95+ let qr_code = QrCode :: new ( device. qr_code . to_string ( ) ) . unwrap ( ) ;
96+ let image = qr_code
97+ . render :: < unicode:: Dense1x2 > ( )
98+ . dark_color ( unicode:: Dense1x2 :: Light )
99+ . light_color ( unicode:: Dense1x2 :: Dark )
100+ . build ( ) ;
101+ println ! ( "{}" , image) ;
102+
103+ // Connect to a known device
104+ let ( mut channel, state_recv) = device. channel ( ) . await . unwrap ( ) ;
105+ println ! ( "Tunnel established {:?}" , channel) ;
106+
107+ tokio:: spawn ( handle_updates ( state_recv) ) ;
108+
109+ // Make Credentials ceremony
110+ let make_credentials_request = MakeCredentialRequest {
111+ origin : "example.org" . to_owned ( ) ,
112+ hash : Vec :: from ( challenge) ,
113+ relying_party : Ctap2PublicKeyCredentialRpEntity :: new ( "example.org" , "example.org" ) ,
114+ user : Ctap2PublicKeyCredentialUserEntity :: new ( & user_id, "mario.rossi" , "Mario Rossi" ) ,
115+ require_resident_key : false ,
116+ user_verification : UserVerificationRequirement :: Preferred ,
117+ algorithms : vec ! [ Ctap2CredentialType :: default ( ) ] ,
118+ exclude : None ,
119+ extensions : None ,
120+ timeout : TIMEOUT ,
121+ } ;
122122
123- let response = loop {
124- match channel
125- . webauthn_make_credential ( & make_credentials_request)
126- . await
127- {
128- Ok ( response) => break Ok ( response) ,
129- Err ( WebAuthnError :: Ctap ( ctap_error) ) => {
130- if ctap_error. is_retryable_user_error ( ) {
131- println ! ( "Oops, try again! Error: {}" , ctap_error) ;
132- continue ;
123+ let response = loop {
124+ match channel
125+ . webauthn_make_credential ( & make_credentials_request)
126+ . await
127+ {
128+ Ok ( response) => break Ok ( response) ,
129+ Err ( WebAuthnError :: Ctap ( ctap_error) ) => {
130+ if ctap_error. is_retryable_user_error ( ) {
131+ println ! ( "Oops, try again! Error: {}" , ctap_error) ;
132+ continue ;
133+ }
134+ break Err ( WebAuthnError :: Ctap ( ctap_error) ) ;
133135 }
134- break Err ( WebAuthnError :: Ctap ( ctap_error) ) ;
135- }
136- Err ( err) => break Err ( err) ,
137- } ;
138- }
139- . unwrap ( ) ;
140- println ! ( "WebAuthn MakeCredential response: {:?}" , response) ;
136+ Err ( err) => break Err ( err) ,
137+ } ;
138+ }
139+ . unwrap ( ) ;
140+ println ! ( "WebAuthn MakeCredential response: {:?}" , response) ;
141+
142+ ( & response. authenticator_data ) . try_into ( ) . unwrap ( )
143+ } ;
144+
145+ println ! ( "Waiting for 10 seconds before contacting the device..." ) ;
146+ sleep ( Duration :: from_secs ( 30 ) ) . await ;
141147
142- let credential: Ctap2PublicKeyCredentialDescriptor =
143- ( & response. authenticator_data ) . try_into ( ) . unwrap ( ) ;
144148 let get_assertion = GetAssertionRequest {
145149 relying_party_id : "example.org" . to_owned ( ) ,
146150 hash : Vec :: from ( challenge) ,
@@ -150,24 +154,17 @@ pub async fn main() -> Result<(), Box<dyn Error>> {
150154 timeout : TIMEOUT ,
151155 } ;
152156
153- // Create QR code
154- let mut device: CableQrCodeDevice = CableQrCodeDevice :: new_persistent (
155- QrCodeOperationHint :: GetAssertionRequest ,
156- device_info_store. clone ( ) ,
157- ) ;
158-
159- println ! ( "Created QR code, awaiting for advertisement." ) ;
160- let qr_code = QrCode :: new ( device. qr_code . to_string ( ) ) . unwrap ( ) ;
161- let image = qr_code
162- . render :: < unicode:: Dense1x2 > ( )
163- . dark_color ( unicode:: Dense1x2 :: Light )
164- . light_color ( unicode:: Dense1x2 :: Dark )
165- . build ( ) ;
166- println ! ( "{}" , image) ;
157+ let all_devices = device_info_store. list_all ( ) . await ;
158+ let ( _known_device_id, known_device_info) =
159+ all_devices. first ( ) . expect ( "No known devices found" ) ;
160+
161+ let mut known_device: CableKnownDevice =
162+ CableKnownDevice :: new ( known_device_info, device_info_store. clone ( ) )
163+ . await
164+ . unwrap ( ) ;
167165
168166 // Connect to a known device
169- println ! ( "Tunnel established {:?}" , channel) ;
170- let ( mut channel, state_recv) = device. channel ( ) . await . unwrap ( ) ;
167+ let ( mut channel, state_recv) = known_device. channel ( ) . await . unwrap ( ) ;
171168 println ! ( "Tunnel established {:?}" , channel) ;
172169
173170 tokio:: spawn ( handle_updates ( state_recv) ) ;
0 commit comments