@@ -20,6 +20,34 @@ const RegisterPasskey: React.FC = () => {
2020 const [ message , setMessage ] = useState ( "" ) ;
2121 const [ passkeyAvailable , setPasskeyAvailable ] = useState ( false ) ;
2222
23+ function base64urlToArrayBuffer ( base64url : string ) : ArrayBuffer {
24+ const padding = "=" . repeat ( ( 4 - ( base64url . length % 4 ) ) % 4 ) ;
25+ const base64 = ( base64url + padding ) . replace ( / - / g, "+" ) . replace ( / _ / g, "/" ) ;
26+ const binary = atob ( base64 ) ;
27+ const buffer = new Uint8Array ( binary . length ) ;
28+ for ( let i = 0 ; i < binary . length ; i ++ ) {
29+ buffer [ i ] = binary . charCodeAt ( i ) ;
30+ }
31+ return buffer . buffer ;
32+ }
33+
34+ function decodeSimpleWebauthnOptions ( options : any ) {
35+ return {
36+ ...options ,
37+ challenge : base64urlToArrayBuffer ( options . challenge ) ,
38+ user : {
39+ ...options . user ,
40+ id : base64urlToArrayBuffer ( options . user . id ) ,
41+ } ,
42+ excludeCredentials : ( options . excludeCredentials || [ ] ) . map (
43+ ( cred : any ) => ( {
44+ ...cred ,
45+ id : base64urlToArrayBuffer ( cred . id ) ,
46+ } )
47+ ) ,
48+ } ;
49+ }
50+
2351 const handlePasskeyRegister = async ( ) => {
2452 setStatus ( "loading" ) ;
2553
@@ -41,14 +69,13 @@ const RegisterPasskey: React.FC = () => {
4169 return ;
4270 }
4371
44- const optionsJSON = await challengeRes . json ( ) ;
72+ const options = await challengeRes . json ( ) ;
73+
74+ const publicKey = decodeSimpleWebauthnOptions ( options ) ;
4575
4676 let attResp : RegistrationResponseJSON ;
4777 try {
48- attResp = await startRegistration ( {
49- optionsJSON,
50- useAutoRegister : true ,
51- } ) ;
78+ attResp = await startRegistration ( publicKey ) ;
5279
5380 await verifyPassKey ( attResp ) ;
5481 } catch ( error ) {
0 commit comments