auth-vir 0.0.3 → 1.0.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 CHANGED
@@ -24,12 +24,7 @@ npm i auth-vir
24
24
  /** When a user creates or resets their password, hash it before storing it in your database. */
25
25
 
26
26
  const hashedPassword = await hashPassword('user input password');
27
-
28
- if (!hashedPassword) {
29
- /** This happens if the user password is too long for the bcrypt algorithm. */
30
- throw new Error('Password too long.');
31
- }
32
- /** Now store `hashedPassword` in your database. */
27
+ /** Store `hashedPassword` in your database. */
33
28
  ```
34
29
 
35
30
  - Compare a stored password hash for login checking:
package/dist/hash.d.ts CHANGED
@@ -1,20 +1,27 @@
1
+ import { type PartialWithUndefined } from '@augment-vir/common';
2
+ import { type IArgon2Options } from 'hash-wasm';
1
3
  /**
2
- * Hashes a password using the bcrypt algorithm so passwords don't need to be stored in plain text.
3
- * The output of this function is safe to store in a database for future credential comparisons.
4
+ * Default value for {@link HashPasswordOptions}.
4
5
  *
5
- * @category Auth : Host
6
- * @returns `undefined` if the password is too long (and would be truncated by the bcrypt hashing
7
- * algorithm). Otherwise, the hashed output.
8
- * @see https://wikipedia.org/wiki/Bcrypt
6
+ * @category Internal
9
7
  */
10
- export declare function hashPassword(password: string): Promise<undefined | string>;
8
+ export declare const defaultHashOptions: HashPasswordOptions;
11
9
  /**
12
- * Checks if the given string will be truncated when passed through {@link hashPassword}. Passwords
13
- * longer than this should not be accepted.
10
+ * Options for {@link hashPassword}.
14
11
  *
15
12
  * @category Internal
16
13
  */
17
- export declare function willHashTruncate(input: string): boolean;
14
+ export type HashPasswordOptions = PartialWithUndefined<Omit<IArgon2Options, 'outputType' | 'salt' | 'password' | 'secret'>>;
15
+ /**
16
+ * Hashes a password using the Argon2id algorithm so passwords don't need to be stored in plain
17
+ * text. The output of this function is safe to store in a database for future credential
18
+ * comparisons.
19
+ *
20
+ * @category Auth : Host
21
+ * @returns The hashed password.
22
+ * @see https://en.wikipedia.org/wiki/Argon2
23
+ */
24
+ export declare function hashPassword(password: string, options?: HashPasswordOptions): Promise<string>;
18
25
  /**
19
26
  * A utility that provides more accurate string byte size than doing `string.length`.
20
27
  *
@@ -22,7 +29,7 @@ export declare function willHashTruncate(input: string): boolean;
22
29
  */
23
30
  export declare function getByteLength(input: string): number;
24
31
  /**
25
- * Checks if the given password is a match by comparing it to its previously computed and stored
32
+ * Checks if the given password is a match by comparing it to the previously computed and stored
26
33
  * hash.
27
34
  *
28
35
  * @category Auth : Host
package/dist/hash.js CHANGED
@@ -1,33 +1,32 @@
1
- import { bcrypt, bcryptVerify } from 'hash-wasm';
1
+ import { mergeDefinedProperties, } from '@augment-vir/common';
2
+ import { argon2id, argon2Verify } from 'hash-wasm';
2
3
  /**
3
- * Hashes a password using the bcrypt algorithm so passwords don't need to be stored in plain text.
4
- * The output of this function is safe to store in a database for future credential comparisons.
4
+ * Default value for {@link HashPasswordOptions}.
5
5
  *
6
- * @category Auth : Host
7
- * @returns `undefined` if the password is too long (and would be truncated by the bcrypt hashing
8
- * algorithm). Otherwise, the hashed output.
9
- * @see https://wikipedia.org/wiki/Bcrypt
6
+ * @category Internal
10
7
  */
11
- export async function hashPassword(password) {
12
- if (willHashTruncate(password)) {
13
- return undefined;
14
- }
15
- const salt = new Uint8Array(16);
16
- globalThis.crypto.getRandomValues(salt);
17
- return await bcrypt({
18
- costFactor: 10,
19
- password: password.normalize(),
20
- salt,
21
- });
22
- }
8
+ export const defaultHashOptions = {
9
+ hashLength: 32,
10
+ iterations: 256,
11
+ memorySize: 512,
12
+ parallelism: 1,
13
+ };
23
14
  /**
24
- * Checks if the given string will be truncated when passed through {@link hashPassword}. Passwords
25
- * longer than this should not be accepted.
15
+ * Hashes a password using the Argon2id algorithm so passwords don't need to be stored in plain
16
+ * text. The output of this function is safe to store in a database for future credential
17
+ * comparisons.
26
18
  *
27
- * @category Internal
19
+ * @category Auth : Host
20
+ * @returns The hashed password.
21
+ * @see https://en.wikipedia.org/wiki/Argon2
28
22
  */
29
- export function willHashTruncate(input) {
30
- return getByteLength(input) > 72;
23
+ export async function hashPassword(password, options = {}) {
24
+ const salt = globalThis.crypto.getRandomValues(new Uint8Array(16));
25
+ return await argon2id(mergeDefinedProperties(defaultHashOptions, options, {
26
+ outputType: 'encoded',
27
+ password: password.normalize(),
28
+ salt,
29
+ }));
31
30
  }
32
31
  /**
33
32
  * A utility that provides more accurate string byte size than doing `string.length`.
@@ -38,13 +37,13 @@ export function getByteLength(input) {
38
37
  return new Blob([input]).size;
39
38
  }
40
39
  /**
41
- * Checks if the given password is a match by comparing it to its previously computed and stored
40
+ * Checks if the given password is a match by comparing it to the previously computed and stored
42
41
  * hash.
43
42
  *
44
43
  * @category Auth : Host
45
44
  */
46
45
  export async function doesPasswordMatchHash({ password, hash, }) {
47
- return await bcryptVerify({
46
+ return await argon2Verify({
48
47
  hash,
49
48
  password,
50
49
  });
@@ -1,2 +1,3 @@
1
+ import { stringifyWithJson5 } from '@augment-vir/common';
1
2
  import { generateNewJwtKeys } from './jwt-keys.js';
2
- console.info(await generateNewJwtKeys());
3
+ console.info(stringifyWithJson5(await generateNewJwtKeys()));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "auth-vir",
3
- "version": "0.0.3",
3
+ "version": "1.0.0",
4
4
  "description": "Auth made easy and secure via JWT cookies, CSRF tokens, and password hashing helpers.",
5
5
  "keywords": [
6
6
  "auth",
package/src/hash.ts CHANGED
@@ -1,37 +1,53 @@
1
- import {bcrypt, bcryptVerify} from 'hash-wasm';
1
+ import {
2
+ type AnyObject,
3
+ mergeDefinedProperties,
4
+ type PartialWithUndefined,
5
+ } from '@augment-vir/common';
6
+ import {argon2id, argon2Verify, type IArgon2Options} from 'hash-wasm';
2
7
 
3
8
  /**
4
- * Hashes a password using the bcrypt algorithm so passwords don't need to be stored in plain text.
5
- * The output of this function is safe to store in a database for future credential comparisons.
9
+ * Default value for {@link HashPasswordOptions}.
6
10
  *
7
- * @category Auth : Host
8
- * @returns `undefined` if the password is too long (and would be truncated by the bcrypt hashing
9
- * algorithm). Otherwise, the hashed output.
10
- * @see https://wikipedia.org/wiki/Bcrypt
11
+ * @category Internal
11
12
  */
12
- export async function hashPassword(password: string): Promise<undefined | string> {
13
- if (willHashTruncate(password)) {
14
- return undefined;
15
- }
16
-
17
- const salt = new Uint8Array(16);
18
- globalThis.crypto.getRandomValues(salt);
19
-
20
- return await bcrypt({
21
- costFactor: 10,
22
- password: password.normalize(),
23
- salt,
24
- });
25
- }
13
+ export const defaultHashOptions: HashPasswordOptions = {
14
+ hashLength: 32,
15
+ iterations: 256,
16
+ memorySize: 512,
17
+ parallelism: 1,
18
+ };
26
19
 
27
20
  /**
28
- * Checks if the given string will be truncated when passed through {@link hashPassword}. Passwords
29
- * longer than this should not be accepted.
21
+ * Options for {@link hashPassword}.
30
22
  *
31
23
  * @category Internal
32
24
  */
33
- export function willHashTruncate(input: string): boolean {
34
- return getByteLength(input) > 72;
25
+ export type HashPasswordOptions = PartialWithUndefined<
26
+ Omit<IArgon2Options, 'outputType' | 'salt' | 'password' | 'secret'>
27
+ >;
28
+
29
+ /**
30
+ * Hashes a password using the Argon2id algorithm so passwords don't need to be stored in plain
31
+ * text. The output of this function is safe to store in a database for future credential
32
+ * comparisons.
33
+ *
34
+ * @category Auth : Host
35
+ * @returns The hashed password.
36
+ * @see https://en.wikipedia.org/wiki/Argon2
37
+ */
38
+ export async function hashPassword(
39
+ password: string,
40
+ options: HashPasswordOptions = {},
41
+ ): Promise<string> {
42
+ const salt = globalThis.crypto.getRandomValues(new Uint8Array(16));
43
+
44
+ return await argon2id(
45
+ mergeDefinedProperties<AnyObject>(defaultHashOptions, options, {
46
+ outputType: 'encoded',
47
+ password: password.normalize(),
48
+ salt,
49
+ }) as IArgon2Options,
50
+ );
35
51
  }
36
52
 
37
53
  /**
@@ -44,7 +60,7 @@ export function getByteLength(input: string): number {
44
60
  }
45
61
 
46
62
  /**
47
- * Checks if the given password is a match by comparing it to its previously computed and stored
63
+ * Checks if the given password is a match by comparing it to the previously computed and stored
48
64
  * hash.
49
65
  *
50
66
  * @category Auth : Host
@@ -58,7 +74,7 @@ export async function doesPasswordMatchHash({
58
74
  /** The stored password hash for that user. */
59
75
  hash: string;
60
76
  }): Promise<boolean> {
61
- return await bcryptVerify({
77
+ return await argon2Verify({
62
78
  hash,
63
79
  password,
64
80
  });
@@ -1,3 +1,4 @@
1
+ import {stringifyWithJson5} from '@augment-vir/common';
1
2
  import {generateNewJwtKeys} from './jwt-keys.js';
2
3
 
3
- console.info(await generateNewJwtKeys());
4
+ console.info(stringifyWithJson5(await generateNewJwtKeys()));