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
146 lines
4.6 KiB
JavaScript
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);
|
|
}
|
|
);
|
|
},
|
|
},
|
|
});
|