@ -14,9 +14,9 @@ export function initUserAuthWebAuthn() {
$ . getJSON ( ` ${ appSubUrl } /user/webauthn/assertion ` , { } )
$ . getJSON ( ` ${ appSubUrl } /user/webauthn/assertion ` , { } )
. done ( ( makeAssertionOptions ) => {
. done ( ( makeAssertionOptions ) => {
makeAssertionOptions . publicKey . challenge = decode ( makeAssertionOptions . publicKey . challenge ) ;
makeAssertionOptions . publicKey . challenge = decodeURLEncodedBase64 ( makeAssertionOptions . publicKey . challenge ) ;
for ( let i = 0 ; i < makeAssertionOptions . publicKey . allowCredentials . length ; i ++ ) {
for ( let i = 0 ; i < makeAssertionOptions . publicKey . allowCredentials . length ; i ++ ) {
makeAssertionOptions . publicKey . allowCredentials [ i ] . id = decode ( makeAssertionOptions . publicKey . allowCredentials [ i ] . id ) ;
makeAssertionOptions . publicKey . allowCredentials [ i ] . id = decodeURLEncodedBase64 ( makeAssertionOptions . publicKey . allowCredentials [ i ] . id ) ;
}
}
navigator . credentials . get ( {
navigator . credentials . get ( {
publicKey : makeAssertionOptions . publicKey
publicKey : makeAssertionOptions . publicKey
@ -56,14 +56,14 @@ function verifyAssertion(assertedCredential) {
type : 'POST' ,
type : 'POST' ,
data : JSON . stringify ( {
data : JSON . stringify ( {
id : assertedCredential . id ,
id : assertedCredential . id ,
rawId : bufferEncode ( rawId ) ,
rawId : encodeURLEncodedBase64 ( rawId ) ,
type : assertedCredential . type ,
type : assertedCredential . type ,
clientExtensionResults : assertedCredential . getClientExtensionResults ( ) ,
clientExtensionResults : assertedCredential . getClientExtensionResults ( ) ,
response : {
response : {
authenticatorData : bufferEncode ( authData ) ,
authenticatorData : encodeURLEncodedBase64 ( authData ) ,
clientDataJSON : bufferEncode ( clientDataJSON ) ,
clientDataJSON : encodeURLEncodedBase64 ( clientDataJSON ) ,
signature : bufferEncode ( sig ) ,
signature : encodeURLEncodedBase64 ( sig ) ,
userHandle : bufferEncode ( userHandle ) ,
userHandle : encodeURLEncodedBase64 ( userHandle ) ,
} ,
} ,
} ) ,
} ) ,
contentType : 'application/json; charset=utf-8' ,
contentType : 'application/json; charset=utf-8' ,
@ -85,14 +85,21 @@ function verifyAssertion(assertedCredential) {
} ) ;
} ) ;
}
}
// Encode an ArrayBuffer into a base64 string.
// Encode an ArrayBuffer into a URLEncoded base64 string.
function bufferEncode ( value ) {
function encodeURLEncodedBase64 ( value ) {
return encode ( value )
return encode ( value )
. replace ( /\+/g , '-' )
. replace ( /\+/g , '-' )
. replace ( /\//g , '_' )
. replace ( /\//g , '_' )
. replace ( /=/g , '' ) ;
. replace ( /=/g , '' ) ;
}
}
// Dccode a URLEncoded base64 to an ArrayBuffer string.
function decodeURLEncodedBase64 ( value ) {
return decode ( value
. replace ( /_/g , '/' )
. replace ( /-/g , '+' ) ) ;
}
function webauthnRegistered ( newCredential ) {
function webauthnRegistered ( newCredential ) {
const attestationObject = new Uint8Array ( newCredential . response . attestationObject ) ;
const attestationObject = new Uint8Array ( newCredential . response . attestationObject ) ;
const clientDataJSON = new Uint8Array ( newCredential . response . clientDataJSON ) ;
const clientDataJSON = new Uint8Array ( newCredential . response . clientDataJSON ) ;
@ -104,11 +111,11 @@ function webauthnRegistered(newCredential) {
headers : { 'X-Csrf-Token' : csrfToken } ,
headers : { 'X-Csrf-Token' : csrfToken } ,
data : JSON . stringify ( {
data : JSON . stringify ( {
id : newCredential . id ,
id : newCredential . id ,
rawId : bufferEncode ( rawId ) ,
rawId : encodeURLEncodedBase64 ( rawId ) ,
type : newCredential . type ,
type : newCredential . type ,
response : {
response : {
attestationObject : bufferEncode ( attestationObject ) ,
attestationObject : encodeURLEncodedBase64 ( attestationObject ) ,
clientDataJSON : bufferEncode ( clientDataJSON ) ,
clientDataJSON : encodeURLEncodedBase64 ( clientDataJSON ) ,
} ,
} ,
} ) ,
} ) ,
dataType : 'json' ,
dataType : 'json' ,
@ -184,11 +191,11 @@ function webAuthnRegisterRequest() {
} ) . done ( ( makeCredentialOptions ) => {
} ) . done ( ( makeCredentialOptions ) => {
$ ( '#nickname' ) . closest ( 'div.field' ) . removeClass ( 'error' ) ;
$ ( '#nickname' ) . closest ( 'div.field' ) . removeClass ( 'error' ) ;
makeCredentialOptions . publicKey . challenge = decode ( makeCredentialOptions . publicKey . challenge ) ;
makeCredentialOptions . publicKey . challenge = decodeURLEncodedBase64 ( makeCredentialOptions . publicKey . challenge ) ;
makeCredentialOptions . publicKey . user . id = decode ( makeCredentialOptions . publicKey . user . id ) ;
makeCredentialOptions . publicKey . user . id = decodeURLEncodedBase64 ( makeCredentialOptions . publicKey . user . id ) ;
if ( makeCredentialOptions . publicKey . excludeCredentials ) {
if ( makeCredentialOptions . publicKey . excludeCredentials ) {
for ( let i = 0 ; i < makeCredentialOptions . publicKey . excludeCredentials . length ; i ++ ) {
for ( let i = 0 ; i < makeCredentialOptions . publicKey . excludeCredentials . length ; i ++ ) {
makeCredentialOptions . publicKey . excludeCredentials [ i ] . id = decode ( makeCredentialOptions . publicKey . excludeCredentials [ i ] . id ) ;
makeCredentialOptions . publicKey . excludeCredentials [ i ] . id = decodeURLEncodedBase64 ( makeCredentialOptions . publicKey . excludeCredentials [ i ] . id ) ;
}
}
}
}