@bb-labs/pkce 0.0.1

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 ADDED
@@ -0,0 +1,125 @@
1
+ # @bb-labs/pkce
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
11
+
12
+ ## Installation
13
+
14
+ ```bash
15
+ npm install @bb-labs/pkce
16
+ ```
17
+
18
+ ## Usage
19
+
20
+ ### Automatic Environment Detection (Recommended)
21
+
22
+ ```typescript
23
+ import { generateCodeVerifier, createCodeChallenge } from "@bb-labs/pkce";
24
+
25
+ // Generate a cryptographically secure code verifier
26
+ const verifier = generateCodeVerifier();
27
+
28
+ // 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
50
+
51
+ ```typescript
52
+ import { generateCodeVerifier, createCodeChallenge } from "@bb-labs/pkce/nodejs";
53
+
54
+ const verifier = generateCodeVerifier();
55
+ const challenge = await createCodeChallenge(verifier);
56
+ ```
57
+
58
+ ## API
59
+
60
+ ### `generateCodeVerifier(): string`
61
+
62
+ Generates a cryptographically secure random code verifier (43-128 characters, base64url encoded).
63
+
64
+ ### `createCodeChallenge(verifier: string): Promise<string>`
65
+
66
+ Creates a code challenge by SHA-256 hashing the verifier and base64url encoding the result.
67
+
68
+ ## Requirements
69
+
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
81
+
82
+ - Modern browsers with Web Crypto API support
83
+ - Or use a polyfill for older browsers
84
+
85
+ ## PKCE Flow Example
86
+
87
+ ```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
+ });
114
+ ```
115
+
116
+ ## Error Handling
117
+
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."`
122
+
123
+ ## License
124
+
125
+ MIT
@@ -0,0 +1,4 @@
1
+ export * as expo from "./pkce/expo";
2
+ export * as nodejs from "./pkce/nodejs";
3
+ export declare const generateCodeVerifier: any;
4
+ export declare const createCodeChallenge: any;
package/dist/index.js ADDED
@@ -0,0 +1,23 @@
1
+ // Direct exports for specific platforms
2
+ export * as expo from "./pkce/expo";
3
+ export * as nodejs from "./pkce/nodejs";
4
+ // Default export - try to auto-detect environment
5
+ let defaultExport;
6
+ try {
7
+ // Try React Native/expo first
8
+ require("expo-crypto");
9
+ defaultExport = require("./pkce/expo");
10
+ }
11
+ catch {
12
+ try {
13
+ // Try Node.js crypto
14
+ require("crypto");
15
+ defaultExport = require("./pkce/nodejs");
16
+ }
17
+ catch {
18
+ // Fallback - neither crypto is available
19
+ throw new Error("No suitable crypto implementation found. Install expo-crypto for React Native or use Node.js.");
20
+ }
21
+ }
22
+ export const generateCodeVerifier = defaultExport.generateCodeVerifier;
23
+ export const createCodeChallenge = defaultExport.createCodeChallenge;
@@ -0,0 +1,10 @@
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>;
@@ -0,0 +1,55 @@
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
+ }
@@ -0,0 +1,10 @@
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>;
@@ -0,0 +1,49 @@
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
+ }
package/package.json ADDED
@@ -0,0 +1,33 @@
1
+ {
2
+ "name": "@bb-labs/pkce",
3
+ "version": "0.0.1",
4
+ "description": "A library for PKCE",
5
+ "homepage": "https://github.com/beepbop-labs/pkce",
6
+ "keywords": [
7
+ "pkce",
8
+ "pkce-challenge",
9
+ "pkce-verifier"
10
+ ],
11
+ "author": "Beepbop",
12
+ "license": "MIT",
13
+ "repository": {
14
+ "type": "git",
15
+ "url": "https://github.com/beepbop-labs/pkce.git"
16
+ },
17
+ "main": "dist/index.js",
18
+ "files": [
19
+ "dist",
20
+ "README.md"
21
+ ],
22
+ "scripts": {
23
+ "clean": "rm -rf dist",
24
+ "build": "npm run clean && tsc -p tsconfig.json",
25
+ "pack": "npm run build && npm pack --pack-destination ./archive/"
26
+ },
27
+ "devDependencies": {
28
+ "@types/bun": "latest"
29
+ },
30
+ "peerDependencies": {
31
+ "typescript": "^5"
32
+ }
33
+ }