@otplib/uri 13.2.0 → 13.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/metafile-cjs.json +1 -1
- package/dist/metafile-esm.json +1 -1
- package/package.json +4 -4
package/README.md
CHANGED
package/dist/index.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var l=Object.defineProperty;var T=Object.getOwnPropertyDescriptor;var w=Object.getOwnPropertyNames;var x=Object.prototype.hasOwnProperty;var U=(t,e)=>{for(var s in e)l(t,s,{get:e[s],enumerable:!0})},R=(t,e,s,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of w(e))!x.call(t,i)&&i!==s&&l(t,i,{get:()=>e[i],enumerable:!(r=T(e,i))||r.enumerable});return t};var A=t=>R(l({},"__esModule",{value:!0}),t);var D={};U(D,{InvalidParameterError:()=>p,InvalidURIError:()=>a,MissingParameterError:()=>g,URIParseError:()=>u,generate:()=>m,generateHOTP:()=>O,generateTOTP:()=>I,parse:()=>d,parseURI:()=>d});module.exports=A(D);var u=class extends Error{constructor(e){super(e),this.name="URIParseError"}},a=class extends u{constructor(e){super(`Invalid otpauth URI: ${e}`),this.name="InvalidURIError"}},g=class extends u{constructor(e){super(`Missing required parameter: ${e}`),this.name="MissingParameterError"}},p=class extends u{constructor(e,s){super(`Invalid value for parameter '${e}': ${s}`),this.name="InvalidParameterError"}};var P=2048,b=512,$=1024;function E(t,e){let s=t instanceof Error?t.message:String(t);return`Invalid URI encoding in ${e}: ${s}`}function h(t,e,s){if(t.length>e*3)throw new a(`${s} exceeds maximum length`);try{let r=decodeURIComponent(t);if(r.length>e)throw new a(`${s} exceeds maximum length of ${e} characters`);return r}catch(r){throw r instanceof a?r:new a(E(r,s))}}function d(t){if(t.length>P)throw new a(`URI exceeds maximum length of ${P} characters`);if(!t.startsWith("otpauth://"))throw new a(t);let e=t.slice(10),s=e.indexOf("/");if(s===-1)throw new a(t);let r=e.slice(0,s);if(r!=="hotp"&&r!=="totp")throw new p("type",r);let i=e.slice(s+1),o=i.indexOf("?"),n,c;o===-1?(n=h(i,b,"label"),c=""):(n=h(i.slice(0,o),b,"label"),c=i.slice(o+1));let f=H(c);if(!f.secret)throw new g("secret");return{type:r,label:n,params:f}}function H(t){let e={};if(!t)return e;let s=t.split("&");for(let r of s){let i=r.indexOf("=");if(i===-1)continue;let o=h(r.slice(0,i),64,"parameter key"),n=h(r.slice(i+1),$,`parameter '${o}'`);switch(o){case"secret":e.secret=n;break;case"issuer":e.issuer=n;break;case"algorithm":e.algorithm=M(n);break;case"digits":e.digits=k(n);break;case"counter":e.counter=y("counter",n,0);break;case"period":e.period=y("period",n,1);break}}return e}function y(t,e,s){if(!/^-?\d+$/.test(e))throw new p(t,e);let r=Number(e);if(!Number.isSafeInteger(r))throw new p(t,e);if(r<s)throw new p(t,e);return r}function M(t){let e=t.toLowerCase();if(e==="sha1"||e==="sha-1")return"sha1";if(e==="sha256"||e==="sha-256")return"sha256";if(e==="sha512"||e==="sha-512")return"sha512";throw new p("algorithm",t)}function k(t){if(!/^\d+$/.test(t))throw new p("digits",t);let e=Number(t);if(e===6||e===7||e===8)return e;throw new p("digits",t)}function m(t){let{type:e,label:s,params:r}=t,i=s.split(":").map(c=>encodeURIComponent(c)).join(":"),o=`otpauth://${e}/${i}?`,n=[];return r.secret&&n.push(`secret=${encodeURIComponent(r.secret)}`),r.issuer&&n.push(`issuer=${encodeURIComponent(r.issuer)}`),r.algorithm&&r.algorithm!=="sha1"&&n.push(`algorithm=${r.algorithm.toUpperCase()}`),r.digits&&r.digits!==6&&n.push(`digits=${r.digits}`),e==="hotp"&&r.counter!==void 0&&n.push(`counter=${r.counter}`),e==="totp"&&r.period!==void 0&&r.period!==30&&n.push(`period=${r.period}`),o+=n.join("&"),o}function I(t){let{issuer:e,label:s,secret:r,algorithm:i="sha1",digits:o=6,period:n=30}=t,c=e?`${e}:${s}`:s;return m({type:"totp",label:c,params:{secret:r,issuer:e,algorithm:i,digits:o,period:n}})}function O(t){let{issuer:e,label:s,secret:r,counter:i=0,algorithm:o="sha1",digits:n=6}=t,c=e?`${e}:${s}`:s;return m({type:"hotp",label:c,params:{secret:r,issuer:e,algorithm:o,digits:n,counter:i}})}0&&(module.exports={InvalidParameterError,InvalidURIError,MissingParameterError,URIParseError,generate,generateHOTP,generateTOTP,parse,parseURI});
|
|
2
2
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/types.ts","../src/parse.ts","../src/generate.ts"],"sourcesContent":["export { parse, parse as parseURI } from \"./parse.js\";\n\nexport { generate, generateTOTP, generateHOTP } from \"./generate.js\";\nexport type { URIOptions, TOTPURIOptions, HOTPURIOptions } from \"./generate.js\";\n\nexport {\n URIParseError,\n InvalidURIError,\n MissingParameterError,\n InvalidParameterError,\n} from \"./types.js\";\n\nexport type { OTPAuthURI, OTPAuthParams, OTPType } from \"./types.js\";\n","import type { HashAlgorithm, Digits } from \"@otplib/core\";\n\n/**\n * OTP type (HOTP or TOTP)\n */\nexport type OTPType = \"hotp\" | \"totp\";\n\n/**\n * otpauth:// URI parameters\n */\nexport type OTPAuthParams = {\n /**\n * Base32-encoded shared secret (required)\n */\n readonly secret: string;\n\n /**\n * Service/provider name (recommended)\n */\n readonly issuer?: string;\n\n /**\n * Hash algorithm (default: sha1)\n * Note: Google Authenticator only supports sha1\n */\n readonly algorithm?: HashAlgorithm;\n\n /**\n * Number of digits (default: 6)\n * Google Authenticator supports 6 or 8\n */\n readonly digits?: Digits;\n\n /**\n * Initial counter value for HOTP (default: 0)\n */\n readonly counter?: number;\n\n /**\n * Time step in seconds for TOTP (default: 30)\n */\n readonly period?: number;\n};\n\n/**\n * otpauth:// URI structure\n */\nexport type OTPAuthURI = {\n /**\n * Type of OTP (hotp or totp)\n */\n readonly type: OTPType;\n\n /**\n * The label (typically: issuer:account or account)\n */\n readonly label: string;\n\n /**\n * Parameters from the URI\n */\n readonly params: OTPAuthParams;\n};\n\n/**\n * Error thrown when URI parsing fails\n */\nexport class URIParseError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"URIParseError\";\n }\n}\n\n/**\n * Error thrown when URI is invalid\n */\nexport class InvalidURIError extends URIParseError {\n constructor(uri: string) {\n super(`Invalid otpauth URI: ${uri}`);\n this.name = \"InvalidURIError\";\n }\n}\n\n/**\n * Error thrown when URI has missing required parameters\n */\nexport class MissingParameterError extends URIParseError {\n constructor(param: string) {\n super(`Missing required parameter: ${param}`);\n this.name = \"MissingParameterError\";\n }\n}\n\n/**\n * Error thrown when URI has invalid parameter value\n */\nexport class InvalidParameterError extends URIParseError {\n constructor(param: string, value: string) {\n super(`Invalid value for parameter '${param}': ${value}`);\n this.name = \"InvalidParameterError\";\n }\n}\n","import { InvalidURIError, InvalidParameterError } from \"./types.js\";\n\nimport type { OTPAuthURI, OTPAuthParams } from \"./types.js\";\nimport type { HashAlgorithm, Digits } from \"@otplib/core\";\n\n// Security limits to prevent DoS attacks\nconst MAX_URI_LENGTH = 2048; // Standard URL length limit\nconst MAX_LABEL_LENGTH = 512;\nconst MAX_PARAM_VALUE_LENGTH = 1024;\n\n/**\n * Format error message for caught errors\n * @internal\n */\nexport function formatErrorMessage(error: unknown, context: string): string {\n const errorStr = error instanceof Error ? error.message : String(error);\n return `Invalid URI encoding in ${context}: ${errorStr}`;\n}\n\n/**\n * Safely decode a URI component with length validation and error handling\n * @throws {InvalidURIError} If decoding fails or length exceeds limit\n */\nfunction safeDecodeURIComponent(str: string, maxLength: number, context: string): string {\n if (str.length > maxLength * 3) {\n throw new InvalidURIError(`${context} exceeds maximum length`);\n }\n\n try {\n const decoded = decodeURIComponent(str);\n if (decoded.length > maxLength) {\n throw new InvalidURIError(`${context} exceeds maximum length of ${maxLength} characters`);\n }\n return decoded;\n } catch (error) {\n if (error instanceof InvalidURIError) {\n throw error;\n }\n throw new InvalidURIError(formatErrorMessage(error, context));\n }\n}\n\n/**\n * Parse an otpauth:// URI into its components\n *\n * @param uri - The otpauth:// URI to parse\n * @returns Parsed URI components\n * @throws {InvalidURIError} If URI is invalid\n * @throws {MissingParameterError} If required parameters are missing\n * @throws {InvalidParameterError} If parameter values are invalid\n *\n * @example\n * ```ts\n * import { parse } from '@otplib/uri';\n *\n * const uri = 'otpauth://totp/ACME:john@example.com?secret=JBSWY3DPEHPK3PXP&issuer=ACME';\n * const parsed = parse(uri);\n * // {\n * // type: 'totp',\n * // label: 'ACME:john@example.com',\n * // params: { secret: 'JBSWY3DPEHPK3PXP', issuer: 'ACME' }\n * // }\n * ```\n */\nexport function parse(uri: string): OTPAuthURI {\n if (uri.length > MAX_URI_LENGTH) {\n throw new InvalidURIError(`URI exceeds maximum length of ${MAX_URI_LENGTH} characters`);\n }\n\n if (!uri.startsWith(\"otpauth://\")) {\n throw new InvalidURIError(uri);\n }\n\n const withoutScheme = uri.slice(\"otpauth://\".length);\n const slashIndex = withoutScheme.indexOf(\"/\");\n\n if (slashIndex === -1) {\n throw new InvalidURIError(uri);\n }\n\n const type = withoutScheme.slice(0, slashIndex);\n if (type !== \"hotp\" && type !== \"totp\") {\n throw new InvalidParameterError(\"type\", type);\n }\n\n const remaining = withoutScheme.slice(slashIndex + 1);\n const queryIndex = remaining.indexOf(\"?\");\n\n let label: string;\n let queryString: string;\n\n if (queryIndex === -1) {\n label = safeDecodeURIComponent(remaining, MAX_LABEL_LENGTH, \"label\");\n queryString = \"\";\n } else {\n label = safeDecodeURIComponent(remaining.slice(0, queryIndex), MAX_LABEL_LENGTH, \"label\");\n queryString = remaining.slice(queryIndex + 1);\n }\n\n const params = parseQueryString(queryString);\n\n return {\n type,\n label,\n params,\n };\n}\n\n/**\n * Parse query string into parameters object\n */\nfunction parseQueryString(queryString: string): OTPAuthParams {\n // Use mutable type during construction\n const params: {\n secret?: string;\n issuer?: string;\n algorithm?: HashAlgorithm;\n digits?: Digits;\n counter?: number;\n period?: number;\n } = {};\n\n if (!queryString) {\n return params as OTPAuthParams;\n }\n\n const pairs = queryString.split(\"&\");\n for (const pair of pairs) {\n const equalIndex = pair.indexOf(\"=\");\n if (equalIndex === -1) {\n continue;\n }\n\n const key = safeDecodeURIComponent(pair.slice(0, equalIndex), 64, \"parameter key\");\n const value = safeDecodeURIComponent(\n pair.slice(equalIndex + 1),\n MAX_PARAM_VALUE_LENGTH,\n `parameter '${key}'`,\n );\n\n switch (key) {\n case \"secret\":\n params.secret = value;\n break;\n case \"issuer\":\n params.issuer = value;\n break;\n case \"algorithm\":\n params.algorithm = parseAlgorithm(value);\n break;\n case \"digits\":\n params.digits = parseDigits(value);\n break;\n case \"counter\":\n params.counter = parseInt(value, 10);\n break;\n case \"period\":\n params.period = parseInt(value, 10);\n break;\n }\n }\n\n return params as OTPAuthParams;\n}\n\n/**\n * Parse algorithm string\n */\nfunction parseAlgorithm(value: string): HashAlgorithm {\n const normalized = value.toLowerCase();\n if (normalized === \"sha1\" || normalized === \"sha-1\") {\n return \"sha1\";\n }\n if (normalized === \"sha256\" || normalized === \"sha-256\") {\n return \"sha256\";\n }\n if (normalized === \"sha512\" || normalized === \"sha-512\") {\n return \"sha512\";\n }\n throw new InvalidParameterError(\"algorithm\", value);\n}\n\n/**\n * Parse digits string\n */\nfunction parseDigits(value: string): Digits {\n const digits = parseInt(value, 10);\n if (digits === 6 || digits === 7 || digits === 8) {\n return digits;\n }\n throw new InvalidParameterError(\"digits\", value);\n}\n","import type { OTPAuthURI } from \"./types.js\";\nimport type { HashAlgorithm, Digits } from \"@otplib/core\";\n\n/**\n * Base options for URI generation\n */\nexport type URIOptions = {\n /**\n * Service/provider name (e.g., 'ACME Co', 'GitHub', 'AWS')\n */\n issuer?: string;\n\n /**\n * Account identifier (e.g., email, username)\n */\n label?: string;\n\n /**\n * Base32-encoded secret key\n */\n secret: string;\n\n /**\n * Hash algorithm (default: 'sha1')\n * Note: Google Authenticator only supports sha1\n */\n algorithm?: HashAlgorithm;\n\n /**\n * Number of digits (default: 6)\n * Google Authenticator supports 6 or 8, RFC also allows 7\n */\n digits?: Digits;\n\n /**\n * Time step in seconds for TOTP (default: 30)\n */\n period?: number;\n\n /**\n * Counter value for HOTP\n */\n counter?: number;\n};\n\n/**\n * TOTP-specific URI options\n */\nexport type TOTPURIOptions = URIOptions & {\n period?: number;\n counter?: never;\n};\n\n/**\n * HOTP-specific URI options\n */\nexport type HOTPURIOptions = URIOptions & {\n period?: never;\n counter?: number;\n};\n\n/**\n * Generate an otpauth:// URI\n *\n * @param uri - The URI components\n * @returns The otpauth:// URI string\n *\n * @example\n * ```ts\n * import { generate } from '@otplib/uri';\n * import { encode } from '@otplib/base32';\n *\n * const secret = encode(new Uint8Array([1, 2, 3, 4, 5]));\n *\n * const uri = generate({\n * type: 'totp',\n * label: 'ACME:john@example.com',\n * params: {\n * secret,\n * issuer: 'ACME',\n * algorithm: 'sha1',\n * digits: 6,\n * },\n * });\n * // Returns: 'otpauth://totp/ACME:john%40example.com?secret=...'\n * ```\n */\nexport function generate(uri: OTPAuthURI): string {\n const { type, label, params } = uri;\n\n // Encode label parts while preserving ':' as the issuer/account separator\n const encodedLabel = label\n .split(\":\")\n .map((part) => encodeURIComponent(part))\n .join(\":\");\n\n let result = `otpauth://${type}/${encodedLabel}?`;\n\n const queryParams: string[] = [];\n\n if (params.secret) {\n queryParams.push(`secret=${params.secret}`);\n }\n\n if (params.issuer) {\n queryParams.push(`issuer=${encodeURIComponent(params.issuer)}`);\n }\n\n if (params.algorithm && params.algorithm !== \"sha1\") {\n queryParams.push(`algorithm=${params.algorithm.toUpperCase()}`);\n }\n\n if (params.digits && params.digits !== 6) {\n queryParams.push(`digits=${params.digits}`);\n }\n\n if (type === \"hotp\" && params.counter !== undefined) {\n queryParams.push(`counter=${params.counter}`);\n }\n\n if (type === \"totp\" && params.period !== undefined && params.period !== 30) {\n queryParams.push(`period=${params.period}`);\n }\n\n result += queryParams.join(\"&\");\n\n return result;\n}\n\n/**\n * Generate a TOTP otpauth:// URI with simplified parameters\n *\n * @param options - TOTP URI generation options\n * @returns The otpauth:// URI string\n */\nexport function generateTOTP(options: TOTPURIOptions & { issuer: string; label: string }): string {\n const { issuer, label: account, secret, algorithm = \"sha1\", digits = 6, period = 30 } = options;\n\n const fullLabel = issuer ? `${issuer}:${account}` : account;\n\n return generate({\n type: \"totp\",\n label: fullLabel,\n params: {\n secret,\n issuer,\n algorithm,\n digits,\n period,\n },\n });\n}\n\n/**\n * Generate a HOTP otpauth:// URI with simplified parameters\n *\n * @param options - HOTP URI generation options\n * @returns The otpauth:// URI string\n */\nexport function generateHOTP(options: HOTPURIOptions & { issuer: string; label: string }): string {\n const { issuer, label: account, secret, counter = 0, algorithm = \"sha1\", digits = 6 } = options;\n\n const fullLabel = issuer ? `${issuer}:${account}` : account;\n\n return generate({\n type: \"hotp\",\n label: fullLabel,\n params: {\n secret,\n issuer,\n algorithm,\n digits,\n counter,\n },\n });\n}\n"],"mappings":"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","names":["index_exports","__export","InvalidParameterError","InvalidURIError","MissingParameterError","URIParseError","generate","generateHOTP","generateTOTP","parse","__toCommonJS","URIParseError","message","InvalidURIError","uri","MissingParameterError","param","InvalidParameterError","value","MAX_URI_LENGTH","MAX_LABEL_LENGTH","MAX_PARAM_VALUE_LENGTH","formatErrorMessage","error","context","errorStr","safeDecodeURIComponent","str","maxLength","InvalidURIError","decoded","parse","uri","withoutScheme","slashIndex","type","InvalidParameterError","remaining","queryIndex","label","queryString","params","parseQueryString","pairs","pair","equalIndex","key","value","parseAlgorithm","parseDigits","normalized","digits","generate","uri","type","label","params","encodedLabel","part","result","queryParams","generateTOTP","options","issuer","account","secret","algorithm","digits","period","fullLabel","generateHOTP","counter"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/types.ts","../src/parse.ts","../src/generate.ts"],"sourcesContent":["export { parse, parse as parseURI } from \"./parse.js\";\n\nexport { generate, generateTOTP, generateHOTP } from \"./generate.js\";\nexport type { URIOptions, TOTPURIOptions, HOTPURIOptions } from \"./generate.js\";\n\nexport {\n URIParseError,\n InvalidURIError,\n MissingParameterError,\n InvalidParameterError,\n} from \"./types.js\";\n\nexport type { OTPAuthURI, OTPAuthParams, OTPType } from \"./types.js\";\n","import type { HashAlgorithm, Digits } from \"@otplib/core\";\n\n/**\n * OTP type (HOTP or TOTP)\n */\nexport type OTPType = \"hotp\" | \"totp\";\n\n/**\n * otpauth:// URI parameters\n */\nexport type OTPAuthParams = {\n /**\n * Base32-encoded shared secret (required)\n */\n readonly secret: string;\n\n /**\n * Service/provider name (recommended)\n */\n readonly issuer?: string;\n\n /**\n * Hash algorithm (default: sha1)\n * Note: Google Authenticator only supports sha1\n */\n readonly algorithm?: HashAlgorithm;\n\n /**\n * Number of digits (default: 6)\n * Google Authenticator supports 6 or 8\n */\n readonly digits?: Digits;\n\n /**\n * Initial counter value for HOTP (default: 0)\n */\n readonly counter?: number;\n\n /**\n * Time step in seconds for TOTP (default: 30)\n */\n readonly period?: number;\n};\n\n/**\n * otpauth:// URI structure\n */\nexport type OTPAuthURI = {\n /**\n * Type of OTP (hotp or totp)\n */\n readonly type: OTPType;\n\n /**\n * The label (typically: issuer:account or account)\n */\n readonly label: string;\n\n /**\n * Parameters from the URI\n */\n readonly params: OTPAuthParams;\n};\n\n/**\n * Error thrown when URI parsing fails\n */\nexport class URIParseError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"URIParseError\";\n }\n}\n\n/**\n * Error thrown when URI is invalid\n */\nexport class InvalidURIError extends URIParseError {\n constructor(uri: string) {\n super(`Invalid otpauth URI: ${uri}`);\n this.name = \"InvalidURIError\";\n }\n}\n\n/**\n * Error thrown when URI has missing required parameters\n */\nexport class MissingParameterError extends URIParseError {\n constructor(param: string) {\n super(`Missing required parameter: ${param}`);\n this.name = \"MissingParameterError\";\n }\n}\n\n/**\n * Error thrown when URI has invalid parameter value\n */\nexport class InvalidParameterError extends URIParseError {\n constructor(param: string, value: string) {\n super(`Invalid value for parameter '${param}': ${value}`);\n this.name = \"InvalidParameterError\";\n }\n}\n","import { InvalidURIError, InvalidParameterError, MissingParameterError } from \"./types.js\";\n\nimport type { OTPAuthURI, OTPAuthParams } from \"./types.js\";\nimport type { HashAlgorithm, Digits } from \"@otplib/core\";\n\n// Security limits to prevent DoS attacks\nconst MAX_URI_LENGTH = 2048; // Standard URL length limit\nconst MAX_LABEL_LENGTH = 512;\nconst MAX_PARAM_VALUE_LENGTH = 1024;\n\ntype MutableOTPAuthParams = {\n secret?: string;\n issuer?: string;\n algorithm?: HashAlgorithm;\n digits?: Digits;\n counter?: number;\n period?: number;\n};\n\n/**\n * Format error message for caught errors\n * @internal\n */\nexport function formatErrorMessage(error: unknown, context: string): string {\n const errorStr = error instanceof Error ? error.message : String(error);\n return `Invalid URI encoding in ${context}: ${errorStr}`;\n}\n\n/**\n * Safely decode a URI component with length validation and error handling\n * @throws {InvalidURIError} If decoding fails or length exceeds limit\n */\nfunction safeDecodeURIComponent(str: string, maxLength: number, context: string): string {\n if (str.length > maxLength * 3) {\n throw new InvalidURIError(`${context} exceeds maximum length`);\n }\n\n try {\n const decoded = decodeURIComponent(str);\n if (decoded.length > maxLength) {\n throw new InvalidURIError(`${context} exceeds maximum length of ${maxLength} characters`);\n }\n return decoded;\n } catch (error) {\n if (error instanceof InvalidURIError) {\n throw error;\n }\n throw new InvalidURIError(formatErrorMessage(error, context));\n }\n}\n\n/**\n * Parse an otpauth:// URI into its components\n *\n * @param uri - The otpauth:// URI to parse\n * @returns Parsed URI components\n * @throws {InvalidURIError} If URI is invalid\n * @throws {MissingParameterError} If required parameters are missing\n * @throws {InvalidParameterError} If parameter values are invalid\n *\n * @example\n * ```ts\n * import { parse } from '@otplib/uri';\n *\n * const uri = 'otpauth://totp/ACME:john@example.com?secret=JBSWY3DPEHPK3PXP&issuer=ACME';\n * const parsed = parse(uri);\n * // {\n * // type: 'totp',\n * // label: 'ACME:john@example.com',\n * // params: { secret: 'JBSWY3DPEHPK3PXP', issuer: 'ACME' }\n * // }\n * ```\n */\nexport function parse(uri: string): OTPAuthURI {\n if (uri.length > MAX_URI_LENGTH) {\n throw new InvalidURIError(`URI exceeds maximum length of ${MAX_URI_LENGTH} characters`);\n }\n\n if (!uri.startsWith(\"otpauth://\")) {\n throw new InvalidURIError(uri);\n }\n\n const withoutScheme = uri.slice(\"otpauth://\".length);\n const slashIndex = withoutScheme.indexOf(\"/\");\n\n if (slashIndex === -1) {\n throw new InvalidURIError(uri);\n }\n\n const type = withoutScheme.slice(0, slashIndex);\n if (type !== \"hotp\" && type !== \"totp\") {\n throw new InvalidParameterError(\"type\", type);\n }\n\n const remaining = withoutScheme.slice(slashIndex + 1);\n const queryIndex = remaining.indexOf(\"?\");\n\n let label: string;\n let queryString: string;\n\n if (queryIndex === -1) {\n label = safeDecodeURIComponent(remaining, MAX_LABEL_LENGTH, \"label\");\n queryString = \"\";\n } else {\n label = safeDecodeURIComponent(remaining.slice(0, queryIndex), MAX_LABEL_LENGTH, \"label\");\n queryString = remaining.slice(queryIndex + 1);\n }\n\n const params = parseQueryString(queryString);\n\n if (!params.secret) {\n throw new MissingParameterError(\"secret\");\n }\n\n return {\n type,\n label,\n params: params as OTPAuthParams,\n };\n}\n\n/**\n * Parse query string into parameters object\n */\nfunction parseQueryString(queryString: string): MutableOTPAuthParams {\n const params: MutableOTPAuthParams = {};\n\n if (!queryString) {\n return params;\n }\n\n const pairs = queryString.split(\"&\");\n for (const pair of pairs) {\n const equalIndex = pair.indexOf(\"=\");\n if (equalIndex === -1) {\n continue;\n }\n\n const key = safeDecodeURIComponent(pair.slice(0, equalIndex), 64, \"parameter key\");\n const value = safeDecodeURIComponent(\n pair.slice(equalIndex + 1),\n MAX_PARAM_VALUE_LENGTH,\n `parameter '${key}'`,\n );\n\n switch (key) {\n case \"secret\":\n params.secret = value;\n break;\n case \"issuer\":\n params.issuer = value;\n break;\n case \"algorithm\":\n params.algorithm = parseAlgorithm(value);\n break;\n case \"digits\":\n params.digits = parseDigits(value);\n break;\n case \"counter\":\n params.counter = parseIntegerParameter(\"counter\", value, 0);\n break;\n case \"period\":\n params.period = parseIntegerParameter(\"period\", value, 1);\n break;\n }\n }\n\n return params;\n}\n\n/**\n * Parse an integer parameter with strict validation\n */\nfunction parseIntegerParameter(name: string, value: string, min: number): number {\n if (!/^-?\\d+$/.test(value)) {\n throw new InvalidParameterError(name, value);\n }\n\n const parsed = Number(value);\n if (!Number.isSafeInteger(parsed)) {\n throw new InvalidParameterError(name, value);\n }\n\n if (parsed < min) {\n throw new InvalidParameterError(name, value);\n }\n\n return parsed;\n}\n\n/**\n * Parse algorithm string\n */\nfunction parseAlgorithm(value: string): HashAlgorithm {\n const normalized = value.toLowerCase();\n if (normalized === \"sha1\" || normalized === \"sha-1\") {\n return \"sha1\";\n }\n if (normalized === \"sha256\" || normalized === \"sha-256\") {\n return \"sha256\";\n }\n if (normalized === \"sha512\" || normalized === \"sha-512\") {\n return \"sha512\";\n }\n throw new InvalidParameterError(\"algorithm\", value);\n}\n\n/**\n * Parse digits string\n */\nfunction parseDigits(value: string): Digits {\n if (!/^\\d+$/.test(value)) {\n throw new InvalidParameterError(\"digits\", value);\n }\n\n const digits = Number(value);\n if (digits === 6 || digits === 7 || digits === 8) {\n return digits;\n }\n throw new InvalidParameterError(\"digits\", value);\n}\n","import type { OTPAuthURI } from \"./types.js\";\nimport type { HashAlgorithm, Digits } from \"@otplib/core\";\n\n/**\n * Base options for URI generation\n */\nexport type URIOptions = {\n /**\n * Service/provider name (e.g., 'ACME Co', 'GitHub', 'AWS')\n */\n issuer?: string;\n\n /**\n * Account identifier (e.g., email, username)\n */\n label?: string;\n\n /**\n * Base32-encoded secret key\n */\n secret: string;\n\n /**\n * Hash algorithm (default: 'sha1')\n * Note: Google Authenticator only supports sha1\n */\n algorithm?: HashAlgorithm;\n\n /**\n * Number of digits (default: 6)\n * Google Authenticator supports 6 or 8, RFC also allows 7\n */\n digits?: Digits;\n\n /**\n * Time step in seconds for TOTP (default: 30)\n */\n period?: number;\n\n /**\n * Counter value for HOTP\n */\n counter?: number;\n};\n\n/**\n * TOTP-specific URI options\n */\nexport type TOTPURIOptions = URIOptions & {\n period?: number;\n counter?: never;\n};\n\n/**\n * HOTP-specific URI options\n */\nexport type HOTPURIOptions = URIOptions & {\n period?: never;\n counter?: number;\n};\n\n/**\n * Generate an otpauth:// URI\n *\n * @param uri - The URI components\n * @returns The otpauth:// URI string\n *\n * @example\n * ```ts\n * import { generate } from '@otplib/uri';\n * import { base32 } from '@otplib/plugin-base32-scure';\n *\n * const secret = base32.encode(new Uint8Array([1, 2, 3, 4, 5]));\n *\n * const uri = generate({\n * type: 'totp',\n * label: 'ACME:john@example.com',\n * params: {\n * secret,\n * issuer: 'ACME',\n * algorithm: 'sha1',\n * digits: 6,\n * },\n * });\n * // Returns: 'otpauth://totp/ACME:john%40example.com?secret=...'\n * ```\n */\nexport function generate(uri: OTPAuthURI): string {\n const { type, label, params } = uri;\n\n // Encode label parts while preserving ':' as the issuer/account separator\n const encodedLabel = label\n .split(\":\")\n .map((part) => encodeURIComponent(part))\n .join(\":\");\n\n let result = `otpauth://${type}/${encodedLabel}?`;\n\n const queryParams: string[] = [];\n\n if (params.secret) {\n queryParams.push(`secret=${encodeURIComponent(params.secret)}`);\n }\n\n if (params.issuer) {\n queryParams.push(`issuer=${encodeURIComponent(params.issuer)}`);\n }\n\n if (params.algorithm && params.algorithm !== \"sha1\") {\n queryParams.push(`algorithm=${params.algorithm.toUpperCase()}`);\n }\n\n if (params.digits && params.digits !== 6) {\n queryParams.push(`digits=${params.digits}`);\n }\n\n if (type === \"hotp\" && params.counter !== undefined) {\n queryParams.push(`counter=${params.counter}`);\n }\n\n if (type === \"totp\" && params.period !== undefined && params.period !== 30) {\n queryParams.push(`period=${params.period}`);\n }\n\n result += queryParams.join(\"&\");\n\n return result;\n}\n\n/**\n * Generate a TOTP otpauth:// URI with simplified parameters\n *\n * @param options - TOTP URI generation options\n * @returns The otpauth:// URI string\n */\nexport function generateTOTP(options: TOTPURIOptions & { issuer: string; label: string }): string {\n const { issuer, label: account, secret, algorithm = \"sha1\", digits = 6, period = 30 } = options;\n\n const fullLabel = issuer ? `${issuer}:${account}` : account;\n\n return generate({\n type: \"totp\",\n label: fullLabel,\n params: {\n secret,\n issuer,\n algorithm,\n digits,\n period,\n },\n });\n}\n\n/**\n * Generate a HOTP otpauth:// URI with simplified parameters\n *\n * @param options - HOTP URI generation options\n * @returns The otpauth:// URI string\n */\nexport function generateHOTP(options: HOTPURIOptions & { issuer: string; label: string }): string {\n const { issuer, label: account, secret, counter = 0, algorithm = \"sha1\", digits = 6 } = options;\n\n const fullLabel = issuer ? `${issuer}:${account}` : account;\n\n return generate({\n type: \"hotp\",\n label: fullLabel,\n params: {\n secret,\n issuer,\n algorithm,\n digits,\n counter,\n },\n });\n}\n"],"mappings":"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","names":["index_exports","__export","InvalidParameterError","InvalidURIError","MissingParameterError","URIParseError","generate","generateHOTP","generateTOTP","parse","__toCommonJS","URIParseError","message","InvalidURIError","uri","MissingParameterError","param","InvalidParameterError","value","MAX_URI_LENGTH","MAX_LABEL_LENGTH","MAX_PARAM_VALUE_LENGTH","formatErrorMessage","error","context","errorStr","safeDecodeURIComponent","str","maxLength","InvalidURIError","decoded","parse","uri","withoutScheme","slashIndex","type","InvalidParameterError","remaining","queryIndex","label","queryString","params","parseQueryString","MissingParameterError","pairs","pair","equalIndex","key","value","parseAlgorithm","parseDigits","parseIntegerParameter","name","min","parsed","normalized","digits","generate","uri","type","label","params","encodedLabel","part","result","queryParams","generateTOTP","options","issuer","account","secret","algorithm","digits","period","fullLabel","generateHOTP","counter"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -159,9 +159,9 @@ type HOTPURIOptions = URIOptions & {
|
|
|
159
159
|
* @example
|
|
160
160
|
* ```ts
|
|
161
161
|
* import { generate } from '@otplib/uri';
|
|
162
|
-
* import {
|
|
162
|
+
* import { base32 } from '@otplib/plugin-base32-scure';
|
|
163
163
|
*
|
|
164
|
-
* const secret = encode(new Uint8Array([1, 2, 3, 4, 5]));
|
|
164
|
+
* const secret = base32.encode(new Uint8Array([1, 2, 3, 4, 5]));
|
|
165
165
|
*
|
|
166
166
|
* const uri = generate({
|
|
167
167
|
* type: 'totp',
|
package/dist/index.d.ts
CHANGED
|
@@ -159,9 +159,9 @@ type HOTPURIOptions = URIOptions & {
|
|
|
159
159
|
* @example
|
|
160
160
|
* ```ts
|
|
161
161
|
* import { generate } from '@otplib/uri';
|
|
162
|
-
* import {
|
|
162
|
+
* import { base32 } from '@otplib/plugin-base32-scure';
|
|
163
163
|
*
|
|
164
|
-
* const secret = encode(new Uint8Array([1, 2, 3, 4, 5]));
|
|
164
|
+
* const secret = base32.encode(new Uint8Array([1, 2, 3, 4, 5]));
|
|
165
165
|
*
|
|
166
166
|
* const uri = generate({
|
|
167
167
|
* type: 'totp',
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var
|
|
1
|
+
var u=class extends Error{constructor(e){super(e),this.name="URIParseError"}},a=class extends u{constructor(e){super(`Invalid otpauth URI: ${e}`),this.name="InvalidURIError"}},g=class extends u{constructor(e){super(`Missing required parameter: ${e}`),this.name="MissingParameterError"}},p=class extends u{constructor(e,s){super(`Invalid value for parameter '${e}': ${s}`),this.name="InvalidParameterError"}};var d=2048,f=512,y=1024;function I(r,e){let s=r instanceof Error?r.message:String(r);return`Invalid URI encoding in ${e}: ${s}`}function h(r,e,s){if(r.length>e*3)throw new a(`${s} exceeds maximum length`);try{let t=decodeURIComponent(r);if(t.length>e)throw new a(`${s} exceeds maximum length of ${e} characters`);return t}catch(t){throw t instanceof a?t:new a(I(t,s))}}function b(r){if(r.length>d)throw new a(`URI exceeds maximum length of ${d} characters`);if(!r.startsWith("otpauth://"))throw new a(r);let e=r.slice(10),s=e.indexOf("/");if(s===-1)throw new a(r);let t=e.slice(0,s);if(t!=="hotp"&&t!=="totp")throw new p("type",t);let i=e.slice(s+1),o=i.indexOf("?"),n,c;o===-1?(n=h(i,f,"label"),c=""):(n=h(i.slice(0,o),f,"label"),c=i.slice(o+1));let l=O(c);if(!l.secret)throw new g("secret");return{type:t,label:n,params:l}}function O(r){let e={};if(!r)return e;let s=r.split("&");for(let t of s){let i=t.indexOf("=");if(i===-1)continue;let o=h(t.slice(0,i),64,"parameter key"),n=h(t.slice(i+1),y,`parameter '${o}'`);switch(o){case"secret":e.secret=n;break;case"issuer":e.issuer=n;break;case"algorithm":e.algorithm=T(n);break;case"digits":e.digits=w(n);break;case"counter":e.counter=P("counter",n,0);break;case"period":e.period=P("period",n,1);break}}return e}function P(r,e,s){if(!/^-?\d+$/.test(e))throw new p(r,e);let t=Number(e);if(!Number.isSafeInteger(t))throw new p(r,e);if(t<s)throw new p(r,e);return t}function T(r){let e=r.toLowerCase();if(e==="sha1"||e==="sha-1")return"sha1";if(e==="sha256"||e==="sha-256")return"sha256";if(e==="sha512"||e==="sha-512")return"sha512";throw new p("algorithm",r)}function w(r){if(!/^\d+$/.test(r))throw new p("digits",r);let e=Number(r);if(e===6||e===7||e===8)return e;throw new p("digits",r)}function m(r){let{type:e,label:s,params:t}=r,i=s.split(":").map(c=>encodeURIComponent(c)).join(":"),o=`otpauth://${e}/${i}?`,n=[];return t.secret&&n.push(`secret=${encodeURIComponent(t.secret)}`),t.issuer&&n.push(`issuer=${encodeURIComponent(t.issuer)}`),t.algorithm&&t.algorithm!=="sha1"&&n.push(`algorithm=${t.algorithm.toUpperCase()}`),t.digits&&t.digits!==6&&n.push(`digits=${t.digits}`),e==="hotp"&&t.counter!==void 0&&n.push(`counter=${t.counter}`),e==="totp"&&t.period!==void 0&&t.period!==30&&n.push(`period=${t.period}`),o+=n.join("&"),o}function x(r){let{issuer:e,label:s,secret:t,algorithm:i="sha1",digits:o=6,period:n=30}=r,c=e?`${e}:${s}`:s;return m({type:"totp",label:c,params:{secret:t,issuer:e,algorithm:i,digits:o,period:n}})}function U(r){let{issuer:e,label:s,secret:t,counter:i=0,algorithm:o="sha1",digits:n=6}=r,c=e?`${e}:${s}`:s;return m({type:"hotp",label:c,params:{secret:t,issuer:e,algorithm:o,digits:n,counter:i}})}export{p as InvalidParameterError,a as InvalidURIError,g as MissingParameterError,u as URIParseError,m as generate,U as generateHOTP,x as generateTOTP,b as parse,b as parseURI};
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/types.ts","../src/parse.ts","../src/generate.ts"],"sourcesContent":["import type { HashAlgorithm, Digits } from \"@otplib/core\";\n\n/**\n * OTP type (HOTP or TOTP)\n */\nexport type OTPType = \"hotp\" | \"totp\";\n\n/**\n * otpauth:// URI parameters\n */\nexport type OTPAuthParams = {\n /**\n * Base32-encoded shared secret (required)\n */\n readonly secret: string;\n\n /**\n * Service/provider name (recommended)\n */\n readonly issuer?: string;\n\n /**\n * Hash algorithm (default: sha1)\n * Note: Google Authenticator only supports sha1\n */\n readonly algorithm?: HashAlgorithm;\n\n /**\n * Number of digits (default: 6)\n * Google Authenticator supports 6 or 8\n */\n readonly digits?: Digits;\n\n /**\n * Initial counter value for HOTP (default: 0)\n */\n readonly counter?: number;\n\n /**\n * Time step in seconds for TOTP (default: 30)\n */\n readonly period?: number;\n};\n\n/**\n * otpauth:// URI structure\n */\nexport type OTPAuthURI = {\n /**\n * Type of OTP (hotp or totp)\n */\n readonly type: OTPType;\n\n /**\n * The label (typically: issuer:account or account)\n */\n readonly label: string;\n\n /**\n * Parameters from the URI\n */\n readonly params: OTPAuthParams;\n};\n\n/**\n * Error thrown when URI parsing fails\n */\nexport class URIParseError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"URIParseError\";\n }\n}\n\n/**\n * Error thrown when URI is invalid\n */\nexport class InvalidURIError extends URIParseError {\n constructor(uri: string) {\n super(`Invalid otpauth URI: ${uri}`);\n this.name = \"InvalidURIError\";\n }\n}\n\n/**\n * Error thrown when URI has missing required parameters\n */\nexport class MissingParameterError extends URIParseError {\n constructor(param: string) {\n super(`Missing required parameter: ${param}`);\n this.name = \"MissingParameterError\";\n }\n}\n\n/**\n * Error thrown when URI has invalid parameter value\n */\nexport class InvalidParameterError extends URIParseError {\n constructor(param: string, value: string) {\n super(`Invalid value for parameter '${param}': ${value}`);\n this.name = \"InvalidParameterError\";\n }\n}\n","import { InvalidURIError, InvalidParameterError } from \"./types.js\";\n\nimport type { OTPAuthURI, OTPAuthParams } from \"./types.js\";\nimport type { HashAlgorithm, Digits } from \"@otplib/core\";\n\n// Security limits to prevent DoS attacks\nconst MAX_URI_LENGTH = 2048; // Standard URL length limit\nconst MAX_LABEL_LENGTH = 512;\nconst MAX_PARAM_VALUE_LENGTH = 1024;\n\n/**\n * Format error message for caught errors\n * @internal\n */\nexport function formatErrorMessage(error: unknown, context: string): string {\n const errorStr = error instanceof Error ? error.message : String(error);\n return `Invalid URI encoding in ${context}: ${errorStr}`;\n}\n\n/**\n * Safely decode a URI component with length validation and error handling\n * @throws {InvalidURIError} If decoding fails or length exceeds limit\n */\nfunction safeDecodeURIComponent(str: string, maxLength: number, context: string): string {\n if (str.length > maxLength * 3) {\n throw new InvalidURIError(`${context} exceeds maximum length`);\n }\n\n try {\n const decoded = decodeURIComponent(str);\n if (decoded.length > maxLength) {\n throw new InvalidURIError(`${context} exceeds maximum length of ${maxLength} characters`);\n }\n return decoded;\n } catch (error) {\n if (error instanceof InvalidURIError) {\n throw error;\n }\n throw new InvalidURIError(formatErrorMessage(error, context));\n }\n}\n\n/**\n * Parse an otpauth:// URI into its components\n *\n * @param uri - The otpauth:// URI to parse\n * @returns Parsed URI components\n * @throws {InvalidURIError} If URI is invalid\n * @throws {MissingParameterError} If required parameters are missing\n * @throws {InvalidParameterError} If parameter values are invalid\n *\n * @example\n * ```ts\n * import { parse } from '@otplib/uri';\n *\n * const uri = 'otpauth://totp/ACME:john@example.com?secret=JBSWY3DPEHPK3PXP&issuer=ACME';\n * const parsed = parse(uri);\n * // {\n * // type: 'totp',\n * // label: 'ACME:john@example.com',\n * // params: { secret: 'JBSWY3DPEHPK3PXP', issuer: 'ACME' }\n * // }\n * ```\n */\nexport function parse(uri: string): OTPAuthURI {\n if (uri.length > MAX_URI_LENGTH) {\n throw new InvalidURIError(`URI exceeds maximum length of ${MAX_URI_LENGTH} characters`);\n }\n\n if (!uri.startsWith(\"otpauth://\")) {\n throw new InvalidURIError(uri);\n }\n\n const withoutScheme = uri.slice(\"otpauth://\".length);\n const slashIndex = withoutScheme.indexOf(\"/\");\n\n if (slashIndex === -1) {\n throw new InvalidURIError(uri);\n }\n\n const type = withoutScheme.slice(0, slashIndex);\n if (type !== \"hotp\" && type !== \"totp\") {\n throw new InvalidParameterError(\"type\", type);\n }\n\n const remaining = withoutScheme.slice(slashIndex + 1);\n const queryIndex = remaining.indexOf(\"?\");\n\n let label: string;\n let queryString: string;\n\n if (queryIndex === -1) {\n label = safeDecodeURIComponent(remaining, MAX_LABEL_LENGTH, \"label\");\n queryString = \"\";\n } else {\n label = safeDecodeURIComponent(remaining.slice(0, queryIndex), MAX_LABEL_LENGTH, \"label\");\n queryString = remaining.slice(queryIndex + 1);\n }\n\n const params = parseQueryString(queryString);\n\n return {\n type,\n label,\n params,\n };\n}\n\n/**\n * Parse query string into parameters object\n */\nfunction parseQueryString(queryString: string): OTPAuthParams {\n // Use mutable type during construction\n const params: {\n secret?: string;\n issuer?: string;\n algorithm?: HashAlgorithm;\n digits?: Digits;\n counter?: number;\n period?: number;\n } = {};\n\n if (!queryString) {\n return params as OTPAuthParams;\n }\n\n const pairs = queryString.split(\"&\");\n for (const pair of pairs) {\n const equalIndex = pair.indexOf(\"=\");\n if (equalIndex === -1) {\n continue;\n }\n\n const key = safeDecodeURIComponent(pair.slice(0, equalIndex), 64, \"parameter key\");\n const value = safeDecodeURIComponent(\n pair.slice(equalIndex + 1),\n MAX_PARAM_VALUE_LENGTH,\n `parameter '${key}'`,\n );\n\n switch (key) {\n case \"secret\":\n params.secret = value;\n break;\n case \"issuer\":\n params.issuer = value;\n break;\n case \"algorithm\":\n params.algorithm = parseAlgorithm(value);\n break;\n case \"digits\":\n params.digits = parseDigits(value);\n break;\n case \"counter\":\n params.counter = parseInt(value, 10);\n break;\n case \"period\":\n params.period = parseInt(value, 10);\n break;\n }\n }\n\n return params as OTPAuthParams;\n}\n\n/**\n * Parse algorithm string\n */\nfunction parseAlgorithm(value: string): HashAlgorithm {\n const normalized = value.toLowerCase();\n if (normalized === \"sha1\" || normalized === \"sha-1\") {\n return \"sha1\";\n }\n if (normalized === \"sha256\" || normalized === \"sha-256\") {\n return \"sha256\";\n }\n if (normalized === \"sha512\" || normalized === \"sha-512\") {\n return \"sha512\";\n }\n throw new InvalidParameterError(\"algorithm\", value);\n}\n\n/**\n * Parse digits string\n */\nfunction parseDigits(value: string): Digits {\n const digits = parseInt(value, 10);\n if (digits === 6 || digits === 7 || digits === 8) {\n return digits;\n }\n throw new InvalidParameterError(\"digits\", value);\n}\n","import type { OTPAuthURI } from \"./types.js\";\nimport type { HashAlgorithm, Digits } from \"@otplib/core\";\n\n/**\n * Base options for URI generation\n */\nexport type URIOptions = {\n /**\n * Service/provider name (e.g., 'ACME Co', 'GitHub', 'AWS')\n */\n issuer?: string;\n\n /**\n * Account identifier (e.g., email, username)\n */\n label?: string;\n\n /**\n * Base32-encoded secret key\n */\n secret: string;\n\n /**\n * Hash algorithm (default: 'sha1')\n * Note: Google Authenticator only supports sha1\n */\n algorithm?: HashAlgorithm;\n\n /**\n * Number of digits (default: 6)\n * Google Authenticator supports 6 or 8, RFC also allows 7\n */\n digits?: Digits;\n\n /**\n * Time step in seconds for TOTP (default: 30)\n */\n period?: number;\n\n /**\n * Counter value for HOTP\n */\n counter?: number;\n};\n\n/**\n * TOTP-specific URI options\n */\nexport type TOTPURIOptions = URIOptions & {\n period?: number;\n counter?: never;\n};\n\n/**\n * HOTP-specific URI options\n */\nexport type HOTPURIOptions = URIOptions & {\n period?: never;\n counter?: number;\n};\n\n/**\n * Generate an otpauth:// URI\n *\n * @param uri - The URI components\n * @returns The otpauth:// URI string\n *\n * @example\n * ```ts\n * import { generate } from '@otplib/uri';\n * import { encode } from '@otplib/base32';\n *\n * const secret = encode(new Uint8Array([1, 2, 3, 4, 5]));\n *\n * const uri = generate({\n * type: 'totp',\n * label: 'ACME:john@example.com',\n * params: {\n * secret,\n * issuer: 'ACME',\n * algorithm: 'sha1',\n * digits: 6,\n * },\n * });\n * // Returns: 'otpauth://totp/ACME:john%40example.com?secret=...'\n * ```\n */\nexport function generate(uri: OTPAuthURI): string {\n const { type, label, params } = uri;\n\n // Encode label parts while preserving ':' as the issuer/account separator\n const encodedLabel = label\n .split(\":\")\n .map((part) => encodeURIComponent(part))\n .join(\":\");\n\n let result = `otpauth://${type}/${encodedLabel}?`;\n\n const queryParams: string[] = [];\n\n if (params.secret) {\n queryParams.push(`secret=${params.secret}`);\n }\n\n if (params.issuer) {\n queryParams.push(`issuer=${encodeURIComponent(params.issuer)}`);\n }\n\n if (params.algorithm && params.algorithm !== \"sha1\") {\n queryParams.push(`algorithm=${params.algorithm.toUpperCase()}`);\n }\n\n if (params.digits && params.digits !== 6) {\n queryParams.push(`digits=${params.digits}`);\n }\n\n if (type === \"hotp\" && params.counter !== undefined) {\n queryParams.push(`counter=${params.counter}`);\n }\n\n if (type === \"totp\" && params.period !== undefined && params.period !== 30) {\n queryParams.push(`period=${params.period}`);\n }\n\n result += queryParams.join(\"&\");\n\n return result;\n}\n\n/**\n * Generate a TOTP otpauth:// URI with simplified parameters\n *\n * @param options - TOTP URI generation options\n * @returns The otpauth:// URI string\n */\nexport function generateTOTP(options: TOTPURIOptions & { issuer: string; label: string }): string {\n const { issuer, label: account, secret, algorithm = \"sha1\", digits = 6, period = 30 } = options;\n\n const fullLabel = issuer ? `${issuer}:${account}` : account;\n\n return generate({\n type: \"totp\",\n label: fullLabel,\n params: {\n secret,\n issuer,\n algorithm,\n digits,\n period,\n },\n });\n}\n\n/**\n * Generate a HOTP otpauth:// URI with simplified parameters\n *\n * @param options - HOTP URI generation options\n * @returns The otpauth:// URI string\n */\nexport function generateHOTP(options: HOTPURIOptions & { issuer: string; label: string }): string {\n const { issuer, label: account, secret, counter = 0, algorithm = \"sha1\", digits = 6 } = options;\n\n const fullLabel = issuer ? `${issuer}:${account}` : account;\n\n return generate({\n type: \"hotp\",\n label: fullLabel,\n params: {\n secret,\n issuer,\n algorithm,\n digits,\n counter,\n },\n });\n}\n"],"mappings":"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","names":["URIParseError","message","InvalidURIError","uri","MissingParameterError","param","InvalidParameterError","value","MAX_URI_LENGTH","MAX_LABEL_LENGTH","MAX_PARAM_VALUE_LENGTH","formatErrorMessage","error","context","errorStr","safeDecodeURIComponent","str","maxLength","InvalidURIError","decoded","parse","uri","withoutScheme","slashIndex","type","InvalidParameterError","remaining","queryIndex","label","queryString","params","parseQueryString","pairs","pair","equalIndex","key","value","parseAlgorithm","parseDigits","normalized","digits","generate","uri","type","label","params","encodedLabel","part","result","queryParams","generateTOTP","options","issuer","account","secret","algorithm","digits","period","fullLabel","generateHOTP","counter"]}
|
|
1
|
+
{"version":3,"sources":["../src/types.ts","../src/parse.ts","../src/generate.ts"],"sourcesContent":["import type { HashAlgorithm, Digits } from \"@otplib/core\";\n\n/**\n * OTP type (HOTP or TOTP)\n */\nexport type OTPType = \"hotp\" | \"totp\";\n\n/**\n * otpauth:// URI parameters\n */\nexport type OTPAuthParams = {\n /**\n * Base32-encoded shared secret (required)\n */\n readonly secret: string;\n\n /**\n * Service/provider name (recommended)\n */\n readonly issuer?: string;\n\n /**\n * Hash algorithm (default: sha1)\n * Note: Google Authenticator only supports sha1\n */\n readonly algorithm?: HashAlgorithm;\n\n /**\n * Number of digits (default: 6)\n * Google Authenticator supports 6 or 8\n */\n readonly digits?: Digits;\n\n /**\n * Initial counter value for HOTP (default: 0)\n */\n readonly counter?: number;\n\n /**\n * Time step in seconds for TOTP (default: 30)\n */\n readonly period?: number;\n};\n\n/**\n * otpauth:// URI structure\n */\nexport type OTPAuthURI = {\n /**\n * Type of OTP (hotp or totp)\n */\n readonly type: OTPType;\n\n /**\n * The label (typically: issuer:account or account)\n */\n readonly label: string;\n\n /**\n * Parameters from the URI\n */\n readonly params: OTPAuthParams;\n};\n\n/**\n * Error thrown when URI parsing fails\n */\nexport class URIParseError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"URIParseError\";\n }\n}\n\n/**\n * Error thrown when URI is invalid\n */\nexport class InvalidURIError extends URIParseError {\n constructor(uri: string) {\n super(`Invalid otpauth URI: ${uri}`);\n this.name = \"InvalidURIError\";\n }\n}\n\n/**\n * Error thrown when URI has missing required parameters\n */\nexport class MissingParameterError extends URIParseError {\n constructor(param: string) {\n super(`Missing required parameter: ${param}`);\n this.name = \"MissingParameterError\";\n }\n}\n\n/**\n * Error thrown when URI has invalid parameter value\n */\nexport class InvalidParameterError extends URIParseError {\n constructor(param: string, value: string) {\n super(`Invalid value for parameter '${param}': ${value}`);\n this.name = \"InvalidParameterError\";\n }\n}\n","import { InvalidURIError, InvalidParameterError, MissingParameterError } from \"./types.js\";\n\nimport type { OTPAuthURI, OTPAuthParams } from \"./types.js\";\nimport type { HashAlgorithm, Digits } from \"@otplib/core\";\n\n// Security limits to prevent DoS attacks\nconst MAX_URI_LENGTH = 2048; // Standard URL length limit\nconst MAX_LABEL_LENGTH = 512;\nconst MAX_PARAM_VALUE_LENGTH = 1024;\n\ntype MutableOTPAuthParams = {\n secret?: string;\n issuer?: string;\n algorithm?: HashAlgorithm;\n digits?: Digits;\n counter?: number;\n period?: number;\n};\n\n/**\n * Format error message for caught errors\n * @internal\n */\nexport function formatErrorMessage(error: unknown, context: string): string {\n const errorStr = error instanceof Error ? error.message : String(error);\n return `Invalid URI encoding in ${context}: ${errorStr}`;\n}\n\n/**\n * Safely decode a URI component with length validation and error handling\n * @throws {InvalidURIError} If decoding fails or length exceeds limit\n */\nfunction safeDecodeURIComponent(str: string, maxLength: number, context: string): string {\n if (str.length > maxLength * 3) {\n throw new InvalidURIError(`${context} exceeds maximum length`);\n }\n\n try {\n const decoded = decodeURIComponent(str);\n if (decoded.length > maxLength) {\n throw new InvalidURIError(`${context} exceeds maximum length of ${maxLength} characters`);\n }\n return decoded;\n } catch (error) {\n if (error instanceof InvalidURIError) {\n throw error;\n }\n throw new InvalidURIError(formatErrorMessage(error, context));\n }\n}\n\n/**\n * Parse an otpauth:// URI into its components\n *\n * @param uri - The otpauth:// URI to parse\n * @returns Parsed URI components\n * @throws {InvalidURIError} If URI is invalid\n * @throws {MissingParameterError} If required parameters are missing\n * @throws {InvalidParameterError} If parameter values are invalid\n *\n * @example\n * ```ts\n * import { parse } from '@otplib/uri';\n *\n * const uri = 'otpauth://totp/ACME:john@example.com?secret=JBSWY3DPEHPK3PXP&issuer=ACME';\n * const parsed = parse(uri);\n * // {\n * // type: 'totp',\n * // label: 'ACME:john@example.com',\n * // params: { secret: 'JBSWY3DPEHPK3PXP', issuer: 'ACME' }\n * // }\n * ```\n */\nexport function parse(uri: string): OTPAuthURI {\n if (uri.length > MAX_URI_LENGTH) {\n throw new InvalidURIError(`URI exceeds maximum length of ${MAX_URI_LENGTH} characters`);\n }\n\n if (!uri.startsWith(\"otpauth://\")) {\n throw new InvalidURIError(uri);\n }\n\n const withoutScheme = uri.slice(\"otpauth://\".length);\n const slashIndex = withoutScheme.indexOf(\"/\");\n\n if (slashIndex === -1) {\n throw new InvalidURIError(uri);\n }\n\n const type = withoutScheme.slice(0, slashIndex);\n if (type !== \"hotp\" && type !== \"totp\") {\n throw new InvalidParameterError(\"type\", type);\n }\n\n const remaining = withoutScheme.slice(slashIndex + 1);\n const queryIndex = remaining.indexOf(\"?\");\n\n let label: string;\n let queryString: string;\n\n if (queryIndex === -1) {\n label = safeDecodeURIComponent(remaining, MAX_LABEL_LENGTH, \"label\");\n queryString = \"\";\n } else {\n label = safeDecodeURIComponent(remaining.slice(0, queryIndex), MAX_LABEL_LENGTH, \"label\");\n queryString = remaining.slice(queryIndex + 1);\n }\n\n const params = parseQueryString(queryString);\n\n if (!params.secret) {\n throw new MissingParameterError(\"secret\");\n }\n\n return {\n type,\n label,\n params: params as OTPAuthParams,\n };\n}\n\n/**\n * Parse query string into parameters object\n */\nfunction parseQueryString(queryString: string): MutableOTPAuthParams {\n const params: MutableOTPAuthParams = {};\n\n if (!queryString) {\n return params;\n }\n\n const pairs = queryString.split(\"&\");\n for (const pair of pairs) {\n const equalIndex = pair.indexOf(\"=\");\n if (equalIndex === -1) {\n continue;\n }\n\n const key = safeDecodeURIComponent(pair.slice(0, equalIndex), 64, \"parameter key\");\n const value = safeDecodeURIComponent(\n pair.slice(equalIndex + 1),\n MAX_PARAM_VALUE_LENGTH,\n `parameter '${key}'`,\n );\n\n switch (key) {\n case \"secret\":\n params.secret = value;\n break;\n case \"issuer\":\n params.issuer = value;\n break;\n case \"algorithm\":\n params.algorithm = parseAlgorithm(value);\n break;\n case \"digits\":\n params.digits = parseDigits(value);\n break;\n case \"counter\":\n params.counter = parseIntegerParameter(\"counter\", value, 0);\n break;\n case \"period\":\n params.period = parseIntegerParameter(\"period\", value, 1);\n break;\n }\n }\n\n return params;\n}\n\n/**\n * Parse an integer parameter with strict validation\n */\nfunction parseIntegerParameter(name: string, value: string, min: number): number {\n if (!/^-?\\d+$/.test(value)) {\n throw new InvalidParameterError(name, value);\n }\n\n const parsed = Number(value);\n if (!Number.isSafeInteger(parsed)) {\n throw new InvalidParameterError(name, value);\n }\n\n if (parsed < min) {\n throw new InvalidParameterError(name, value);\n }\n\n return parsed;\n}\n\n/**\n * Parse algorithm string\n */\nfunction parseAlgorithm(value: string): HashAlgorithm {\n const normalized = value.toLowerCase();\n if (normalized === \"sha1\" || normalized === \"sha-1\") {\n return \"sha1\";\n }\n if (normalized === \"sha256\" || normalized === \"sha-256\") {\n return \"sha256\";\n }\n if (normalized === \"sha512\" || normalized === \"sha-512\") {\n return \"sha512\";\n }\n throw new InvalidParameterError(\"algorithm\", value);\n}\n\n/**\n * Parse digits string\n */\nfunction parseDigits(value: string): Digits {\n if (!/^\\d+$/.test(value)) {\n throw new InvalidParameterError(\"digits\", value);\n }\n\n const digits = Number(value);\n if (digits === 6 || digits === 7 || digits === 8) {\n return digits;\n }\n throw new InvalidParameterError(\"digits\", value);\n}\n","import type { OTPAuthURI } from \"./types.js\";\nimport type { HashAlgorithm, Digits } from \"@otplib/core\";\n\n/**\n * Base options for URI generation\n */\nexport type URIOptions = {\n /**\n * Service/provider name (e.g., 'ACME Co', 'GitHub', 'AWS')\n */\n issuer?: string;\n\n /**\n * Account identifier (e.g., email, username)\n */\n label?: string;\n\n /**\n * Base32-encoded secret key\n */\n secret: string;\n\n /**\n * Hash algorithm (default: 'sha1')\n * Note: Google Authenticator only supports sha1\n */\n algorithm?: HashAlgorithm;\n\n /**\n * Number of digits (default: 6)\n * Google Authenticator supports 6 or 8, RFC also allows 7\n */\n digits?: Digits;\n\n /**\n * Time step in seconds for TOTP (default: 30)\n */\n period?: number;\n\n /**\n * Counter value for HOTP\n */\n counter?: number;\n};\n\n/**\n * TOTP-specific URI options\n */\nexport type TOTPURIOptions = URIOptions & {\n period?: number;\n counter?: never;\n};\n\n/**\n * HOTP-specific URI options\n */\nexport type HOTPURIOptions = URIOptions & {\n period?: never;\n counter?: number;\n};\n\n/**\n * Generate an otpauth:// URI\n *\n * @param uri - The URI components\n * @returns The otpauth:// URI string\n *\n * @example\n * ```ts\n * import { generate } from '@otplib/uri';\n * import { base32 } from '@otplib/plugin-base32-scure';\n *\n * const secret = base32.encode(new Uint8Array([1, 2, 3, 4, 5]));\n *\n * const uri = generate({\n * type: 'totp',\n * label: 'ACME:john@example.com',\n * params: {\n * secret,\n * issuer: 'ACME',\n * algorithm: 'sha1',\n * digits: 6,\n * },\n * });\n * // Returns: 'otpauth://totp/ACME:john%40example.com?secret=...'\n * ```\n */\nexport function generate(uri: OTPAuthURI): string {\n const { type, label, params } = uri;\n\n // Encode label parts while preserving ':' as the issuer/account separator\n const encodedLabel = label\n .split(\":\")\n .map((part) => encodeURIComponent(part))\n .join(\":\");\n\n let result = `otpauth://${type}/${encodedLabel}?`;\n\n const queryParams: string[] = [];\n\n if (params.secret) {\n queryParams.push(`secret=${encodeURIComponent(params.secret)}`);\n }\n\n if (params.issuer) {\n queryParams.push(`issuer=${encodeURIComponent(params.issuer)}`);\n }\n\n if (params.algorithm && params.algorithm !== \"sha1\") {\n queryParams.push(`algorithm=${params.algorithm.toUpperCase()}`);\n }\n\n if (params.digits && params.digits !== 6) {\n queryParams.push(`digits=${params.digits}`);\n }\n\n if (type === \"hotp\" && params.counter !== undefined) {\n queryParams.push(`counter=${params.counter}`);\n }\n\n if (type === \"totp\" && params.period !== undefined && params.period !== 30) {\n queryParams.push(`period=${params.period}`);\n }\n\n result += queryParams.join(\"&\");\n\n return result;\n}\n\n/**\n * Generate a TOTP otpauth:// URI with simplified parameters\n *\n * @param options - TOTP URI generation options\n * @returns The otpauth:// URI string\n */\nexport function generateTOTP(options: TOTPURIOptions & { issuer: string; label: string }): string {\n const { issuer, label: account, secret, algorithm = \"sha1\", digits = 6, period = 30 } = options;\n\n const fullLabel = issuer ? `${issuer}:${account}` : account;\n\n return generate({\n type: \"totp\",\n label: fullLabel,\n params: {\n secret,\n issuer,\n algorithm,\n digits,\n period,\n },\n });\n}\n\n/**\n * Generate a HOTP otpauth:// URI with simplified parameters\n *\n * @param options - HOTP URI generation options\n * @returns The otpauth:// URI string\n */\nexport function generateHOTP(options: HOTPURIOptions & { issuer: string; label: string }): string {\n const { issuer, label: account, secret, counter = 0, algorithm = \"sha1\", digits = 6 } = options;\n\n const fullLabel = issuer ? `${issuer}:${account}` : account;\n\n return generate({\n type: \"hotp\",\n label: fullLabel,\n params: {\n secret,\n issuer,\n algorithm,\n digits,\n counter,\n },\n });\n}\n"],"mappings":"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","names":["URIParseError","message","InvalidURIError","uri","MissingParameterError","param","InvalidParameterError","value","MAX_URI_LENGTH","MAX_LABEL_LENGTH","MAX_PARAM_VALUE_LENGTH","formatErrorMessage","error","context","errorStr","safeDecodeURIComponent","str","maxLength","InvalidURIError","decoded","parse","uri","withoutScheme","slashIndex","type","InvalidParameterError","remaining","queryIndex","label","queryString","params","parseQueryString","MissingParameterError","pairs","pair","equalIndex","key","value","parseAlgorithm","parseDigits","parseIntegerParameter","name","min","parsed","normalized","digits","generate","uri","type","label","params","encodedLabel","part","result","queryParams","generateTOTP","options","issuer","account","secret","algorithm","digits","period","fullLabel","generateHOTP","counter"]}
|
package/dist/metafile-cjs.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"inputs":{"src/types.ts":{"bytes":2038,"imports":[],"format":"esm"},"src/parse.ts":{"bytes":
|
|
1
|
+
{"inputs":{"src/types.ts":{"bytes":2038,"imports":[],"format":"esm"},"src/parse.ts":{"bytes":5830,"imports":[{"path":"src/types.ts","kind":"import-statement","original":"./types.js"}],"format":"esm"},"src/generate.ts":{"bytes":3904,"imports":[],"format":"esm"},"src/index.ts":{"bytes":395,"imports":[{"path":"src/parse.ts","kind":"import-statement","original":"./parse.js"},{"path":"src/generate.ts","kind":"import-statement","original":"./generate.js"},{"path":"src/types.ts","kind":"import-statement","original":"./types.js"}],"format":"esm"}},"outputs":{"dist/index.cjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":18385},"dist/index.cjs":{"imports":[],"exports":[],"entryPoint":"src/index.ts","inputs":{"src/index.ts":{"bytesInOutput":214},"src/types.ts":{"bytesInOutput":408},"src/parse.ts":{"bytesInOutput":1737},"src/generate.ts":{"bytesInOutput":940}},"bytes":3871}}}
|
package/dist/metafile-esm.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"inputs":{"src/types.ts":{"bytes":2038,"imports":[],"format":"esm"},"src/parse.ts":{"bytes":
|
|
1
|
+
{"inputs":{"src/types.ts":{"bytes":2038,"imports":[],"format":"esm"},"src/parse.ts":{"bytes":5830,"imports":[{"path":"src/types.ts","kind":"import-statement","original":"./types.js"}],"format":"esm"},"src/generate.ts":{"bytes":3904,"imports":[],"format":"esm"},"src/index.ts":{"bytes":395,"imports":[{"path":"src/parse.ts","kind":"import-statement","original":"./parse.js"},{"path":"src/generate.ts","kind":"import-statement","original":"./generate.js"},{"path":"src/types.ts","kind":"import-statement","original":"./types.js"}],"format":"esm"}},"outputs":{"dist/index.js.map":{"imports":[],"exports":[],"inputs":{},"bytes":17609},"dist/index.js":{"imports":[],"exports":["InvalidParameterError","InvalidURIError","MissingParameterError","URIParseError","generate","generateHOTP","generateTOTP","parse","parseURI"],"entryPoint":"src/index.ts","inputs":{"src/types.ts":{"bytesInOutput":408},"src/parse.ts":{"bytesInOutput":1737},"src/index.ts":{"bytesInOutput":0},"src/generate.ts":{"bytesInOutput":940}},"bytes":3263}}}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@otplib/uri",
|
|
3
|
-
"version": "13.
|
|
3
|
+
"version": "13.3.0",
|
|
4
4
|
"description": "otpauth:// URI parsing and generation for otplib",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Gerald Yeo <support@yeojz.dev>",
|
|
@@ -44,11 +44,11 @@
|
|
|
44
44
|
"LICENSE"
|
|
45
45
|
],
|
|
46
46
|
"dependencies": {
|
|
47
|
-
"@otplib/core": "13.
|
|
47
|
+
"@otplib/core": "13.3.0"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
|
-
"tsup": "^8.
|
|
51
|
-
"typescript": "^5.
|
|
50
|
+
"tsup": "^8.5.1",
|
|
51
|
+
"typescript": "^5.9.3",
|
|
52
52
|
"vitest": "^4.0.18",
|
|
53
53
|
"@repo/testing": "13.0.1"
|
|
54
54
|
},
|