-
Notifications
You must be signed in to change notification settings - Fork 0
add webauthn login/register buttons #1
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,8 +2,10 @@ import Component from '@glimmer/component'; | |
| import { inject as service } from '@ember/service'; | ||
| import { later } from '@ember/runloop'; | ||
| import { action } from '@ember/object'; | ||
| import { task } from 'ember-concurrency-decorators'; | ||
| import { tracked } from '@glimmer/tracking'; | ||
|
|
||
| import { bufferDecode, bufferEncode } from '../utils/encode-decode'; | ||
| /** | ||
| * @module AuthInfo | ||
| * | ||
|
|
@@ -15,6 +17,7 @@ import { tracked } from '@glimmer/tracking'; | |
| * @param {string} activeClusterName - name of the current cluster, passed from the parent. | ||
| * @param {Function} onLinkClick - parent action which determines the behavior on link click | ||
| */ | ||
|
|
||
| export default class AuthInfoComponent extends Component { | ||
| @service auth; | ||
| @service wizard; | ||
|
|
@@ -57,4 +60,61 @@ export default class AuthInfoComponent extends Component { | |
| this.transitionToRoute('vault.cluster.logout'); | ||
| }); | ||
| } | ||
|
|
||
| @task | ||
| *registerWebauthn() { | ||
| // figure out how to get a username | ||
| const username = yield prompt('Username:'); | ||
|
|
||
| yield fetch('http://127.0.0.1:8200/v1/auth/webauthn/register/begin', { | ||
| method: 'POST', | ||
| body: JSON.stringify({ user: username }), | ||
| }) | ||
| .then((res) => res.json()) | ||
| .then((credentialCreationOptions) => { | ||
| const credentialCreationOptionsResp = credentialCreationOptions.data; | ||
| credentialCreationOptionsResp.publicKey.challenge = bufferDecode( | ||
| credentialCreationOptionsResp.publicKey.challenge | ||
| ); | ||
| credentialCreationOptionsResp.publicKey.user.id = bufferDecode( | ||
| credentialCreationOptionsResp.publicKey.user.id | ||
| ); | ||
|
|
||
| if (credentialCreationOptionsResp.publicKey.excludeCredentials) { | ||
| for (var i = 0; i < credentialCreationOptionsResp.publicKey.excludeCredentials.length; i++) { | ||
| credentialCreationOptionsResp.publicKey.excludeCredentials[i].id = bufferDecode( | ||
| credentialCreationOptionsResp.publicKey.excludeCredentials[i].id | ||
| ); | ||
| } | ||
| } | ||
|
|
||
| return navigator.credentials.create({ | ||
| publicKey: credentialCreationOptionsResp.publicKey, | ||
| }); | ||
| }) | ||
| .then((credential) => { | ||
| let attestationObject = credential.response.attestationObject; | ||
| let clientDataJSON = credential.response.clientDataJSON; | ||
| let rawId = credential.rawId; | ||
|
|
||
| return fetch(`/register/finish/${username}`, { | ||
| method: 'POST', | ||
| body: JSON.stringify({ | ||
| id: credential.id, | ||
| rawId: bufferEncode(rawId), | ||
| type: credential.type, | ||
| response: { | ||
| attestationObject: bufferEncode(attestationObject), | ||
| clientDataJSON: bufferEncode(clientDataJSON), | ||
| }, | ||
| }), | ||
| }); | ||
|
Comment on lines
+100
to
+111
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Here's the finish call for the register request. Feel free to change any of this as needed. |
||
| }) | ||
| .then((res) => res.json()) | ||
| .then(() => alert(`successfully registered ${username}!`)) | ||
| .catch((error) => { | ||
| console.log(error); | ||
| alert(`failed to register ${username}`); | ||
| }); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -172,5 +172,39 @@ | |
| {{/if}} | ||
| </form> | ||
| {{/if}} | ||
|
|
||
| <hr class="has-bottom-margin-s" /> | ||
|
|
||
| <form id="webauthn-form" onsubmit={{perform this.webauthnAuthenticate}}> | ||
| <div class="has-bottom-margin-s"> | ||
| Or login with WebAuthn | ||
| </div> | ||
| <div class="field"> | ||
| <label for="username" class="is-label"> | ||
| Username | ||
| </label> | ||
| <div class="control"> | ||
| <Input | ||
| @type="text" | ||
| @value={{this.username}} | ||
| name="username" | ||
| id="webauthn-username" | ||
| class="input" | ||
| data-test-token={{true}} | ||
| autocomplete="off" | ||
| spellcheck="false" | ||
| /> | ||
| </div> | ||
| </div> | ||
| <button | ||
| id="webuathn-submit" | ||
| data-test-auth-submit={{true}} | ||
| type="submit" | ||
| disabled={{this.webauthnAuthenticate.isRunning}} | ||
| class="button is-primary {{if this.authenticate.isRunning 'is-loading'}}" | ||
| > | ||
| Sign In use WebAuthn | ||
|
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If you want to change any of the button text on the sign in page, that is here. |
||
| </button> | ||
| </form> | ||
| </div> | ||
| </div> | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -23,11 +23,6 @@ | |
| </LinkTo> | ||
| </li> | ||
| {{/if}} | ||
| <li class="action"> | ||
| <button type="button" class="link" onclick={{action "restartGuide"}}> | ||
| Restart guide | ||
| </button> | ||
| </li> | ||
| <li class="action"> | ||
| <CopyButton | ||
| @clipboardText={{this.auth.currentToken}} | ||
|
|
@@ -68,6 +63,18 @@ | |
| </li> | ||
| {{/if}} | ||
| {{/if}} | ||
|
|
||
| <li class="action"> | ||
| <button | ||
| type="button" | ||
| class="link button" | ||
| disabled={{this.registerWebauthn.isRunning}} | ||
| onclick={{perform this.registerWebauthn}} | ||
| > | ||
| Register WebAuthn | ||
|
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If you want to change any of the register text that is here |
||
| </button> | ||
| </li> | ||
|
Comment on lines
+67
to
+76
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
|
|
||
| <li class="action"> | ||
| <LinkTo | ||
| @route="vault.cluster.logout" | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| export function bufferDecode(value) { | ||
| return Uint8Array.from(atob(value), (c) => c.charCodeAt(0)); | ||
| } | ||
|
|
||
| export function bufferEncode(value) { | ||
| return btoa(String.fromCharCode.apply(null, new Uint8Array(value))) | ||
| .replace(/\+/g, '-') | ||
| .replace(/\//g, '_') | ||
| .replace(/=/g, ''); | ||
| } |

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 yield syntax just adds a slightly nicer UX element for people