-
Notifications
You must be signed in to change notification settings - Fork 46
feat(javascript-sdk): register-device-name #340
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
Your preview environment pr-340-ryanbas21 has been deployed. Preview environment endpoints are available at: |
| "executor": "@nrwl/rollup:rollup", | ||
| "options": { | ||
| "compiler": "babel", | ||
| "compiler": "tsc", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so typechecking happens on build, was an oversight by me.
☁️ Nx Cloud ReportCI is running/has finished running commands for commit f845505. As they complete they will appear below. Click to see the status, the terminal output, and the build insights. 📂 See all runs for this branch ✅ Successfully ran 5 targetsSent with 💌 from NxCloud. |
| import { parseWebAuthnAuthenticateText, parseWebAuthnRegisterText } from './script-parser'; | ||
|
|
||
| // <clientdata>::<attestation>::<publickeyCredential>::<DeviceName> | ||
| type DeviceName< |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a type that can create a Device Name if given a name or not
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like the strictness of this type, but the name feels a bit misleading.
| PubKeyCred extends PublicKeyCredential, | ||
| Name = '', | ||
| > = Name extends infer P extends string | ||
| ? `${ClientId}::${Attestation}::${PubKeyCred['id']}${P extends '' ? '' : `::${P}`}` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
realistically, i thought a simpler type could be used, i have no idea why i couldn't use a simpler type, it only worked when I went this route.
| } | ||
|
|
||
| hiddenCallback.setInputValue(outcome); | ||
| hiddenCallback.setInputValue(deviceName ? `${outcome}::${deviceName}` : outcome); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hypothetically, we could give hiddenCallback a generic that defaults to unknown and then we can provide that here for more type inference and passing.
|
|
||
| let stringOutput = `${clientDataJSON}::${authenticatorData}::${signature}::${credential.id}`; | ||
| let stringOutput = | ||
| `${clientDataJSON}::${authenticatorData}::${signature}::${credential.id}` as DeviceName< |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Had to force this type, theres probably a way to create a string builder that outputs as the type though that may fit better.
| string, | ||
| AttestationType, | ||
| PublicKeyCredential, | ||
| typeof userHandle |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suppose this will always be string, but if userHandle is ever a more strict type then we could leverage that here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
userHandle is just a username, so it can be any kind of string. This is used for supporting the "usernameless" flow where the username is stored on the WebAuthn device.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right but one could pass “username” and in typescript 5 we could leverage a const generic which would make the type “username” and not string so it could be used more strictly
| "target": "ES2020" | ||
| }, | ||
| "include": ["**/*.ts"], | ||
| "include": ["**/*.ts", "jest.setup.js"], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I addedt his when I was trying to find ways to test this with jest, but I can remove it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably should remove it then, if it's not needed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
removed
| <body> | ||
| <!-- script src="/_polyfills/fast-text-encoder.js"></script --> | ||
| <button class="login-btn">Login</button> | ||
| <button class="device-registration">Device Registration</button> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is just for that manual test I wrote, has no affect on the automation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, I was wondering why the additional flow was added. There's currently no automation around WebAuthn; everything is manually tested. So, nothing should prevent you from adding your feature to the existing flow, rather than create an entirely new flow.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah I only added it because the only difference is that the previous flow didn't add a device name, but i could just add a device name and remvoe this i think if preferred.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The main reason for this flow, is that the tenant i used had a different tree, so I used stoyans tenant and the flow itself requires certs that run without errors.
So my testing was done in a dfiferent env and couldn't use the mock server itself.
cerebrl
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks good overall. A few additional comments:
- Can you fill out the PR description template?
- Provide screenshots of the results from testing this new feature from Platform Admin (showing full end-to-end testing)
- Rework the name of the new type
- I don't think you need to create a whole new flow in the
autoscript.ts, but let me know if I'm missing something
| console.log('Handle WebAuthn Registration'); | ||
| try { | ||
| step = await forgerock.FRWebAuthn.register<'mydevice'>(step, 'mydevice'); | ||
| // ensure the step here has the 'mydevice' name at the end of the value. (outcome) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this a TODO comment?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, okay. Rather than this comment instructing the manual tester to inspect the step in the console, can we just have a condition in the code to check this for us, similar to the other conditions that are ensuring things are working properly? If mydevice is not present, let's just throw an error like how we handle other issues.
| <body> | ||
| <!-- script src="/_polyfills/fast-text-encoder.js"></script --> | ||
| <button class="login-btn">Login</button> | ||
| <button class="device-registration">Device Registration</button> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, I was wondering why the additional flow was added. There's currently no automation around WebAuthn; everything is manually tested. So, nothing should prevent you from adding your feature to the existing flow, rather than create an entirely new flow.
| const { hiddenCallback, metadataCallback, textOutputCallback } = this.getCallbacks(step); | ||
| if (hiddenCallback && (metadataCallback || textOutputCallback)) { | ||
| let outcome: string; | ||
| let outcome: DeviceName<string, AttestationType, PublicKeyCredential>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This type reads a bit odd for me. Should the type name be something more like OutcomeWithName, rather than DeviceName?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
| import { parseWebAuthnAuthenticateText, parseWebAuthnRegisterText } from './script-parser'; | ||
|
|
||
| // <clientdata>::<attestation>::<publickeyCredential>::<DeviceName> | ||
| type DeviceName< |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like the strictness of this type, but the name feels a bit misleading.
| string, | ||
| AttestationType, | ||
| PublicKeyCredential, | ||
| typeof userHandle |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
userHandle is just a username, so it can be any kind of string. This is used for supporting the "usernameless" flow where the username is stored on the WebAuthn device.
| "target": "ES2020" | ||
| }, | ||
| "include": ["**/*.ts"], | ||
| "include": ["**/*.ts", "jest.setup.js"], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably should remove it then, if it's not needed.
make it so `register` accepts a parameter for registering a device name
cerebrl
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!

JIRA Ticket
https://bugster.forgerock.org/jira/browse/SDKS-2298
Description
make it so
registeraccepts a parameter for registering a device name. An optional generic parameter that adds a device name to the registration step. This makes it so that::${devicename}is concated to the device string that is made from the outcome.Type of Change
Please Delete options that are not relevant
How Has This Been Tested?
See the e2e example, which uses stoyans tenant
Click the device registration button and then go through the flow there. You should see the hidden callback have the
outcomevalue withDeviceName(as passed in) concated to the end.The name can be very long and cut off
Definition of Done
Check all that apply
Documentation