-
Notifications
You must be signed in to change notification settings - Fork 8
Expand file tree
/
Copy pathtoken-signing.ts
More file actions
113 lines (98 loc) · 3.39 KB
/
token-signing.ts
File metadata and controls
113 lines (98 loc) · 3.39 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
/**
* This example demonstrates how to use the token signing functionality in Knock
* for authenticating client-side requests, such as for in-app feeds.
*
* Learn more: https://docs.knock.app/in-app-ui/security-and-authentication#authentication-with-enhanced-security-enabled
*/
import { signUserToken, buildUserTokenGrant, Grants } from '../src/lib';
/**
* Helper function to decode a JWT token
*/
function decodeToken(token: string) {
const [, payload] = token.split('.');
if (!payload) {
throw new Error('Invalid token format');
}
return JSON.parse(Buffer.from(payload, 'base64').toString());
}
/**
* Example 1: Basic usage - Sign a token for a user
*/
async function basicTokenSigning() {
try {
// Generate a JWT token for user-1
const token = await signUserToken('user-1');
console.log('Basic token:', token);
// Decode and display the token contents
const decoded = decodeToken(token);
console.log('Decoded token:', JSON.stringify(decoded, null, 2));
} catch (error) {
console.error('Error signing token:', error);
}
}
/**
* Example 2: Advanced usage - Sign a token with custom expiration and grants
*/
async function advancedTokenSigning() {
try {
// Get signing key from environment or use a test key
const signingKey = process.env['KNOCK_SIGNING_KEY'] || undefined;
// Generate a JWT token with custom expiration and grants
const token = await signUserToken('user-1', {
// Token valid for 12 hours (43200 seconds)
expiresInSeconds: 43200,
// Custom signing key (normally from environment variable)
signingKey,
// Grants for tenant and object access
grants: [
// Grant access to a tenant
buildUserTokenGrant({ type: 'tenant', id: 'jurassic-park' }, [Grants.SlackChannelsRead]),
// Grant access to specific objects
buildUserTokenGrant({ type: 'object', id: 'dinosaurs-loose', collection: 'videos' }, [
Grants.ChannelDataRead,
Grants.ChannelDataWrite,
]),
buildUserTokenGrant({ type: 'object', id: 'raptor-feeding-guide', collection: 'videos' }, [
Grants.ChannelDataRead,
Grants.ChannelDataWrite,
]),
],
});
console.log('Advanced token:', token);
// Decode and display the token contents
const decoded = decodeToken(token);
console.log('Decoded token:', JSON.stringify(decoded, null, 2));
} catch (error) {
console.error('Error signing token:', error);
}
}
/**
* Example 3: Unique tokens with jti
*
* JWT tokens use second-precision timestamps, so tokens generated within
* the same second are identical. Use shouldGenerateJti to include a unique
* JWT ID (jti) claim, ensuring each token is unique.
*/
async function uniqueTokenSigning() {
try {
const token = await signUserToken('user-1', {
shouldGenerateJti: true,
});
console.log('Token with jti:', token);
const decoded = decodeToken(token);
console.log('Decoded token:', JSON.stringify(decoded, null, 2));
console.log('JWT ID (jti):', decoded.jti);
} catch (error) {
console.error('Error signing token:', error);
}
}
// Run the examples
(async () => {
console.log('===== Knock Token Signing Examples =====');
await basicTokenSigning();
console.log('\n---\n');
await advancedTokenSigning();
console.log('\n---\n');
await uniqueTokenSigning();
console.log('\n===== End of Examples =====');
})();