feat: 초기 프로젝트 설정 및 룰.md 파일 추가
This commit is contained in:
26
api.hyungi.net/node_modules/@simplewebauthn/server/script/authentication/generateAuthenticationOptions.d.ts
generated
vendored
Normal file
26
api.hyungi.net/node_modules/@simplewebauthn/server/script/authentication/generateAuthenticationOptions.d.ts
generated
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
import type { AuthenticationExtensionsClientInputs, AuthenticatorTransportFuture, Base64URLString, PublicKeyCredentialRequestOptionsJSON } from '../types/index.js';
|
||||
export type GenerateAuthenticationOptionsOpts = Parameters<typeof generateAuthenticationOptions>[0];
|
||||
/**
|
||||
* Prepare a value to pass into navigator.credentials.get(...) for authenticator authentication
|
||||
*
|
||||
* **Options:**
|
||||
*
|
||||
* @param rpID - Valid domain name (after `https://`)
|
||||
* @param allowCredentials **(Optional)** - Authenticators previously registered by the user, if any. If undefined the client will ask the user which credential they want to use
|
||||
* @param challenge **(Optional)** - Random value the authenticator needs to sign and pass back user for authentication. Defaults to generating a random value
|
||||
* @param timeout **(Optional)** - How long (in ms) the user can take to complete authentication. Defaults to `60000`
|
||||
* @param userVerification **(Optional)** - Set to `'discouraged'` when asserting as part of a 2FA flow, otherwise set to `'preferred'` or `'required'` as desired. Defaults to `"preferred"`
|
||||
* @param extensions **(Optional)** - Additional plugins the authenticator or browser should use during authentication
|
||||
*/
|
||||
export declare function generateAuthenticationOptions(options: {
|
||||
rpID: string;
|
||||
allowCredentials?: {
|
||||
id: Base64URLString;
|
||||
transports?: AuthenticatorTransportFuture[];
|
||||
}[];
|
||||
challenge?: string | Uint8Array;
|
||||
timeout?: number;
|
||||
userVerification?: 'required' | 'preferred' | 'discouraged';
|
||||
extensions?: AuthenticationExtensionsClientInputs;
|
||||
}): Promise<PublicKeyCredentialRequestOptionsJSON>;
|
||||
//# sourceMappingURL=generateAuthenticationOptions.d.ts.map
|
||||
1
api.hyungi.net/node_modules/@simplewebauthn/server/script/authentication/generateAuthenticationOptions.d.ts.map
generated
vendored
Normal file
1
api.hyungi.net/node_modules/@simplewebauthn/server/script/authentication/generateAuthenticationOptions.d.ts.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"generateAuthenticationOptions.d.ts","sourceRoot":"","sources":["../../src/authentication/generateAuthenticationOptions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,oCAAoC,EACpC,4BAA4B,EAC5B,eAAe,EACf,qCAAqC,EACtC,MAAM,mBAAmB,CAAC;AAI3B,MAAM,MAAM,iCAAiC,GAAG,UAAU,CAAC,OAAO,6BAA6B,CAAC,CAAC,CAAC,CAAC,CAAC;AAEpG;;;;;;;;;;;GAWG;AACH,wBAAsB,6BAA6B,CACjD,OAAO,EAAE;IACP,IAAI,EAAE,MAAM,CAAC;IACb,gBAAgB,CAAC,EAAE;QACjB,EAAE,EAAE,eAAe,CAAC;QACpB,UAAU,CAAC,EAAE,4BAA4B,EAAE,CAAC;KAC7C,EAAE,CAAC;IACJ,SAAS,CAAC,EAAE,MAAM,GAAG,UAAU,CAAC;IAChC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gBAAgB,CAAC,EAAE,UAAU,GAAG,WAAW,GAAG,aAAa,CAAC;IAC5D,UAAU,CAAC,EAAE,oCAAoC,CAAC;CACnD,GACA,OAAO,CAAC,qCAAqC,CAAC,CAoChD"}
|
||||
44
api.hyungi.net/node_modules/@simplewebauthn/server/script/authentication/generateAuthenticationOptions.js
generated
vendored
Normal file
44
api.hyungi.net/node_modules/@simplewebauthn/server/script/authentication/generateAuthenticationOptions.js
generated
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.generateAuthenticationOptions = generateAuthenticationOptions;
|
||||
const index_js_1 = require("../helpers/iso/index.js");
|
||||
const generateChallenge_js_1 = require("../helpers/generateChallenge.js");
|
||||
/**
|
||||
* Prepare a value to pass into navigator.credentials.get(...) for authenticator authentication
|
||||
*
|
||||
* **Options:**
|
||||
*
|
||||
* @param rpID - Valid domain name (after `https://`)
|
||||
* @param allowCredentials **(Optional)** - Authenticators previously registered by the user, if any. If undefined the client will ask the user which credential they want to use
|
||||
* @param challenge **(Optional)** - Random value the authenticator needs to sign and pass back user for authentication. Defaults to generating a random value
|
||||
* @param timeout **(Optional)** - How long (in ms) the user can take to complete authentication. Defaults to `60000`
|
||||
* @param userVerification **(Optional)** - Set to `'discouraged'` when asserting as part of a 2FA flow, otherwise set to `'preferred'` or `'required'` as desired. Defaults to `"preferred"`
|
||||
* @param extensions **(Optional)** - Additional plugins the authenticator or browser should use during authentication
|
||||
*/
|
||||
async function generateAuthenticationOptions(options) {
|
||||
const { allowCredentials, challenge = await (0, generateChallenge_js_1.generateChallenge)(), timeout = 60000, userVerification = 'preferred', extensions, rpID, } = options;
|
||||
/**
|
||||
* Preserve ability to specify `string` values for challenges
|
||||
*/
|
||||
let _challenge = challenge;
|
||||
if (typeof _challenge === 'string') {
|
||||
_challenge = index_js_1.isoUint8Array.fromUTF8String(_challenge);
|
||||
}
|
||||
return {
|
||||
rpId: rpID,
|
||||
challenge: index_js_1.isoBase64URL.fromBuffer(_challenge),
|
||||
allowCredentials: allowCredentials?.map((cred) => {
|
||||
if (!index_js_1.isoBase64URL.isBase64URL(cred.id)) {
|
||||
throw new Error(`excludeCredential id "${cred.id}" is not a valid base64url string`);
|
||||
}
|
||||
return {
|
||||
...cred,
|
||||
id: index_js_1.isoBase64URL.trimPadding(cred.id),
|
||||
type: 'public-key',
|
||||
};
|
||||
}),
|
||||
timeout,
|
||||
userVerification,
|
||||
extensions,
|
||||
};
|
||||
}
|
||||
67
api.hyungi.net/node_modules/@simplewebauthn/server/script/authentication/verifyAuthenticationResponse.d.ts
generated
vendored
Normal file
67
api.hyungi.net/node_modules/@simplewebauthn/server/script/authentication/verifyAuthenticationResponse.d.ts
generated
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
import type { AuthenticationResponseJSON, Base64URLString, CredentialDeviceType, UserVerificationRequirement, WebAuthnCredential } from '../types/index.js';
|
||||
import type { AuthenticationExtensionsAuthenticatorOutputs } from '../helpers/decodeAuthenticatorExtensions.js';
|
||||
/**
|
||||
* Configurable options when calling `verifyAuthenticationResponse()`
|
||||
*/
|
||||
export type VerifyAuthenticationResponseOpts = Parameters<typeof verifyAuthenticationResponse>[0];
|
||||
/**
|
||||
* Verify that the user has legitimately completed the authentication process
|
||||
*
|
||||
* **Options:**
|
||||
*
|
||||
* @param response - Response returned by **@simplewebauthn/browser**'s `startAssertion()`
|
||||
* @param expectedChallenge - The base64url-encoded `options.challenge` returned by `generateAuthenticationOptions()`
|
||||
* @param expectedOrigin - Website URL (or array of URLs) that the registration should have occurred on
|
||||
* @param expectedRPID - RP ID (or array of IDs) that was specified in the registration options
|
||||
* @param credential - An internal {@link WebAuthnCredential} corresponding to `id` in the authentication response
|
||||
* @param expectedType **(Optional)** - The response type expected ('webauthn.get')
|
||||
* @param requireUserVerification **(Optional)** - Enforce user verification by the authenticator (via PIN, fingerprint, etc...) Defaults to `true`
|
||||
* @param advancedFIDOConfig **(Optional)** - Options for satisfying more stringent FIDO RP feature requirements
|
||||
* @param advancedFIDOConfig.userVerification **(Optional)** - Enable alternative rules for evaluating the User Presence and User Verified flags in authenticator data: UV (and UP) flags are optional unless this value is `"required"`
|
||||
*/
|
||||
export declare function verifyAuthenticationResponse(options: {
|
||||
response: AuthenticationResponseJSON;
|
||||
expectedChallenge: string | ((challenge: string) => boolean | Promise<boolean>);
|
||||
expectedOrigin: string | string[];
|
||||
expectedRPID: string | string[];
|
||||
credential: WebAuthnCredential;
|
||||
expectedType?: string | string[];
|
||||
requireUserVerification?: boolean;
|
||||
advancedFIDOConfig?: {
|
||||
userVerification?: UserVerificationRequirement;
|
||||
};
|
||||
}): Promise<VerifiedAuthenticationResponse>;
|
||||
/**
|
||||
* Result of authentication verification
|
||||
*
|
||||
* @param verified If the authentication response could be verified
|
||||
* @param authenticationInfo.credentialID The ID of the authenticator used during authentication.
|
||||
* Should be used to identify which DB authenticator entry needs its `counter` updated to the value
|
||||
* below
|
||||
* @param authenticationInfo.newCounter The number of times the authenticator identified above
|
||||
* reported it has been used. **Should be kept in a DB for later reference to help prevent replay
|
||||
* attacks!**
|
||||
* @param authenticationInfo.credentialDeviceType Whether this is a single-device or multi-device
|
||||
* credential. **Should be kept in a DB for later reference!**
|
||||
* @param authenticationInfo.credentialBackedUp Whether or not the multi-device credential has been
|
||||
* backed up. Always `false` for single-device credentials. **Should be kept in a DB for later
|
||||
* reference!**
|
||||
* @param authenticationInfo.origin The origin of the website that the authentication occurred on
|
||||
* @param authenticationInfo.rpID The RP ID that the authentication occurred on
|
||||
* @param authenticationInfo?.authenticatorExtensionResults The authenticator extensions returned
|
||||
* by the browser
|
||||
*/
|
||||
export type VerifiedAuthenticationResponse = {
|
||||
verified: boolean;
|
||||
authenticationInfo: {
|
||||
credentialID: Base64URLString;
|
||||
newCounter: number;
|
||||
userVerified: boolean;
|
||||
credentialDeviceType: CredentialDeviceType;
|
||||
credentialBackedUp: boolean;
|
||||
origin: string;
|
||||
rpID: string;
|
||||
authenticatorExtensionResults?: AuthenticationExtensionsAuthenticatorOutputs;
|
||||
};
|
||||
};
|
||||
//# sourceMappingURL=verifyAuthenticationResponse.d.ts.map
|
||||
1
api.hyungi.net/node_modules/@simplewebauthn/server/script/authentication/verifyAuthenticationResponse.d.ts.map
generated
vendored
Normal file
1
api.hyungi.net/node_modules/@simplewebauthn/server/script/authentication/verifyAuthenticationResponse.d.ts.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"verifyAuthenticationResponse.d.ts","sourceRoot":"","sources":["../../src/authentication/verifyAuthenticationResponse.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,0BAA0B,EAC1B,eAAe,EACf,oBAAoB,EACpB,2BAA2B,EAC3B,kBAAkB,EACnB,MAAM,mBAAmB,CAAC;AAM3B,OAAO,KAAK,EAAE,4CAA4C,EAAE,MAAM,6CAA6C,CAAC;AAIhH;;GAEG;AACH,MAAM,MAAM,gCAAgC,GAAG,UAAU,CAAC,OAAO,4BAA4B,CAAC,CAAC,CAAC,CAAC,CAAC;AAElG;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,4BAA4B,CAChD,OAAO,EAAE;IACP,QAAQ,EAAE,0BAA0B,CAAC;IACrC,iBAAiB,EAAE,MAAM,GAAG,CAAC,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;IAChF,cAAc,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAClC,YAAY,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAChC,UAAU,EAAE,kBAAkB,CAAC;IAC/B,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IACjC,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAClC,kBAAkB,CAAC,EAAE;QACnB,gBAAgB,CAAC,EAAE,2BAA2B,CAAC;KAChD,CAAC;CACH,GACA,OAAO,CAAC,8BAA8B,CAAC,CAmNzC;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,MAAM,8BAA8B,GAAG;IAC3C,QAAQ,EAAE,OAAO,CAAC;IAClB,kBAAkB,EAAE;QAClB,YAAY,EAAE,eAAe,CAAC;QAC9B,UAAU,EAAE,MAAM,CAAC;QACnB,YAAY,EAAE,OAAO,CAAC;QACtB,oBAAoB,EAAE,oBAAoB,CAAC;QAC3C,kBAAkB,EAAE,OAAO,CAAC;QAC5B,MAAM,EAAE,MAAM,CAAC;QACf,IAAI,EAAE,MAAM,CAAC;QACb,6BAA6B,CAAC,EAAE,4CAA4C,CAAC;KAC9E,CAAC;CACH,CAAC"}
|
||||
174
api.hyungi.net/node_modules/@simplewebauthn/server/script/authentication/verifyAuthenticationResponse.js
generated
vendored
Normal file
174
api.hyungi.net/node_modules/@simplewebauthn/server/script/authentication/verifyAuthenticationResponse.js
generated
vendored
Normal file
@@ -0,0 +1,174 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.verifyAuthenticationResponse = verifyAuthenticationResponse;
|
||||
const decodeClientDataJSON_js_1 = require("../helpers/decodeClientDataJSON.js");
|
||||
const toHash_js_1 = require("../helpers/toHash.js");
|
||||
const verifySignature_js_1 = require("../helpers/verifySignature.js");
|
||||
const parseAuthenticatorData_js_1 = require("../helpers/parseAuthenticatorData.js");
|
||||
const parseBackupFlags_js_1 = require("../helpers/parseBackupFlags.js");
|
||||
const matchExpectedRPID_js_1 = require("../helpers/matchExpectedRPID.js");
|
||||
const index_js_1 = require("../helpers/iso/index.js");
|
||||
/**
|
||||
* Verify that the user has legitimately completed the authentication process
|
||||
*
|
||||
* **Options:**
|
||||
*
|
||||
* @param response - Response returned by **@simplewebauthn/browser**'s `startAssertion()`
|
||||
* @param expectedChallenge - The base64url-encoded `options.challenge` returned by `generateAuthenticationOptions()`
|
||||
* @param expectedOrigin - Website URL (or array of URLs) that the registration should have occurred on
|
||||
* @param expectedRPID - RP ID (or array of IDs) that was specified in the registration options
|
||||
* @param credential - An internal {@link WebAuthnCredential} corresponding to `id` in the authentication response
|
||||
* @param expectedType **(Optional)** - The response type expected ('webauthn.get')
|
||||
* @param requireUserVerification **(Optional)** - Enforce user verification by the authenticator (via PIN, fingerprint, etc...) Defaults to `true`
|
||||
* @param advancedFIDOConfig **(Optional)** - Options for satisfying more stringent FIDO RP feature requirements
|
||||
* @param advancedFIDOConfig.userVerification **(Optional)** - Enable alternative rules for evaluating the User Presence and User Verified flags in authenticator data: UV (and UP) flags are optional unless this value is `"required"`
|
||||
*/
|
||||
async function verifyAuthenticationResponse(options) {
|
||||
const { response, expectedChallenge, expectedOrigin, expectedRPID, expectedType, credential, requireUserVerification = true, advancedFIDOConfig, } = options;
|
||||
const { id, rawId, type: credentialType, response: assertionResponse } = response;
|
||||
// Ensure credential specified an ID
|
||||
if (!id) {
|
||||
throw new Error('Missing credential ID');
|
||||
}
|
||||
// Ensure ID is base64url-encoded
|
||||
if (id !== rawId) {
|
||||
throw new Error('Credential ID was not base64url-encoded');
|
||||
}
|
||||
// Make sure credential type is public-key
|
||||
if (credentialType !== 'public-key') {
|
||||
throw new Error(`Unexpected credential type ${credentialType}, expected "public-key"`);
|
||||
}
|
||||
if (!response) {
|
||||
throw new Error('Credential missing response');
|
||||
}
|
||||
if (typeof assertionResponse?.clientDataJSON !== 'string') {
|
||||
throw new Error('Credential response clientDataJSON was not a string');
|
||||
}
|
||||
const clientDataJSON = (0, decodeClientDataJSON_js_1.decodeClientDataJSON)(assertionResponse.clientDataJSON);
|
||||
const { type, origin, challenge, tokenBinding } = clientDataJSON;
|
||||
// Make sure we're handling an authentication
|
||||
if (Array.isArray(expectedType)) {
|
||||
if (!expectedType.includes(type)) {
|
||||
const joinedExpectedType = expectedType.join(', ');
|
||||
throw new Error(`Unexpected authentication response type "${type}", expected one of: ${joinedExpectedType}`);
|
||||
}
|
||||
}
|
||||
else if (expectedType) {
|
||||
if (type !== expectedType) {
|
||||
throw new Error(`Unexpected authentication response type "${type}", expected "${expectedType}"`);
|
||||
}
|
||||
}
|
||||
else if (type !== 'webauthn.get') {
|
||||
throw new Error(`Unexpected authentication response type: ${type}`);
|
||||
}
|
||||
// Ensure the device provided the challenge we gave it
|
||||
if (typeof expectedChallenge === 'function') {
|
||||
if (!(await expectedChallenge(challenge))) {
|
||||
throw new Error(`Custom challenge verifier returned false for registration response challenge "${challenge}"`);
|
||||
}
|
||||
}
|
||||
else if (challenge !== expectedChallenge) {
|
||||
throw new Error(`Unexpected authentication response challenge "${challenge}", expected "${expectedChallenge}"`);
|
||||
}
|
||||
// Check that the origin is our site
|
||||
if (Array.isArray(expectedOrigin)) {
|
||||
if (!expectedOrigin.includes(origin)) {
|
||||
const joinedExpectedOrigin = expectedOrigin.join(', ');
|
||||
throw new Error(`Unexpected authentication response origin "${origin}", expected one of: ${joinedExpectedOrigin}`);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (origin !== expectedOrigin) {
|
||||
throw new Error(`Unexpected authentication response origin "${origin}", expected "${expectedOrigin}"`);
|
||||
}
|
||||
}
|
||||
if (!index_js_1.isoBase64URL.isBase64URL(assertionResponse.authenticatorData)) {
|
||||
throw new Error('Credential response authenticatorData was not a base64url string');
|
||||
}
|
||||
if (!index_js_1.isoBase64URL.isBase64URL(assertionResponse.signature)) {
|
||||
throw new Error('Credential response signature was not a base64url string');
|
||||
}
|
||||
if (assertionResponse.userHandle &&
|
||||
typeof assertionResponse.userHandle !== 'string') {
|
||||
throw new Error('Credential response userHandle was not a string');
|
||||
}
|
||||
if (tokenBinding) {
|
||||
if (typeof tokenBinding !== 'object') {
|
||||
throw new Error('ClientDataJSON tokenBinding was not an object');
|
||||
}
|
||||
if (['present', 'supported', 'notSupported'].indexOf(tokenBinding.status) < 0) {
|
||||
throw new Error(`Unexpected tokenBinding status ${tokenBinding.status}`);
|
||||
}
|
||||
}
|
||||
const authDataBuffer = index_js_1.isoBase64URL.toBuffer(assertionResponse.authenticatorData);
|
||||
const parsedAuthData = (0, parseAuthenticatorData_js_1.parseAuthenticatorData)(authDataBuffer);
|
||||
const { rpIdHash, flags, counter, extensionsData } = parsedAuthData;
|
||||
// Make sure the response's RP ID is ours
|
||||
let expectedRPIDs = [];
|
||||
if (typeof expectedRPID === 'string') {
|
||||
expectedRPIDs = [expectedRPID];
|
||||
}
|
||||
else {
|
||||
expectedRPIDs = expectedRPID;
|
||||
}
|
||||
const matchedRPID = await (0, matchExpectedRPID_js_1.matchExpectedRPID)(rpIdHash, expectedRPIDs);
|
||||
if (advancedFIDOConfig !== undefined) {
|
||||
const { userVerification: fidoUserVerification } = advancedFIDOConfig;
|
||||
/**
|
||||
* Use FIDO Conformance-defined rules for verifying UP and UV flags
|
||||
*/
|
||||
if (fidoUserVerification === 'required') {
|
||||
// Require `flags.uv` be true (implies `flags.up` is true)
|
||||
if (!flags.uv) {
|
||||
throw new Error('User verification required, but user could not be verified');
|
||||
}
|
||||
}
|
||||
else if (fidoUserVerification === 'preferred' ||
|
||||
fidoUserVerification === 'discouraged') {
|
||||
// Ignore `flags.uv`
|
||||
}
|
||||
}
|
||||
else {
|
||||
/**
|
||||
* Use WebAuthn spec-defined rules for verifying UP and UV flags
|
||||
*/
|
||||
// WebAuthn only requires the user presence flag be true
|
||||
if (!flags.up) {
|
||||
throw new Error('User not present during authentication');
|
||||
}
|
||||
// Enforce user verification if required
|
||||
if (requireUserVerification && !flags.uv) {
|
||||
throw new Error('User verification required, but user could not be verified');
|
||||
}
|
||||
}
|
||||
const clientDataHash = await (0, toHash_js_1.toHash)(index_js_1.isoBase64URL.toBuffer(assertionResponse.clientDataJSON));
|
||||
const signatureBase = index_js_1.isoUint8Array.concat([authDataBuffer, clientDataHash]);
|
||||
const signature = index_js_1.isoBase64URL.toBuffer(assertionResponse.signature);
|
||||
if ((counter > 0 || credential.counter > 0) &&
|
||||
counter <= credential.counter) {
|
||||
// Error out when the counter in the DB is greater than or equal to the counter in the
|
||||
// dataStruct. It's related to how the authenticator maintains the number of times its been
|
||||
// used for this client. If this happens, then someone's somehow increased the counter
|
||||
// on the device without going through this site
|
||||
throw new Error(`Response counter value ${counter} was lower than expected ${credential.counter}`);
|
||||
}
|
||||
const { credentialDeviceType, credentialBackedUp } = (0, parseBackupFlags_js_1.parseBackupFlags)(flags);
|
||||
const toReturn = {
|
||||
verified: await (0, verifySignature_js_1.verifySignature)({
|
||||
signature,
|
||||
data: signatureBase,
|
||||
credentialPublicKey: credential.publicKey,
|
||||
}),
|
||||
authenticationInfo: {
|
||||
newCounter: counter,
|
||||
credentialID: credential.id,
|
||||
userVerified: flags.uv,
|
||||
credentialDeviceType,
|
||||
credentialBackedUp,
|
||||
authenticatorExtensionResults: extensionsData,
|
||||
origin: clientDataJSON.origin,
|
||||
rpID: matchedRPID,
|
||||
},
|
||||
};
|
||||
return toReturn;
|
||||
}
|
||||
Reference in New Issue
Block a user