This repository has been archived on 2023-03-18. You can view files and clone it, but cannot push or open issues or pull requests.
osr-discourse-src/app/assets/javascripts/discourse/app/controllers/second-factor-add-security-key.js
Josh Soref 59097b207f
DEV: Correct typos and spelling mistakes (#12812)
Over the years we accrued many spelling mistakes in the code base. 

This PR attempts to fix spelling mistakes and typos in all areas of the code that are extremely safe to change 

- comments
- test descriptions
- other low risk areas
2021-05-21 11:43:47 +10:00

146 lines
4.6 KiB
JavaScript

import {
bufferToBase64,
isWebauthnSupported,
stringToBuffer,
} from "discourse/lib/webauthn";
import Controller from "@ember/controller";
import I18n from "I18n";
import ModalFunctionality from "discourse/mixins/modal-functionality";
// model for this controller is user
export default Controller.extend(ModalFunctionality, {
loading: false,
errorMessage: null,
onShow() {
// clear properties every time because the controller is a singleton
this.setProperties({
errorMessage: null,
loading: true,
securityKeyName: I18n.t("user.second_factor.security_key.default_name"),
webauthnUnsupported: !isWebauthnSupported(),
});
this.model
.requestSecurityKeyChallenge()
.then((response) => {
if (response.error) {
this.set("errorMessage", response.error);
return;
}
this.setProperties({
errorMessage: isWebauthnSupported()
? null
: I18n.t("login.security_key_support_missing_error"),
loading: false,
challenge: response.challenge,
relayingParty: {
id: response.rp_id,
name: response.rp_name,
},
supported_algorithms: response.supported_algorithms,
user_secure_id: response.user_secure_id,
existing_active_credential_ids:
response.existing_active_credential_ids,
});
})
.catch((error) => {
this.send("closeModal");
this.onError(error);
})
.finally(() => this.set("loading", false));
},
actions: {
registerSecurityKey() {
if (!this.securityKeyName) {
this.set(
"errorMessage",
I18n.t("user.second_factor.security_key.name_required_error")
);
return;
}
const publicKeyCredentialCreationOptions = {
challenge: Uint8Array.from(this.challenge, (c) => c.charCodeAt(0)),
rp: {
name: this.relayingParty.name,
id: this.relayingParty.id,
},
user: {
id: Uint8Array.from(this.user_secure_id, (c) => c.charCodeAt(0)),
displayName: this.model.username_lower,
name: this.model.username_lower,
},
pubKeyCredParams: this.supported_algorithms.map((alg) => {
return { type: "public-key", alg: alg };
}),
excludeCredentials: this.existing_active_credential_ids.map(
(credentialId) => {
return {
type: "public-key",
id: stringToBuffer(atob(credentialId)),
};
}
),
timeout: 20000,
attestation: "none",
authenticatorSelection: {
// see https://chromium.googlesource.com/chromium/src/+/master/content/browser/webauth/uv_preferred.md for why
// default value of preferred is not necessarily what we want, it limits webauthn to only devices that support
// user verification, which usually requires entering a PIN
userVerification: "discouraged",
},
};
navigator.credentials
.create({
publicKey: publicKeyCredentialCreationOptions,
})
.then(
(credential) => {
let serverData = {
id: credential.id,
rawId: bufferToBase64(credential.rawId),
type: credential.type,
attestation: bufferToBase64(
credential.response.attestationObject
),
clientData: bufferToBase64(credential.response.clientDataJSON),
name: this.securityKeyName,
};
this.model
.registerSecurityKey(serverData)
.then((response) => {
if (response.error) {
this.set("errorMessage", response.error);
return;
}
this.markDirty();
this.set("errorMessage", null);
this.send("closeModal");
})
.catch((error) => this.onError(error))
.finally(() => this.set("loading", false));
},
(err) => {
if (err.name === "InvalidStateError") {
return this.set(
"errorMessage",
I18n.t("user.second_factor.security_key.already_added_error")
);
}
if (err.name === "NotAllowedError") {
return this.set(
"errorMessage",
I18n.t("user.second_factor.security_key.not_allowed_error")
);
}
this.set("errorMessage", err.message);
}
);
},
},
});