diff options
author | Matthew Miller <matthew@millerti.me> | 2020-11-16 21:21:28 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-11-16 21:21:28 -0800 |
commit | 0f0a2d9b85ca549f3ebcb8cc4678085779dbf92c (patch) | |
tree | 8d03baba70c4969118647c361882c76443b114f9 | |
parent | 79b8188f5a7dab3dc70234e20216cd3b24267c9a (diff) | |
parent | 5a05e786ced984f9b41a791cfa7d734d7a5b21e5 (diff) |
Merge pull request #71 from MasterKale/feat/port-example-to-ts
feat/port-example-to-ts
-rw-r--r-- | example/example-server.d.ts | 39 | ||||
-rw-r--r-- | example/fido-conformance.ts (renamed from example/fido-conformance.js) | 54 | ||||
-rw-r--r-- | example/index.ts (renamed from example/index.js) | 76 | ||||
-rw-r--r-- | example/package-lock.json | 70 | ||||
-rw-r--r-- | example/package.json | 8 | ||||
-rw-r--r-- | example/tsconfig.json | 17 | ||||
-rw-r--r-- | package-lock.json | 99 | ||||
-rw-r--r-- | package.json | 3 |
8 files changed, 292 insertions, 74 deletions
diff --git a/example/example-server.d.ts b/example/example-server.d.ts new file mode 100644 index 0000000..6d1dfb8 --- /dev/null +++ b/example/example-server.d.ts @@ -0,0 +1,39 @@ +import type { AuthenticatorDevice } from '@simplewebauthn/typescript-types'; + +/** + * You'll need a database to store a few things: + * + * 1. Users + * + * You'll need to be able to associate attestation and assertions challenges, and authenticators to + * a specific user. See `LoggedInUser` below for an idea of the minimum amount of info you'll need to + * track for a specific user during these flows. + * + * 2. Challenges + * + * The totally-random-unique-every-time values you pass into every execution of + * `generateAttestationOptions()` or `generateAssertionOptions()` MUST be stored until + * `verifyAttestationResponse()` or `verifyAssertionResponse()` (respectively) is called to verify + * that the response contains the signed challenge. + * + * These values only need to be persisted for `timeout` number of milliseconds (see the `generate` + * methods and their optional `timeout` parameter) + * + * 3. Authenticator Devices + * + * After an attestation, you'll need to store three things about the authenticator: + * + * - Base64-encoded "Credential ID" (varchar) + * - Base64-encoded "Public Key" (varchar) + * - Counter (int) + * + * Each authenticator must also be associated to a user so that you can generate a list of + * authenticator credential IDs to pass into `generateAssertionOptions()`, from which one is + * expected to generate an assertion response. + */ +interface LoggedInUser { + id: string; + username: string; + devices: AuthenticatorDevice[]; + currentChallenge?: string; +} diff --git a/example/fido-conformance.js b/example/fido-conformance.ts index 9317a27..4b8e0c3 100644 --- a/example/fido-conformance.js +++ b/example/fido-conformance.ts @@ -1,32 +1,39 @@ /* eslint-disable @typescript-eslint/no-var-requires */ -const fs = require('fs'); -const express = require('express'); -const fetch = require('node-fetch'); +import fs from 'fs'; +import express from 'express'; +import fetch from 'node-fetch'; -const { +import { generateAttestationOptions, verifyAttestationResponse, generateAssertionOptions, verifyAssertionResponse, MetadataService, -} = require('@simplewebauthn/server'); +} from '@simplewebauthn/server'; +import { MetadataStatement } from '@simplewebauthn/server/dist/metadata/metadataService'; + +import { LoggedInUser } from './example-server'; + +interface LoggedInFIDOUser extends LoggedInUser { + currentAssertionUserVerification?: 'discouraged' | 'preferred' | 'required' | undefined; +} /** * Create paths specifically for testing with the FIDO Conformance Tools */ -const fidoConformanceRouter = express.Router(); +export const fidoConformanceRouter = express.Router(); +export const fidoRouteSuffix = '/fido'; const rpName = 'FIDO Conformance Test'; const rpID = 'localhost'; const origin = 'https://localhost'; -const fidoRouteSuffix = '/fido'; /** * Load JSON metadata statements provided by the Conformance Tools * * FIDO2 > TESTS CONFIGURATION > DOWNLOAD SERVER METADATA (button) */ -const statements = []; +const statements: MetadataStatement[] = []; try { // Update this to whatever folder you extracted the statements to @@ -53,7 +60,7 @@ fetch('https://mds.certinfra.fidoalliance.org/getEndpoints', { .then(resp => resp.json()) .then(json => { const routes = json.result; - const mdsServers = routes.map(url => ({ + const mdsServers = routes.map((url: string) => ({ url, rootCertURL: 'https://mds.certinfra.fidoalliance.org/pki/MDSROOT.crt', metadataURLSuffix: '', @@ -72,7 +79,7 @@ fetch('https://mds.certinfra.fidoalliance.org/getEndpoints', { console.log('🔐 FIDO Conformance routes ready'); }); -const inMemoryUserDeviceDB = { +const inMemoryUserDeviceDB: { [username: string]: LoggedInFIDOUser } = { // [username]: string: { // id: loggedInUserId, // username: 'user@yourdomain.com', @@ -90,7 +97,7 @@ const inMemoryUserDeviceDB = { // }, }; // A cheap way of remembering who's "logged in" between the request for options and the response -let loggedInUsername = undefined; +let loggedInUsername: string | undefined = undefined; /** * [FIDO2] Server Tests > MakeCredential Request @@ -146,7 +153,7 @@ fidoConformanceRouter.post('/attestation/options', (req, res) => { fidoConformanceRouter.post('/attestation/result', async (req, res) => { const { body } = req; - const user = inMemoryUserDeviceDB[loggedInUsername]; + const user = inMemoryUserDeviceDB[`${loggedInUsername}`]; const expectedChallenge = user.currentChallenge; @@ -154,7 +161,7 @@ fidoConformanceRouter.post('/attestation/result', async (req, res) => { try { verification = await verifyAttestationResponse({ credential: body, - expectedChallenge, + expectedChallenge: `${expectedChallenge}`, expectedOrigin: origin, }); } catch (error) { @@ -164,7 +171,7 @@ fidoConformanceRouter.post('/attestation/result', async (req, res) => { const { verified, authenticatorInfo } = verification; - if (verified) { + if (verified && authenticatorInfo) { const { base64PublicKey, base64CredentialID, counter } = authenticatorInfo; const existingDevice = user.devices.find(device => device.credentialID === base64CredentialID); @@ -196,7 +203,7 @@ fidoConformanceRouter.post('/assertion/options', (req, res) => { loggedInUsername = username; - let user = inMemoryUserDeviceDB[username]; + const user = inMemoryUserDeviceDB[username]; const { devices } = user; @@ -224,7 +231,7 @@ fidoConformanceRouter.post('/assertion/result', (req, res) => { const { body } = req; const { id } = body; - const user = inMemoryUserDeviceDB[loggedInUsername]; + const user = inMemoryUserDeviceDB[`${loggedInUsername}`]; // Pull up values specified when generation assertion options const expectedChallenge = user.currentChallenge; @@ -232,11 +239,15 @@ fidoConformanceRouter.post('/assertion/result', (req, res) => { const existingDevice = user.devices.find(device => device.credentialID === id); + if (!existingDevice) { + throw new Error(`Could not find device matching ${id}`); + } + let verification; try { verification = verifyAssertionResponse({ credential: body, - expectedChallenge, + expectedChallenge: `${expectedChallenge}`, expectedOrigin: origin, expectedRPID: rpID, authenticator: existingDevice, @@ -250,8 +261,8 @@ fidoConformanceRouter.post('/assertion/result', (req, res) => { const { verified, authenticatorInfo } = verification; if (verified) { - const { base64CredentialID, counter } = authenticatorInfo; - const existingDevice = user.devices.find(device => device.credentialID === base64CredentialID); + const { counter } = authenticatorInfo; + existingDevice.counter = counter; } @@ -272,8 +283,3 @@ fidoConformanceRouter.all('*', (req, res, next) => { next(); }); - -module.exports = { - fidoConformanceRouter, - fidoRouteSuffix, -}; diff --git a/example/index.js b/example/index.ts index 928eb64..b3ecd4d 100644 --- a/example/index.js +++ b/example/index.ts @@ -5,42 +5,52 @@ * The webpages served from ./public use @simplewebauthn/browser. */ -const https = require('https'); -const fs = require('fs'); +import https from 'https'; +import fs from 'fs'; -const express = require('express'); +import express from 'express'; +import dotenv from 'dotenv'; -const { +dotenv.config(); + +import { // Registration ("Attestation") generateAttestationOptions, verifyAttestationResponse, // Login ("Assertion") generateAssertionOptions, verifyAssertionResponse, -} = require('@simplewebauthn/server'); +} from '@simplewebauthn/server'; + +import { LoggedInUser } from './example-server'; const app = express(); const host = '0.0.0.0'; const port = 443; +const { ENABLE_CONFORMANCE } = process.env; + app.use(express.static('./public/')); app.use(express.json()); /** - * If the words "metadata statements" mean anything to you, you'll want to check out this file. It + * If the words "metadata statements" mean anything to you, you'll want to enable this route. It * contains an example of a more complex deployment of SimpleWebAuthn with support enabled for the * FIDO Metadata Service. This enables greater control over the types of authenticators that can * interact with the Rely Party (a.k.a. "RP", a.k.a. "this server"). */ -// const { fidoRouteSuffix, fidoConformanceRouter } = require('./fido-conformance'); -// app.use(fidoRouteSuffix, fidoConformanceRouter); +if (ENABLE_CONFORMANCE === 'true') { + import('./fido-conformance').then(({ fidoRouteSuffix, fidoConformanceRouter }) => { + app.use(fidoRouteSuffix, fidoConformanceRouter); + }); +} /** * RP ID represents the "scope" of websites on which a authenticator should be usable. The Origin * represents the expected URL from which an attestation or assertion occurs. */ const rpID = 'localhost'; -const origin = `https://${rpID}`; +const expectedOrigin = `https://${rpID}`; /** * 2FA and Passwordless WebAuthn flows expect you to be able to uniquely identify the user that * performs an attestation or assertion. The user ID you specify here should be your internal, @@ -51,37 +61,7 @@ const origin = `https://${rpID}`; */ const loggedInUserId = 'internalUserId'; -/** - * You'll need a database to store a few things: - * - * 1. Users - * - * You'll need to be able to associate attestation and assertions challenges, and authenticators to - * a specific user - * - * 2. Challenges - * - * The totally-random-unique-every-time values you pass into every execution of - * `generateAttestationOptions()` or `generateAssertionOptions()` MUST be stored until - * `verifyAttestationResponse()` or `verifyAssertionResponse()` (respectively) is called to verify - * that the response contains the signed challenge. - * - * These values only need to be persisted for `timeout` number of milliseconds (see the `generate` - * methods and their optional `timeout` parameter) - * - * 3. Authenticator Devices - * - * After an attestation, you'll need to store three things about the authenticator: - * - * - Base64-encoded "Credential ID" (varchar) - * - Base64-encoded "Public Key" (varchar) - * - Counter (int) - * - * Each authenticator must also be associated to a user so that you can generate a list of - * authenticator credential IDs to pass into `generateAssertionOptions()`, from which one is - * expected to generate an assertion response. - */ -const inMemoryUserDeviceDB = { +const inMemoryUserDeviceDB: { [loggedInUserId: string]: LoggedInUser } = { [loggedInUserId]: { id: loggedInUserId, username: `user@${rpID}`, @@ -165,8 +145,8 @@ app.post('/verify-attestation', async (req, res) => { try { verification = await verifyAttestationResponse({ credential: body, - expectedChallenge, - expectedOrigin: origin, + expectedChallenge: `${expectedChallenge}`, + expectedOrigin, expectedRPID: rpID, }); } catch (error) { @@ -176,7 +156,7 @@ app.post('/verify-attestation', async (req, res) => { const { verified, authenticatorInfo } = verification; - if (verified) { + if (verified && authenticatorInfo) { const { base64PublicKey, base64CredentialID, counter } = authenticatorInfo; const existingDevice = user.devices.find(device => device.credentialID === base64CredentialID); @@ -236,7 +216,7 @@ app.post('/verify-assertion', (req, res) => { let dbAuthenticator; // "Query the DB" here for an authenticator matching `credentialID` - for (let dev of user.devices) { + for (const dev of user.devices) { if (dev.credentialID === body.id) { dbAuthenticator = dev; break; @@ -244,15 +224,15 @@ app.post('/verify-assertion', (req, res) => { } if (!dbAuthenticator) { - throw new Error('could not find authenticator matching', body.id); + throw new Error(`could not find authenticator matching ${body.id}`); } let verification; try { verification = verifyAssertionResponse({ credential: body, - expectedChallenge, - expectedOrigin: origin, + expectedChallenge: `${expectedChallenge}`, + expectedOrigin, expectedRPID: rpID, authenticator: dbAuthenticator, }); @@ -283,5 +263,5 @@ https app, ) .listen(port, host, () => { - console.log(`🚀 Server ready at https://${host}:${port}`); + console.log(`🚀 Server ready at https://${rpID} (${host}:${port})`); }); diff --git a/example/package-lock.json b/example/package-lock.json index 2c5f201..8165712 100644 --- a/example/package-lock.json +++ b/example/package-lock.json @@ -171,6 +171,12 @@ "picomatch": "^2.0.4" } }, + "arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true + }, "array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", @@ -287,6 +293,12 @@ "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=" }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "dev": true + }, "bytes": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", @@ -506,6 +518,12 @@ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" }, + "diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true + }, "dot-prop": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.2.0.tgz", @@ -515,6 +533,11 @@ "is-obj": "^2.0.0" } }, + "dotenv": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.2.0.tgz", + "integrity": "sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw==" + }, "duplexer3": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", @@ -950,6 +973,12 @@ } } }, + "make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, "media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -1361,6 +1390,22 @@ "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", "dev": true }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "source-map-support": { + "version": "0.5.19", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", + "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, "statuses": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", @@ -1465,6 +1510,19 @@ "nopt": "~1.0.10" } }, + "ts-node": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-9.0.0.tgz", + "integrity": "sha512-/TqB4SnererCDR/vb4S/QvSZvzQMJN8daAslg7MeaiHvD8rDZsSfXmNeNumyZZzMned72Xoq/isQljYSt8Ynfg==", + "dev": true, + "requires": { + "arg": "^4.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "source-map-support": "^0.5.17", + "yn": "3.1.1" + } + }, "tslib": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz", @@ -1494,6 +1552,12 @@ "is-typedarray": "^1.0.0" } }, + "typescript": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.0.5.tgz", + "integrity": "sha512-ywmr/VrTVCmNTJ6iV2LwIrfG1P+lv6luD8sUJs+2eI9NLGigaN+nUQc13iHqisq7bra9lnmUSYqbJvegraBOPQ==", + "dev": true + }, "undefsafe": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.3.tgz", @@ -1589,6 +1653,12 @@ "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", "dev": true + }, + "yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true } } } diff --git a/example/package.json b/example/package.json index ae99dbb..3f76907 100644 --- a/example/package.json +++ b/example/package.json @@ -4,17 +4,21 @@ "description": "", "main": "index.js", "scripts": { - "start": "nodemon index.js" + "start": "nodemon index.ts", + "build": "tsc" }, "keywords": [], "author": "", "license": "ISC", "dependencies": { "@simplewebauthn/server": "0.10.3", + "dotenv": "^8.2.0", "express": "^4.17.1", "node-fetch": "^2.6.0" }, "devDependencies": { - "nodemon": "^2.0.4" + "nodemon": "^2.0.4", + "ts-node": "^9.0.0", + "typescript": "^4.0.5" } } diff --git a/example/tsconfig.json b/example/tsconfig.json new file mode 100644 index 0000000..8cdf351 --- /dev/null +++ b/example/tsconfig.json @@ -0,0 +1,17 @@ +{ + "compilerOptions": { + "target": "ES2018", + "lib": ["ES2018", "DOM"], + "module": "commonjs", + "esModuleInterop": true, + "declaration": true, + "sourceMap": true, + "allowSyntheticDefaultImports": true, + "strict": true, + "outDir": "dist" + }, + "exclude": [ + "node_modules", + "**/dist/*" + ] +} diff --git a/package-lock.json b/package-lock.json index 8cd8f9c..a726a74 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2363,6 +2363,12 @@ "@types/node": ">= 8" } }, + "@simplewebauthn/typescript-types": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/@simplewebauthn/typescript-types/-/typescript-types-0.10.0.tgz", + "integrity": "sha512-Pvg3I76o1YNt7FYOe5K3upsuLwR2Q6xSu6ofGrs/ltIFdTXI2JLCJzTvOIsnIXNSBWY4Wp3c9gizb8mn6Q6ntw==", + "dev": true + }, "@sinonjs/commons": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.0.tgz", @@ -2422,18 +2428,60 @@ "@babel/types": "^7.3.0" } }, + "@types/body-parser": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-W98JrE0j2K78swW4ukqMleo8R7h/pFETjM2DQ90MF6XK2i4LO4W3gQ71Lt4w3bfm2EvVSyWHplECvB5sK22yFQ==", + "dev": true, + "requires": { + "@types/connect": "*", + "@types/node": "*" + } + }, "@types/color-name": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==", "dev": true }, + "@types/connect": { + "version": "3.4.33", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.33.tgz", + "integrity": "sha512-2+FrkXY4zllzTNfJth7jOqEHC+enpLeGslEhpnTAkg21GkRrWV4SsAtqchtT4YS9/nODBU2/ZfsBY2X4J/dX7A==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, "@types/eslint-visitor-keys": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", "integrity": "sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag==", "dev": true }, + "@types/express": { + "version": "4.17.9", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.9.tgz", + "integrity": "sha512-SDzEIZInC4sivGIFY4Sz1GG6J9UObPwCInYJjko2jzOf/Imx/dlpume6Xxwj1ORL82tBbmN4cPDIDkLbWHk9hw==", + "dev": true, + "requires": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "*", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "@types/express-serve-static-core": { + "version": "4.17.13", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.13.tgz", + "integrity": "sha512-RgDi5a4nuzam073lRGKTUIaL3eF2+H7LJvJ8eUnCI0wA6SNjXc44DCmWNiTLs/AZ7QlsFWZiw/gTG3nSQGL0fA==", + "dev": true, + "requires": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*" + } + }, "@types/glob": { "version": "7.1.3", "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.3.tgz", @@ -2494,6 +2542,12 @@ "integrity": "sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw==", "dev": true }, + "@types/mime": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-2.0.3.tgz", + "integrity": "sha512-Jus9s4CDbqwocc5pOAnh8ShfrnMcPHuJYzVcSUU7lrh8Ni5HuIqX3oilL86p3dlTrk0LzHRCgA/GQ7uNCw6l2Q==", + "dev": true + }, "@types/minimatch": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", @@ -2512,6 +2566,29 @@ "integrity": "sha512-k3NqigXWRzQZVBDS5D1U70A5E8Qk4Kh+Ha/x4M8Bt9pF0X05eggfnC9+63Usc9Q928hRUIpIhTQaXsZwZBl4Ew==", "dev": true }, + "@types/node-fetch": { + "version": "2.5.7", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.5.7.tgz", + "integrity": "sha512-o2WVNf5UhWRkxlf6eq+jMZDu7kjgpgJfl4xVNlvryc95O/6F2ld8ztKX+qu+Rjyet93WAWm5LjeX9H5FGkODvw==", + "dev": true, + "requires": { + "@types/node": "*", + "form-data": "^3.0.0" + }, + "dependencies": { + "form-data": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.0.tgz", + "integrity": "sha512-CKMFDglpbMi6PyN+brwB9Q/GOw0eAnsrEZDgcsH5Krhz5Od/haKHAX0NmQfha2zPPz0JpWzA7GJHGSnvCRLWsg==", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + } + } + }, "@types/normalize-package-data": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz", @@ -2530,6 +2607,28 @@ "integrity": "sha512-5qOlnZscTn4xxM5MeGXAMOsIOIKIbh9e85zJWfBRVPlRMEVawzoPhINYbRGkBZCI8LxvBe7tJCdWiarA99OZfQ==", "dev": true }, + "@types/qs": { + "version": "6.9.5", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.5.tgz", + "integrity": "sha512-/JHkVHtx/REVG0VVToGRGH2+23hsYLHdyG+GrvoUGlGAd0ErauXDyvHtRI/7H7mzLm+tBCKA7pfcpkQ1lf58iQ==", + "dev": true + }, + "@types/range-parser": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.3.tgz", + "integrity": "sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA==", + "dev": true + }, + "@types/serve-static": { + "version": "1.13.7", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.7.tgz", + "integrity": "sha512-3diZWucbR+xTmbDlU+FRRxBf+31OhFew7cJXML/zh9NmvSPTNoFecAwHB66BUqFgENJtqMiyl7JAwUE/siqdLw==", + "dev": true, + "requires": { + "@types/mime": "*", + "@types/node": "*" + } + }, "@types/stack-utils": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-1.0.1.tgz", diff --git a/package.json b/package.json index 8e2fc70..62a8a12 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,10 @@ "build:server": "lerna bootstrap --scope=@simplewebauthn/server" }, "devDependencies": { + "@simplewebauthn/typescript-types": "^0.10.0", + "@types/express": "^4.17.9", "@types/jest": "^25.2.3", + "@types/node-fetch": "^2.5.7", "@typescript-eslint/eslint-plugin": "^3.10.1", "@typescript-eslint/parser": "^3.10.1", "eslint": "^7.8.1", |