1
0
mirror of https://github.com/misskey-dev/misskey.git synced 2026-05-21 16:55:33 +02:00

refactor: パスキーまわりのライブラリを更新 (#17354)

* refactor: パスキーまわりのライブラリを更新

* fix
This commit is contained in:
かっこかり
2026-05-03 17:16:06 +09:00
committed by GitHub
parent 9d20152e05
commit 723d8add2f
20 changed files with 96 additions and 243 deletions

View File

@@ -22,21 +22,21 @@ SPDX-License-Identifier: AGPL-3.0-only
<script setup lang="ts">
import { ref, onMounted } from 'vue';
import { get as webAuthnRequest } from '@github/webauthn-json/browser-ponyfill';
import { startAuthentication } from '@simplewebauthn/browser';
import { i18n } from '@/i18n.js';
import MkButton from '@/components/MkButton.vue';
import type { AuthenticationPublicKeyCredential } from '@github/webauthn-json/browser-ponyfill';
import type { PublicKeyCredentialRequestOptionsJSON, AuthenticationResponseJSON } from '@simplewebauthn/browser';
const props = defineProps<{
credentialRequest: CredentialRequestOptions;
credentialRequest: PublicKeyCredentialRequestOptionsJSON;
isPerformingPasswordlessLogin?: boolean;
}>();
const emit = defineEmits<{
(ev: 'done', credential: AuthenticationPublicKeyCredential): void;
(ev: 'done', credential: AuthenticationResponseJSON): void;
(ev: 'useTotp'): void;
}>();
@@ -44,7 +44,7 @@ const queryingKey = ref(true);
async function queryKey() {
queryingKey.value = true;
await webAuthnRequest(props.credentialRequest)
await startAuthentication({ optionsJSON: props.credentialRequest })
.catch(() => {
return Promise.reject(null);
})

View File

@@ -67,8 +67,8 @@ SPDX-License-Identifier: AGPL-3.0-only
<script setup lang="ts">
import { nextTick, onBeforeUnmount, ref, shallowRef, useTemplateRef } from 'vue';
import * as Misskey from 'misskey-js';
import { supported as webAuthnSupported, parseRequestOptionsFromJSON } from '@github/webauthn-json/browser-ponyfill';
import type { AuthenticationPublicKeyCredential } from '@github/webauthn-json/browser-ponyfill';
import { browserSupportsWebAuthn } from '@simplewebauthn/browser';
import type { PublicKeyCredentialRequestOptionsJSON, AuthenticationResponseJSON } from '@simplewebauthn/browser';
import type { OpenOnRemoteOptions } from '@/utility/please-login.js';
import type { PwResponse } from '@/components/MkSignin.password.vue';
import { misskeyApi } from '@/utility/misskey-api.js';
@@ -108,21 +108,18 @@ const userInfo = ref<null | Misskey.entities.UserDetailed>(null);
const password = ref('');
//#region Passkey Passwordless
const credentialRequest = shallowRef<CredentialRequestOptions | null>(null);
const credentialRequest = shallowRef<PublicKeyCredentialRequestOptionsJSON | null>(null);
const passkeyContext = ref('');
const doingPasskeyFromInputPage = ref(false);
function onPasskeyLogin(): void {
if (webAuthnSupported()) {
if (browserSupportsWebAuthn()) {
doingPasskeyFromInputPage.value = true;
waiting.value = true;
misskeyApi('signin-with-passkey', {})
.then((res) => {
passkeyContext.value = res.context ?? '';
credentialRequest.value = parseRequestOptionsFromJSON({
// @ts-expect-error TODO: misskey-js由来の型@simplewebauthn/typesとフロントエンド由来の型@github/webauthn-jsonが合わない
publicKey: res.option,
});
credentialRequest.value = res.option;
page.value = 'passkey';
waiting.value = false;
@@ -131,12 +128,12 @@ function onPasskeyLogin(): void {
}
}
function onPasskeyDone(credential: AuthenticationPublicKeyCredential): void {
function onPasskeyDone(credential: AuthenticationResponseJSON): void {
waiting.value = true;
if (doingPasskeyFromInputPage.value) {
misskeyApi<Misskey.entities.SigninWithPasskeyResponse>('signin-with-passkey', {
credential: credential.toJSON(),
misskeyApi('signin-with-passkey', {
credential: credential,
context: passkeyContext.value,
}).then((res) => {
if (res.signinResponse == null) {
@@ -150,8 +147,7 @@ function onPasskeyDone(credential: AuthenticationPublicKeyCredential): void {
tryLogin({
username: userInfo.value.username,
password: password.value,
// @ts-expect-error TODO: misskey-js由来の型@simplewebauthn/typesとフロントエンド由来の型@github/webauthn-jsonが合わない
credential: credential.toJSON(),
credential: credential,
});
}
}
@@ -253,11 +249,8 @@ async function tryLogin(req: Partial<Misskey.entities.SigninFlowRequest>): Promi
break;
}
case 'passkey': {
if (webAuthnSupported()) {
credentialRequest.value = parseRequestOptionsFromJSON({
// @ts-expect-error TODO: misskey-js由来の型@simplewebauthn/typesとフロントエンド由来の型@github/webauthn-jsonが合わない
publicKey: res.authRequest,
});
if (browserSupportsWebAuthn()) {
credentialRequest.value = res.authRequest;
page.value = 'passkey';
} else {
page.value = 'totp';

View File

@@ -48,11 +48,11 @@ SPDX-License-Identifier: AGPL-3.0-only
{{ i18n.ts._2fa.securityKeyInfo }}
</MkInfo>
<MkInfo v-if="!webAuthnSupported()" warn>
<MkInfo v-if="!browserSupportsWebAuthn()" warn>
{{ i18n.ts._2fa.securityKeyNotSupported }}
</MkInfo>
<MkInfo v-else-if="webAuthnSupported() && !$i.twoFactorEnabled" warn>
<MkInfo v-else-if="browserSupportsWebAuthn() && !$i.twoFactorEnabled" warn>
{{ i18n.ts._2fa.registerTOTPBeforeKey }}
</MkInfo>
@@ -83,8 +83,8 @@ SPDX-License-Identifier: AGPL-3.0-only
</template>
<script lang="ts" setup>
import { defineAsyncComponent, computed } from 'vue';
import { supported as webAuthnSupported, create as webAuthnCreate, parseCreationOptionsFromJSON } from '@github/webauthn-json/browser-ponyfill';
import { computed } from 'vue';
import { browserSupportsWebAuthn, startRegistration } from '@simplewebauthn/browser';
import * as Misskey from 'misskey-js';
import MkButton from '@/components/MkButton.vue';
import MkInfo from '@/components/MkInfo.vue';
@@ -196,12 +196,9 @@ async function addSecurityKey() {
const auth = await os.authenticateDialog();
if (auth.canceled) return;
const registrationOptions = parseCreationOptionsFromJSON({
// @ts-expect-error misskey-js側に型がない
publicKey: await os.apiWithDialog('i/2fa/register-key', {
password: auth.result.password,
token: auth.result.token,
}),
const registrationOptions = await os.apiWithDialog('i/2fa/register-key', {
password: auth.result.password,
token: auth.result.token,
});
const name = await os.inputText({
@@ -214,7 +211,7 @@ async function addSecurityKey() {
if (name.canceled) return;
const credential = await os.promiseDialog(
webAuthnCreate(registrationOptions),
startRegistration({ optionsJSON: registrationOptions }),
null,
() => {}, // ユーザーのキャンセルはrejectなのでエラーダイアログを出さない
i18n.ts._2fa.tapSecurityKey,
@@ -228,8 +225,7 @@ async function addSecurityKey() {
password: auth.result.password,
token: auth.result.token,
name: name.result,
// @ts-expect-error misskey-js側に型がない
credential: credential.toJSON(),
credential: credential,
});
}