Integrating WebAuthn/Passkeys and moving values from JS to C++
Added by Ethin Probst 9 months ago
I have a couple questions:
- I'd like to write a custom authentication system that uses WebAuthn and Passkeys, but I'm not sure how to actually do this in a framework like Wt. Has someone managed to do this?
- How do I transfer values from JS to C++ and back? I.e., if I want to integrate this SDK (https://simplelogin.io/docs/siwsl/intro) what's the best way of doing it? I could just use raw OAuth2, but I'm uncertain how I'd use those parts of the auth module separately from the rest.
Replies (4)
RE: Integrating WebAuthn/Passkeys and moving values from JS to C++ - Added by Matthias Van Ceulebroeck 9 months ago
Hello,
I'm very sorry for the late reply.
We are currently looking at a WebAuthn implementation internally. As far as I am aware I do not know of any clients/users that have this implementation. The native Wt implementation is far from ready, and still tentative, but I would really like to update the Auth module a bit, to ensure that it supports alternatives (or extensions) to username/password, like MFA. As such, I cannot promise a specific date for this feature.
For any OAuth2 flow you need to look at OAuthService and/or OidcService. If the service follows the spec closely, an implementation like GoogleService would be a good guideline.
If there is more custom logic necessary, and you need to pass information between JS and the C++ backend you can look at JSignal, and JSlot. The former is used to call JS from C++, the latter does the reverse. I believe that for an OAuth2 flow this will likely be unnecessary, since you can rely on the above Service
. Should you not be able to, and require more help, please let me know.
Best,
Matthias
RE: Integrating WebAuthn/Passkeys and moving values from JS to C++ - Added by Ethin Probst 9 months ago
Hi Matthias,
Thank you for your reply. I asked about passing values between the C++ and JS sides because I know that Wt does not yet implement WebAuthn but I wanted to try my hand at implementing it myself. However, for this to work the credentials/challenges (used in navigator.credential.create
and navigator.credential.get
) need to be passed between client and server and I wasn't sure how I would go about actually accomplishing that. Are there any simpler examples of using JSlot/JSignal? I can look at the docs but I thought I would ask (the WebGL example is pretty daunting).
As for the implementation of something like this would I create a widget and then just store state in there? I'm quite new to Wt so am quite unsure about best practice. I am, however, familiar with Qt and similar frameworks, and Wt's similarity is what attracted me to it (I don't fancy having to manually write HTML/CSS, and Razor/React doesn't look all that appealing either).
RE: Integrating WebAuthn/Passkeys and moving values from JS to C++ - Added by Matthias Van Ceulebroeck 9 months ago
I believe that the examples/javascript
example may show you how this works, without being too verbose.
If you are familiar with Qt, that's great, since Wt approaches a lot of things similarly.
In rough lines I believe the implementation will have to do the following:
- create a
Credential
class to manage a single credential unit (tracking the identifier, key, additional info) - link these to your specific user record
- ensure that your UserDatabase is able to find the user based on credentials / add credentials to users
- add a new widget that shows a login page, and upon pressing a button (and entering an identifier) starts the authentication flow <- you will need some JSlot/JSignal handing here to ensure that communication between browser and the back-end is synchronized
- integrate the new widget with your current login page
As I said before you'll likely be able to rely on a basic OAuthService
flow, and may need to extend it to set the right variables and start the correct request chain.
It's a rough outline, but I hope this helps you.
RE: Integrating WebAuthn/Passkeys and moving values from JS to C++ - Added by Ethin Probst 9 months ago
That was a good outline. I believe wt::dbo
will be of great help here. In general my login flow, at least theoretically, will be something like:
- User is prompted to login/create an account.
- User hits log in.
- System checks to see if account identifier is stored in client; if so, it immediately skips to the Passkey authentication flow.
- If the account identifier is not stored on the client, user is prompted to enter it. Then the login flow proceeds to the Passkey authentication flow.
- If the device is not a registered Passkey, OAuth2 (via a service like Simple Login) is used as an account access acquisition method. This method is secured such that only device registration is possible.
My goal is to try to build an IAM solution that collects as little to no information about the user as possible. I'm sure this method has flaws that I'll have to address. I'll look at the example you recommended though -- thanks!