Skip to content

Commit 500ea60

Browse files
committed
fix: Better integration with cbSecurity when not using cbauth
1 parent 1d9a4f3 commit 500ea60

File tree

9 files changed

+385
-30
lines changed

9 files changed

+385
-30
lines changed

ModuleConfig.cfc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,13 @@ component {
1414
"relyingPartyName" : controller.getSetting( "appName" ),
1515
"allowedOrigins" : []
1616
};
17+
18+
interceptorSettings = {
19+
"customInterceptionPoints" : [
20+
"onPasskeyLogin",
21+
"onPasskeyRegistration"
22+
]
23+
};
1724
}
1825

1926
function afterAspectsLoad() {
@@ -37,6 +44,7 @@ component {
3744
.build();
3845

3946
if ( settings.allowedOrigins.isEmpty() ) {
47+
throw( "You are required to set at least one `allowedOrigin` to use cbsecurity-passkeys" );
4048
}
4149

4250
var rpBuilder = createObject( "java", "com.yubico.webauthn.RelyingParty" )

README.md

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ this.javaSettings = {
1818
};
1919
```
2020

21-
3. Implement the `ICredentialRepository` interface. (See an example in `/resources/examples/Passkey.cfc`)
21+
3. Implement the `ICredentialRepository` interface. (See an example in `/resources/examples/quick/Passkey.cfc`)
2222

2323
4. Configure your `credentialRepositoryMapping` in `config/ColdBox.cfc`
2424
```js
@@ -27,4 +27,36 @@ moduleSettings = {
2727
"credentialRepositoryMapping": "Passkey"
2828
}
2929
}
30+
```
31+
32+
5. Configure at least one (1) `allowedOrigins`
33+
```js
34+
moduleSettings = {
35+
"cbsecurity-passkeys": {
36+
"credentialRepositoryMapping": "Passkey",
37+
"allowedOrigins": [ "example.com" ]
38+
}
39+
}
40+
```
41+
42+
Integrate using the `includes/passkeys.js` library:
43+
44+
```html
45+
<script src="/modules/cbsecurity-passkeys/includes/passkeys.js"></script>
46+
<script type="module">
47+
if ( await window.cbSecurity.passkeys.isSupported() ) {
48+
await window.cbSecurity.passkeys.register(
49+
// redirectLocation ("/")
50+
);
51+
}
52+
</script>
53+
<script type="module">
54+
if ( await window.cbSecurity.passkeys.isSupported() ) {
55+
await window.cbSecurity.passkeys.login(
56+
// username (optional)
57+
// redirectLocation ("/")
58+
// additionalParams ({})
59+
)
60+
}
61+
</script>
3062
```

handlers/Authentication.cfc

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,12 +91,12 @@ component {
9191
log.debug( "Passkey assertion successful for user [#username#]." );
9292
}
9393

94-
var user = auth().getUserService().retrieveUserByUsername( username );
94+
var user = cbSecure().getUserService().retrieveUserByUsername( username );
9595

9696
if ( log.canDebug() ) {
9797
log.debug( "Logging in user [#username#] from a successful Passkey assertion." );
9898
}
99-
auth().login( user );
99+
cbSecure().getAuthService().login( user );
100100

101101
if ( log.canDebug() ) {
102102
log.debug( "Updating the credential after a successful Passkey assertion." );
@@ -109,6 +109,8 @@ component {
109109
lastUsedTimestamp = now()
110110
);
111111

112+
announce( "onPasskeyLogin", { "event" : event, "user" : user } );
113+
112114
event.renderData(
113115
type = "json",
114116
statusCode = 200,

handlers/Registration.cfc

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@ component secured {
66
property name="flash" inject="coldbox:flash";
77

88
function new( event, rc, prc ) {
9-
var user = auth().user();
9+
var user = cbSecure().getUser();
1010
var name = variables.clientCredentialRepository.getUsernameForUser( user );
1111
var displayName = variables.clientCredentialRepository.getDisplayNameForUser( user );
1212
var idByteArray = createObject( "java", "com.yubico.webauthn.data.ByteArray" ).init(
13-
variables.clientCredentialRepository.getUserHandleForUser( auth().user() )
13+
variables.clientCredentialRepository.getUserHandleForUser( cbSecure().getUser() )
1414
);
1515

1616
if ( log.canDebug() ) {
@@ -102,7 +102,7 @@ component secured {
102102
}
103103

104104
variables.clientCredentialRepository.storeCredentialForUser(
105-
user = auth().user(),
105+
user = cbSecure().getUser(),
106106
credentialId = result
107107
.getKeyId()
108108
.getId()

resources/assets/js/passkeys.js

Lines changed: 38 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -27,40 +27,54 @@ const passkeys = {
2727
const publicKeyCredential = await webauthnJSON.create(credentialCreateOptions);
2828

2929
// Return encoded PublicKeyCredential to server
30-
await fetch("/cbsecurity/passkeys/registration", {
30+
const registrationResponse = await fetch("/cbsecurity/passkeys/registration", {
3131
method: "POST",
3232
headers: {
3333
"Content-Type": "application/json"
3434
},
3535
body: JSON.stringify({
3636
"publicKeyCredentialJson": JSON.stringify(publicKeyCredential)
3737
})
38-
})
39-
window.location = redirectLocation;
38+
});
39+
40+
if (registrationResponse.ok) {
41+
window.location = redirectLocation;
42+
} else {
43+
console.error("cbsecurity-passkeys - Registration failed:", registrationResponse);
44+
}
4045
},
41-
async login(username, redirectLocation = "/") {
42-
// Make the call that returns the credentialGetJson above
43-
const credentialGetOptions = await fetch("/cbsecurity/passkeys/authentication/new?" + new URLSearchParams({
44-
"username": username
45-
}))
46-
.then(resp => resp.json())
47-
.then(json => JSON.parse(json));
46+
async login(username, redirectLocation = "/", additionalParams = {}) {
47+
if ( !username ) {
48+
username = "";
49+
}
50+
// Make the call that returns the credentialGetJson above
51+
const credentialGetOptions = await fetch("/cbsecurity/passkeys/authentication/new?" + new URLSearchParams({
52+
...additionalParams,
53+
"username": username,
54+
}))
55+
.then(resp => resp.json())
56+
.then(json => JSON.parse(json));
57+
58+
// Call WebAuthn ceremony using webauthn-json wrapper
59+
const publicKeyCredential = await webauthnJSON.get(credentialGetOptions);
4860

49-
// Call WebAuthn ceremony using webauthn-json wrapper
50-
const publicKeyCredential = await webauthnJSON.get(credentialGetOptions);
61+
// Return encoded PublicKeyCredential to server
62+
const authenticationResponse = await fetch("/cbsecurity/passkeys/authentication", {
63+
method: "POST",
64+
headers: {
65+
"Content-Type": "application/json"
66+
},
67+
body: JSON.stringify({
68+
...additionalParams,
69+
"publicKeyCredentialJson": JSON.stringify(publicKeyCredential)
70+
})
71+
});
5172

52-
// Return encoded PublicKeyCredential to server
53-
await fetch("/cbsecurity/passkeys/authentication", {
54-
method: "POST",
55-
headers: {
56-
"Content-Type": "application/json"
57-
},
58-
body: JSON.stringify({
59-
"publicKeyCredentialJson": JSON.stringify(publicKeyCredential)
60-
})
61-
}).then( () => {
62-
window.location = redirectLocation;
63-
});
73+
if (authenticationResponse.ok) {
74+
window.location = redirectLocation;
75+
} else {
76+
console.error("cbsecurity-passkeys - Authentication failed:", authenticationResponse);
77+
}
6478
},
6579
};
6680

0 commit comments

Comments
 (0)