https://slides.com/elpete/itb2024-cbsecurity-passkeys
Who has the most Passkeys?
Username and Password
Single-use Links (Email login)
Two Factor Authentication
Security Keys or Cards
Source: The United States of P@ssw0rd$
Source: The United States of P@ssw0rd$
Source: The United States of P@ssw0rd$
Source: The United States of P@ssw0rd$
Source: The United States of P@ssw0rd$ (2019)
Techincal Name
Marketing
In less than a year, passkeys have been used to authenticate people more than 1 billion times across over 400 million Google Accounts.
box install cbsecurity-passkeys
component {
this.javaSettings = {
loadPaths : [ expandPath( "./modules/cbsecurity-passkeys/lib" ) ],
loadColdFusionClassPath : true,
reloadOnChange : false
};
}
schema.create( "cbsecurity_passkeys", ( t ) => {
t.increments( "id" );
t.unsignedInteger( "userId" ).references( "id" ).onTable( "users" );
t.raw( "credentialId BLOB" );
t.raw( "publicKey BLOB" );
t.unsignedInteger( "signCount" );
t.bit( "backupEligible" );
t.bit( "backupState" );
t.raw( "attestationObject BLOB" );
t.text( "clientDataJSON" );
t.datetime( "lastUsedTimestamp" ).nullable();
} );
moduleSettings = {
"cbsecurity-passkeys" : {
// WireBox mapping to the component
// implementing the ICredentialRepository interface
"credentialRepositoryMapping": "",
// The identifier for the relying party (your application)
"relyingPartyId" : CGI.SERVER_NAME,
// The display name for the relying party (your application)
"relyingPartyName" : controller.getSetting( "appName" ),
// The allowed origins to send you Passkeys.
// Defaults to the server name, if empty.
// (Non-standard ports need to be specified explicitly)
"allowedOrigins": []
}
};
resources/examples/Passkey.cfc
public string function getUsernameForUser( required any user ) {}
public string function getDisplayNameForUser( required any user ) {}
public any function getUserHandleForUser( required any user ) {}
public array function getCredentialIdsForUsername( required string username ) {}
public any function getUserHandleForUsername( required string username ) {}
public string function getUsernameForUserHandle( required any userHandle ) {}
public struct function lookup( required any credentialId, required any userHandle ) {}
public array function lookupAll( required any credentialId ) {}
public void function storeCredentialForUser( /* ... */ ) {}
public void function updateCredentialForUser( /* ... */ ) {}
<cfoutput>
<div>
<div class="jumbotron mt-sm-5 p-4">
<h1>Passkey Demo</h1>
</div>
<form id="passkey-form" action="#event.buildLink( "passkeys.new" )#" method="GET" style="display: none;">
<button type="submit" class="btn btn-primary">Create Passkey</button>
</form>
</div>
</cfoutput>
<script src="/modules_app/cbsecurity-passkeys/includes/js/passkeys.js"></script>
<script>
if (window.cbSecurity.passkeys.isSupported()) {
document.getElementById("passkey-form").style.display = "block";
}
</script>
<cfoutput>
<div>
<div class="jumbotron mt-sm-5 p-4">
<h1>Creating a Passkey...</h1>
</div>
</div>
<script src="/modules/cbsecurity-passkeys/includes/passkeys.js"></script>
<script>
window.cbSecurity.passkeys.register();
</script>
</cfoutput>
<cfoutput>
<h3>Log In</h3>
<small>or <a href="#event.buildLink( "registrations.new" )#">register for an account</a></small>
<hr />
<form id="loginForm" method="POST" action="#event.buildLink( "login" )#">
<input type="hidden" name="_token" value="#csrfGenerateToken()#" />
<div class="form-group">
<label for="username">Email Address:</label>
<input name="email" type="text" class="form-control" id="email" autocomplete="username webauthn" />
</div>
<div class="form-group">
<label for="password">Password:</label>
<input name="password" type="password" class="form-control" id="password" autocomplete="current-password webauthn"/>
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary">Log In</button>
</div>
</form>
<button id="passkeyLoginButton" type="button" class="btn btn-primary" style="display: none;">Log in with Passkey</button>
</cfoutput>
<script src="/modules_app/cbsecurity-passkeys/includes/passkeys.js"></script>
<script>
if ( window.cbSecurity.passkeys.isSupported() ) {
const passkeyLoginButton = document.getElementById( "passkeyLoginButton" );
passkeyLoginButton.style.display = "block";
passkeyLoginButton.addEventListener( "click", function() {
window.cbSecurity.passkeys.login(document.forms.loginForm.email.value);
});
}
</script>
So who has the most Passkeys?