22< script type = "application/javascript" src = "{% static 'passkeys/js/base64url.js' %}" > </ script >
33< script type = "application/javascript" src = "{% static 'passkeys/js/helpers.js' %}" > < / script >
44< script type = "text/javascript" >
5- window.conditionalUI=false;
5+ window.allow_immediate=true;
6+ async function checkImmediateMediationAvailability() {
7+ if ( ! window . allow_immediate )
8+ return [ false , false ] ;
9+ try {
10+ const capabilities = await PublicKeyCredential . getClientCapabilities ( ) ;
11+ if ( capabilities . immediateGet && window . PasswordCredential ) {
12+ console . log ( "Immediate Mediation with passwords supported." ) ;
13+ return [ true , true ] ;
14+ } else if ( capabilities . immediateGet ) {
15+ console . log ( "Immediate Mediation without passwords supported." ) ;
16+ return [ true , false ] ;
17+ } else {
18+ console . log ( "Immediate Mediation unsupported." ) ;
19+ return [ false , false ] ; }
20+ } catch ( error ) {
21+ console . error ( "Error getting client capabilities:" , error ) ;
22+ return [ false , false ] ;
23+ }
24+ }
25+
26+ function tryLogin ( formid )
27+ {
28+ window . loginForm = formid ;
29+ if ( $ ( "#inputUsername" ) . val ( ) != "" && $ ( "#inputPassword" ) . val ( ) != "" )
30+ $ ( "#" + formid ) . submit ( ) ;
31+ options = { } ;
32+ status = checkImmediateMediationAvailability ( ) ;
33+ if ( status [ 0 ] && window . allow_immediate )
34+ {
35+ start_authn ( formid , false ) ;
36+ }
37+ }
38+ window . conditionalUI = false ;
639 window . conditionUIAbortController = new AbortController ( ) ;
740 window . conditionUIAbortSignal = conditionUIAbortController . signal ;
841 function checkConditionalUI ( form ) {
9- if ( window . PublicKeyCredential && PublicKeyCredential . isConditionalMediationAvailable ) {
10- // Check if conditional mediation is available.
11- PublicKeyCredential . isConditionalMediationAvailable ( ) . then ( ( result ) => {
12- window . conditionalUI = result ;
13- if ( window . conditionalUI ) {
14- start_authn ( form , true )
15- }
42+ if ( window . PublicKeyCredential && PublicKeyCredential . isConditionalMediationAvailable ) {
43+ // Check if conditional mediation is available.
44+ PublicKeyCredential . isConditionalMediationAvailable ( ) . then ( ( result ) => {
45+ window . conditionalUI = result ;
46+ if ( window . conditionalUI ) {
47+ start_authn ( form , true )
48+ }
1649} ) ;
1750}
1851}
1952
20- var GetAssertReq = ( getAssert ) => {
21- getAssert . publicKey . challenge = base64url . decode ( getAssert . publicKey . challenge ) ;
53+ var GetAssertReq = ( getAssert ) => {
54+ getAssert . publicKey . challenge = base64url . decode ( getAssert . publicKey . challenge ) ;
2255
23- for ( let allowCred of getAssert . publicKey . allowCredentials ) {
24- allowCred . id = base64url . decode ( allowCred . id ) ;
25- }
56+ for ( let allowCred of getAssert . publicKey . allowCredentials ) {
57+ allowCred . id = base64url . decode ( allowCred . id ) ;
58+ }
2659
27- return getAssert
28- }
60+ return getAssert
61+ }
2962
30- function start_authn ( form , conditionalUI = false )
31- {
32- window . loginForm = form ;
33- fetch ( '{% url ' passkeys :auth_begin ' %}' , {
34- method : 'GET' ,
63+ function start_authn ( form , conditionalUI = false )
64+ {
65+ window . loginForm = form ;
66+ fetch ( '{% url ' passkeys :auth_begin ' %}' , {
67+ method : 'GET' ,
3568 } ) . then ( function ( response ) {
36- if ( response . ok ) {
37- return response . json ( ) . then ( function ( req ) {
38- return GetAssertReq ( req )
39- } ) ;
40- }
41- throw new Error ( 'No credential available to authenticate!' ) ;
69+ if ( response . ok ) {
70+ return response . json ( ) . then ( function ( req ) {
71+ return GetAssertReq ( req )
72+ } ) ;
73+ }
74+ throw new Error ( 'No credential available to authenticate!' ) ;
4275 } ) . then ( function ( options ) {
4376 if ( conditionalUI ) {
4477 options . mediation = 'conditional' ;
4578 options . signal = window . conditionUIAbortSignal ;
4679 }
4780 else
48- window . conditionUIAbortController . abort ( )
81+ {
82+ window . conditionUIAbortController . abort ( 'Stopping conditional UI' ) ;
83+ options . mediation = 'immediate' ;
84+ options . password = true ;
85+ }
4986 console . log ( options )
50- return navigator . credentials . get ( options ) ;
87+ return navigator . credentials . get ( options ) ;
5188 } ) . then ( function ( assertion ) {
5289 pk = $ ( "#passkeys" )
5390 if ( pk . length == 0 )
54- {
55- console . error ( "Did you add the 'passkeys' hidden input field" )
56- return
57- }
91+ {
92+ console . error ( "Did you add the 'passkeys' hidden input field" )
93+ return
94+ }
5895 pk . val ( JSON . stringify ( publicKeyCredentialToJSON ( assertion ) ) ) ;
5996 x = document . getElementById ( window . loginForm )
6097 if ( x === null || x === undefined )
61- {
62- console . error ( "Did you pass the correct form id to auth function" )
63- return ;
64- }
65- x . submit ( )
98+ {
99+ console . error ( "Did you pass the correct form id to auth function" )
100+ return ;
101+ }
102+ x . submit ( )
103+
104+ } ) . catch ( function ( err )
105+ {
66106
67- } ) ;
68- $ ( document ) . ready ( function ( ) {
107+ if ( err . toString ( ) === 'NotAllowedError: No immediate discoverable credentials are found.' ) {
108+ window . allow_immediate = false ;
109+ tryLogin ( window . loginForm ) ;
110+ }
111+ else {
112+ console . error ( "Authentication failed: " + err ) ;
113+ }
114+
115+ } ) ;
116+ $ ( document ) . ready ( function ( ) {
69117 if ( location . protocol != 'https:' ) {
70- console . error ( "Passkeys must work under secure context" )
71- }
118+ console . error ( "Passkeys must work under secure context" )
119+ }
72120 } ) ;
73- }
74- function authn(form)
121+ }
122+ function authn ( form )
75123 {
76- start_authn ( form , false )
124+ start_authn ( form , false )
77125 }
78126
79- </ script >
127+ < / script >
0 commit comments