@bb-labs/pkce 0.0.2 → 0.0.3

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
@@ -1,13 +1,6 @@
1
1
  # @bb-labs/pkce
2
2
 
3
- A lightweight, zero-dependency PKCE (Proof Key for Code Exchange) library for OAuth 2.0 that works across platforms.
4
-
5
- ## Features
6
-
7
- - 🎯 **Zero Dependencies**: No external crypto libraries required
8
- - 🔄 **Cross-Platform**: Works in React Native (expo-crypto), Node.js (built-in crypto), and browsers
9
- - 🚀 **Auto-Detection**: Automatically uses the best available crypto implementation
10
- - 📦 **Tree-Shakable**: Import only what you need
3
+ A lightweight PKCE (Proof Key for Code Exchange) library using `@noble/hashes` for universal compatibility.
11
4
 
12
5
  ## Installation
13
6
 
@@ -17,8 +10,6 @@ npm install @bb-labs/pkce
17
10
 
18
11
  ## Usage
19
12
 
20
- ### Automatic Environment Detection (Recommended)
21
-
22
13
  ```typescript
23
14
  import { generateCodeVerifier, createCodeChallenge } from "@bb-labs/pkce";
24
15
 
@@ -26,99 +17,39 @@ import { generateCodeVerifier, createCodeChallenge } from "@bb-labs/pkce";
26
17
  const verifier = generateCodeVerifier();
27
18
 
28
19
  // Create the corresponding code challenge
29
- const challenge = await createCodeChallenge(verifier);
30
-
31
- console.log("Verifier:", verifier);
32
- console.log("Challenge:", challenge);
33
- ```
34
-
35
- ### Platform-Specific Imports
36
-
37
- #### React Native / Expo
38
-
39
- ```typescript
40
- import { generateCodeVerifier, createCodeChallenge } from "@bb-labs/pkce/expo";
41
-
42
- // Make sure expo-crypto is installed in your React Native app
43
- // npm install expo-crypto
44
-
45
- const verifier = generateCodeVerifier();
46
- const challenge = await createCodeChallenge(verifier);
47
- ```
48
-
49
- #### Node.js
20
+ const challenge = createCodeChallenge(verifier);
50
21
 
51
- ```typescript
52
- import { generateCodeVerifier, createCodeChallenge } from "@bb-labs/pkce/nodejs";
53
-
54
- const verifier = generateCodeVerifier();
55
- const challenge = await createCodeChallenge(verifier);
22
+ // Use in OAuth flow...
56
23
  ```
57
24
 
58
25
  ## API
59
26
 
60
27
  ### `generateCodeVerifier(): string`
61
28
 
62
- Generates a cryptographically secure random code verifier (43-128 characters, base64url encoded).
29
+ Generates a cryptographically secure random code verifier (43 characters, base64url encoded).
63
30
 
64
- ### `createCodeChallenge(verifier: string): Promise<string>`
31
+ ### `createCodeChallenge(verifier: string): string`
65
32
 
66
33
  Creates a code challenge by SHA-256 hashing the verifier and base64url encoding the result.
67
34
 
68
35
  ## Requirements
69
36
 
70
- ### React Native / Expo Apps
71
-
72
- - Install `expo-crypto`: `npm install expo-crypto`
73
- - The library will automatically detect and use expo-crypto
74
-
75
- ### Node.js Apps
76
-
77
- - Node.js built-in `crypto` module (available in all modern Node.js versions)
78
- - No additional dependencies required
79
-
80
- ### Browser Apps
37
+ Depends on [`@noble/hashes`](https://github.com/paulmillr/noble-hashes) for crypto functions.
81
38
 
82
- - Modern browsers with Web Crypto API support
83
- - Or use a polyfill for older browsers
84
-
85
- ## PKCE Flow Example
39
+ **React Native Setup:**
86
40
 
87
41
  ```typescript
88
- import { generateCodeVerifier, createCodeChallenge } from "@bb-labs/pkce";
89
-
90
- // 1. Generate verifier and challenge
91
- const verifier = generateCodeVerifier();
92
- const challenge = await createCodeChallenge(verifier);
93
-
94
- // 2. Send challenge to authorization server
95
- const authUrl =
96
- `https://auth.example.com/oauth/authorize?` +
97
- `client_id=your_client_id&` +
98
- `redirect_uri=your_redirect_uri&` +
99
- `response_type=code&` +
100
- `code_challenge=${challenge}&` +
101
- `code_challenge_method=S256`;
102
-
103
- // 3. After user authorization, exchange code for tokens using the verifier
104
- const tokenResponse = await fetch("https://auth.example.com/oauth/token", {
105
- method: "POST",
106
- body: new URLSearchParams({
107
- grant_type: "authorization_code",
108
- code: authorizationCode,
109
- redirect_uri: redirectUri,
110
- client_id: clientId,
111
- code_verifier: verifier, // ← Send the original verifier
112
- }),
113
- });
42
+ // In your app/_layout.tsx (Expo) or App.tsx
43
+ import { polyfillWebCrypto } from "expo-standard-web-crypto";
44
+ polyfillWebCrypto();
114
45
  ```
115
46
 
116
- ## Error Handling
47
+ For bare React Native:
117
48
 
118
- The library will throw descriptive errors if no suitable crypto implementation is found:
119
-
120
- - React Native: `"expo-crypto is required for React Native PKCE operations. Install expo-crypto or use a different PKCE implementation."`
121
- - Node.js: `"Node.js crypto is required for server-side PKCE operations."`
49
+ ```bash
50
+ npm install react-native-get-random-values
51
+ import 'react-native-get-random-values';
52
+ ```
122
53
 
123
54
  ## License
124
55
 
package/dist/index.d.ts CHANGED
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Universal PKCE implementation using @noble/hashes
3
+ * Works in Node.js, React Native, Expo, and browsers
4
+ */
5
+ /**
6
+ * Generates a cryptographically secure random code verifier for PKCE
7
+ * Uses @noble/hashes randomBytes (works in Node.js, browsers, React Native)
8
+ */
9
+ export declare function generateCodeVerifier(): string;
10
+ /**
11
+ * Creates a code challenge from a code verifier using SHA-256
12
+ * Uses @noble/hashes sha256 (works in Node.js, browsers, React Native)
13
+ */
14
+ export declare function createCodeChallenge(verifier: string): string;
package/dist/index.js CHANGED
@@ -1 +1,74 @@
1
- "use strict";
1
+ /**
2
+ * Universal PKCE implementation using @noble/hashes
3
+ * Works in Node.js, React Native, Expo, and browsers
4
+ */
5
+ import { sha256 } from "@noble/hashes/sha2";
6
+ import { randomBytes } from "@noble/hashes/utils";
7
+ /**
8
+ * Generates a cryptographically secure random code verifier for PKCE
9
+ * Uses @noble/hashes randomBytes (works in Node.js, browsers, React Native)
10
+ */
11
+ export function generateCodeVerifier() {
12
+ // Generate 32 bytes (256 bits) of random data
13
+ const randomBytesData = randomBytes(32);
14
+ // Convert to base64url encoding (RFC 4648)
15
+ return base64UrlEncode(randomBytesData);
16
+ }
17
+ /**
18
+ * Creates a code challenge from a code verifier using SHA-256
19
+ * Uses @noble/hashes sha256 (works in Node.js, browsers, React Native)
20
+ */
21
+ export function createCodeChallenge(verifier) {
22
+ // Convert string to bytes
23
+ const bytes = stringToBytes(verifier);
24
+ // Hash using SHA-256 from @noble/hashes
25
+ const hash = sha256(bytes);
26
+ // Convert to base64url encoding
27
+ return base64UrlEncode(hash);
28
+ }
29
+ /**
30
+ * Converts a string to UTF-8 bytes
31
+ */
32
+ function stringToBytes(str) {
33
+ const bytes = [];
34
+ for (let i = 0; i < str.length; i++) {
35
+ const code = str.charCodeAt(i);
36
+ if (code < 0x80) {
37
+ bytes.push(code);
38
+ }
39
+ else if (code < 0x800) {
40
+ bytes.push(0xc0 | (code >> 6), 0x80 | (code & 0x3f));
41
+ }
42
+ else if (code < 0xd800 || code >= 0xe000) {
43
+ bytes.push(0xe0 | (code >> 12), 0x80 | ((code >> 6) & 0x3f), 0x80 | (code & 0x3f));
44
+ }
45
+ else {
46
+ // Surrogate pair
47
+ i++;
48
+ const cp = 0x10000 + (((code & 0x3ff) << 10) | (str.charCodeAt(i) & 0x3ff));
49
+ bytes.push(0xf0 | (cp >> 18), 0x80 | ((cp >> 12) & 0x3f), 0x80 | ((cp >> 6) & 0x3f), 0x80 | (cp & 0x3f));
50
+ }
51
+ }
52
+ return new Uint8Array(bytes);
53
+ }
54
+ /**
55
+ * Converts Uint8Array to base64url encoding (RFC 4648)
56
+ */
57
+ function base64UrlEncode(bytes) {
58
+ const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
59
+ let result = "";
60
+ for (let i = 0; i < bytes.length; i += 3) {
61
+ const b1 = bytes[i];
62
+ const b2 = i + 1 < bytes.length ? bytes[i + 1] : 0;
63
+ const b3 = i + 2 < bytes.length ? bytes[i + 2] : 0;
64
+ result += chars[b1 >> 2];
65
+ result += chars[((b1 & 0x03) << 4) | (b2 >> 4)];
66
+ if (i + 1 < bytes.length) {
67
+ result += chars[((b2 & 0x0f) << 2) | (b3 >> 6)];
68
+ }
69
+ if (i + 2 < bytes.length) {
70
+ result += chars[b3 & 0x3f];
71
+ }
72
+ }
73
+ return result;
74
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bb-labs/pkce",
3
- "version": "0.0.2",
3
+ "version": "0.0.3",
4
4
  "description": "A library for PKCE",
5
5
  "homepage": "https://github.com/beepbop-labs/pkce",
6
6
  "keywords": [
@@ -27,7 +27,10 @@
27
27
  "scripts": {
28
28
  "clean": "rm -rf dist",
29
29
  "build": "npm run clean && tsc -p tsconfig.json",
30
- "pack": "npm run build && npm pack --pack-destination ./archive/"
30
+ "pack": "npm run build && rm -rf archive && mkdir -p archive && bun pm pack --destination ./archive && find ./archive -name '*.tgz' -exec mv {} ./archive/archive2.tgz \\;"
31
+ },
32
+ "dependencies": {
33
+ "@noble/hashes": "^1.3.0"
31
34
  },
32
35
  "devDependencies": {
33
36
  "@types/bun": "latest"
@@ -1,10 +0,0 @@
1
- /**
2
- * Generates a cryptographically secure random code verifier for PKCE
3
- * Uses expo-crypto if available, otherwise throws an error
4
- */
5
- export declare function generateCodeVerifier(): string;
6
- /**
7
- * Creates a code challenge from a code verifier using SHA-256
8
- * Uses expo-crypto if available, otherwise throws an error
9
- */
10
- export declare function createCodeChallenge(verifier: string): Promise<string>;
@@ -1,55 +0,0 @@
1
- /**
2
- * Generates a cryptographically secure random code verifier for PKCE
3
- * Uses expo-crypto if available, otherwise throws an error
4
- */
5
- export function generateCodeVerifier() {
6
- try {
7
- const Crypto = require("expo-crypto");
8
- // Generate 32 bytes (256 bits) of random data
9
- const randomBytes = Crypto.getRandomBytes(32);
10
- // Convert to base64url encoding (RFC 4648)
11
- return base64UrlEncode(randomBytes);
12
- }
13
- catch (error) {
14
- throw new Error("expo-crypto is required for React Native PKCE operations. Install expo-crypto or use a different PKCE implementation.");
15
- }
16
- }
17
- /**
18
- * Creates a code challenge from a code verifier using SHA-256
19
- * Uses expo-crypto if available, otherwise throws an error
20
- */
21
- export async function createCodeChallenge(verifier) {
22
- try {
23
- const Crypto = require("expo-crypto");
24
- // Hash the verifier using SHA-256
25
- const hashBuffer = await Crypto.digestStringAsync(Crypto.CryptoDigestAlgorithm.SHA256, verifier, {
26
- encoding: Crypto.CryptoEncoding.BASE64,
27
- });
28
- // Return base64url encoded hash
29
- return base64UrlEncode(hashBuffer);
30
- }
31
- catch (error) {
32
- throw new Error("expo-crypto is required for React Native PKCE operations. Install expo-crypto or use a different PKCE implementation.");
33
- }
34
- }
35
- /**
36
- * Converts input to base64url encoding (RFC 4648)
37
- * Replaces '+' with '-', '/' with '_', and removes padding
38
- */
39
- function base64UrlEncode(input) {
40
- let base64;
41
- if (typeof input === "string") {
42
- // If input is already a base64 string, use it directly
43
- base64 = input;
44
- }
45
- else {
46
- // Convert Uint8Array to base64
47
- base64 = "";
48
- for (let i = 0; i < input.length; i++) {
49
- base64 += String.fromCharCode(input[i]);
50
- }
51
- base64 = btoa(base64);
52
- }
53
- // Convert to base64url
54
- return base64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
55
- }
@@ -1,10 +0,0 @@
1
- /**
2
- * Generates a cryptographically secure random code verifier for PKCE
3
- * Node.js implementation using built-in crypto
4
- */
5
- export declare function generateCodeVerifier(): string;
6
- /**
7
- * Creates a code challenge from a code verifier using SHA-256
8
- * Node.js implementation using built-in crypto
9
- */
10
- export declare function createCodeChallenge(verifier: string): Promise<string>;
@@ -1,49 +0,0 @@
1
- /**
2
- * Generates a cryptographically secure random code verifier for PKCE
3
- * Node.js implementation using built-in crypto
4
- */
5
- export function generateCodeVerifier() {
6
- try {
7
- const { randomBytes } = require("crypto");
8
- // Generate 32 bytes (256 bits) of random data
9
- const randomBytesData = randomBytes(32);
10
- // Convert to base64url encoding (RFC 4648)
11
- return base64UrlEncode(randomBytesData);
12
- }
13
- catch (error) {
14
- throw new Error("Node.js crypto is required for server-side PKCE operations.");
15
- }
16
- }
17
- /**
18
- * Creates a code challenge from a code verifier using SHA-256
19
- * Node.js implementation using built-in crypto
20
- */
21
- export async function createCodeChallenge(verifier) {
22
- try {
23
- const { createHash } = require("crypto");
24
- // Hash the verifier using SHA-256
25
- const hash = createHash("sha256").update(verifier).digest();
26
- // Return base64url encoded hash
27
- return base64UrlEncode(hash);
28
- }
29
- catch (error) {
30
- throw new Error("Node.js crypto is required for server-side PKCE operations.");
31
- }
32
- }
33
- /**
34
- * Converts input to base64url encoding (RFC 4648)
35
- * Replaces '+' with '-', '/' with '_', and removes padding
36
- */
37
- function base64UrlEncode(input) {
38
- let base64;
39
- if (typeof input === "string") {
40
- // If input is already a base64 string, use it directly
41
- base64 = input;
42
- }
43
- else {
44
- // Convert Buffer to base64
45
- base64 = input.toString("base64");
46
- }
47
- // Convert to base64url
48
- return base64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
49
- }