@mytechtoday/augment-extensions 0.1.0 → 0.1.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/AGENTS.md +83 -3
- package/README.md +6 -5
- package/augment-extensions/coding-standards/python/README.md +44 -0
- package/augment-extensions/coding-standards/python/module.json +26 -0
- package/augment-extensions/coding-standards/python/rules/best-practices.md +232 -0
- package/augment-extensions/coding-standards/python/rules/code-organization.md +220 -0
- package/augment-extensions/coding-standards/python/rules/error-handling.md +221 -0
- package/augment-extensions/coding-standards/python/rules/naming-conventions.md +172 -0
- package/augment-extensions/coding-standards/python/rules/type-hints.md +188 -0
- package/augment-extensions/coding-standards/react/README.md +45 -0
- package/augment-extensions/coding-standards/react/module.json +27 -0
- package/augment-extensions/coding-standards/react/rules/component-patterns.md +214 -0
- package/augment-extensions/coding-standards/react/rules/hooks-best-practices.md +235 -0
- package/augment-extensions/coding-standards/react/rules/performance.md +300 -0
- package/augment-extensions/coding-standards/react/rules/state-management.md +265 -0
- package/augment-extensions/coding-standards/react/rules/typescript-react.md +271 -0
- package/augment-extensions/domain-rules/api-design/README.md +41 -0
- package/augment-extensions/domain-rules/api-design/module.json +27 -0
- package/augment-extensions/domain-rules/api-design/rules/authentication.md +263 -0
- package/augment-extensions/domain-rules/api-design/rules/documentation.md +395 -0
- package/augment-extensions/domain-rules/api-design/rules/error-handling.md +290 -0
- package/augment-extensions/domain-rules/api-design/rules/graphql-api.md +313 -0
- package/augment-extensions/domain-rules/api-design/rules/rest-api.md +214 -0
- package/augment-extensions/domain-rules/api-design/rules/versioning.md +268 -0
- package/augment-extensions/domain-rules/security/README.md +41 -0
- package/augment-extensions/domain-rules/security/module.json +28 -0
- package/augment-extensions/domain-rules/security/rules/authentication-security.md +361 -0
- package/augment-extensions/domain-rules/security/rules/encryption.md +208 -0
- package/augment-extensions/domain-rules/security/rules/input-validation.md +294 -0
- package/augment-extensions/domain-rules/security/rules/owasp-top-10.md +339 -0
- package/augment-extensions/domain-rules/security/rules/secure-coding.md +293 -0
- package/augment-extensions/domain-rules/security/rules/web-security.md +268 -0
- package/augment-extensions/examples/design-patterns/README.md +37 -0
- package/augment-extensions/examples/design-patterns/examples/behavioral-patterns.md +370 -0
- package/augment-extensions/examples/design-patterns/examples/creational-patterns.md +250 -0
- package/augment-extensions/examples/design-patterns/examples/structural-patterns.md +264 -0
- package/augment-extensions/examples/design-patterns/module.json +27 -0
- package/{modules → augment-extensions}/workflows/beads/examples/complete-workflow-example.md +5 -5
- package/{modules → augment-extensions}/workflows/beads/rules/file-format.md +45 -1
- package/{modules → augment-extensions}/workflows/beads/rules/workflow.md +41 -0
- package/{modules → augment-extensions}/workflows/openspec/examples/complete-change-example.md +14 -0
- package/{modules → augment-extensions}/workflows/openspec/rules/spec-format.md +44 -1
- package/{modules → augment-extensions}/workflows/openspec/rules/workflow.md +25 -0
- package/cli/dist/cli.js +64 -0
- package/cli/dist/cli.js.map +1 -1
- package/cli/dist/commands/coord.d.ts +30 -0
- package/cli/dist/commands/coord.d.ts.map +1 -0
- package/cli/dist/commands/coord.js +150 -0
- package/cli/dist/commands/coord.js.map +1 -0
- package/cli/dist/commands/link.js +1 -1
- package/cli/dist/commands/link.js.map +1 -1
- package/cli/dist/commands/list.js +1 -1
- package/cli/dist/commands/list.js.map +1 -1
- package/cli/dist/commands/search.d.ts.map +1 -1
- package/cli/dist/commands/search.js +107 -5
- package/cli/dist/commands/search.js.map +1 -1
- package/cli/dist/commands/show.js +1 -1
- package/cli/dist/commands/show.js.map +1 -1
- package/cli/dist/commands/sync.d.ts +26 -0
- package/cli/dist/commands/sync.d.ts.map +1 -0
- package/cli/dist/commands/sync.js +106 -0
- package/cli/dist/commands/sync.js.map +1 -0
- package/cli/dist/commands/update.d.ts.map +1 -1
- package/cli/dist/commands/update.js +132 -7
- package/cli/dist/commands/update.js.map +1 -1
- package/cli/dist/utils/auto-sync.d.ts +34 -0
- package/cli/dist/utils/auto-sync.d.ts.map +1 -0
- package/cli/dist/utils/auto-sync.js +172 -0
- package/cli/dist/utils/auto-sync.js.map +1 -0
- package/cli/dist/utils/beads-sync.d.ts +51 -0
- package/cli/dist/utils/beads-sync.d.ts.map +1 -0
- package/cli/dist/utils/beads-sync.js +171 -0
- package/cli/dist/utils/beads-sync.js.map +1 -0
- package/cli/dist/utils/coordination-queries.d.ts +79 -0
- package/cli/dist/utils/coordination-queries.d.ts.map +1 -0
- package/cli/dist/utils/coordination-queries.js +155 -0
- package/cli/dist/utils/coordination-queries.js.map +1 -0
- package/cli/dist/utils/file-tracking.d.ts +42 -0
- package/cli/dist/utils/file-tracking.d.ts.map +1 -0
- package/cli/dist/utils/file-tracking.js +155 -0
- package/cli/dist/utils/file-tracking.js.map +1 -0
- package/cli/dist/utils/migrate.d.ts +25 -0
- package/cli/dist/utils/migrate.d.ts.map +1 -0
- package/cli/dist/utils/migrate.js +204 -0
- package/cli/dist/utils/migrate.js.map +1 -0
- package/cli/dist/utils/openspec-sync.d.ts +48 -0
- package/cli/dist/utils/openspec-sync.d.ts.map +1 -0
- package/cli/dist/utils/openspec-sync.js +167 -0
- package/cli/dist/utils/openspec-sync.js.map +1 -0
- package/{MODULES.md → modules.md} +1 -1
- package/package.json +9 -7
- /package/{modules → augment-extensions}/coding-standards/typescript/README.md +0 -0
- /package/{modules → augment-extensions}/coding-standards/typescript/module.json +0 -0
- /package/{modules → augment-extensions}/coding-standards/typescript/rules/naming-conventions.md +0 -0
- /package/{modules → augment-extensions}/workflows/beads/README.md +0 -0
- /package/{modules → augment-extensions}/workflows/beads/module.json +0 -0
- /package/{modules → augment-extensions}/workflows/beads/rules/best-practices.md +0 -0
- /package/{modules → augment-extensions}/workflows/beads/rules/manual-setup.md +0 -0
- /package/{modules → augment-extensions}/workflows/openspec/README.md +0 -0
- /package/{modules → augment-extensions}/workflows/openspec/module.json +0 -0
- /package/{modules → augment-extensions}/workflows/openspec/rules/best-practices.md +0 -0
- /package/{modules → augment-extensions}/workflows/openspec/rules/manual-setup.md +0 -0
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
# TypeScript with React
|
|
2
|
+
|
|
3
|
+
Best practices for using TypeScript in React applications.
|
|
4
|
+
|
|
5
|
+
## Component Props
|
|
6
|
+
|
|
7
|
+
Always type component props explicitly.
|
|
8
|
+
|
|
9
|
+
```tsx
|
|
10
|
+
// Good - Explicit prop types
|
|
11
|
+
interface ButtonProps {
|
|
12
|
+
label: string;
|
|
13
|
+
onClick: () => void;
|
|
14
|
+
variant?: 'primary' | 'secondary';
|
|
15
|
+
disabled?: boolean;
|
|
16
|
+
children?: React.ReactNode;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export const Button: React.FC<ButtonProps> = ({
|
|
20
|
+
label,
|
|
21
|
+
onClick,
|
|
22
|
+
variant = 'primary',
|
|
23
|
+
disabled = false,
|
|
24
|
+
children
|
|
25
|
+
}) => {
|
|
26
|
+
return (
|
|
27
|
+
<button
|
|
28
|
+
onClick={onClick}
|
|
29
|
+
disabled={disabled}
|
|
30
|
+
className={`btn btn-${variant}`}
|
|
31
|
+
>
|
|
32
|
+
{children || label}
|
|
33
|
+
</button>
|
|
34
|
+
);
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
// Bad - No types
|
|
38
|
+
export const Button = ({ label, onClick, variant }) => {
|
|
39
|
+
return <button onClick={onClick}>{label}</button>;
|
|
40
|
+
};
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Event Handlers
|
|
44
|
+
|
|
45
|
+
Type event handlers correctly.
|
|
46
|
+
|
|
47
|
+
```tsx
|
|
48
|
+
// Good - Typed event handlers
|
|
49
|
+
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
|
50
|
+
setQuery(e.target.value);
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
|
|
54
|
+
e.preventDefault();
|
|
55
|
+
submitForm();
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {
|
|
59
|
+
console.log('Clicked at', e.clientX, e.clientY);
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
|
|
63
|
+
if (e.key === 'Enter') {
|
|
64
|
+
handleSubmit();
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
// Bad - Any type
|
|
69
|
+
const handleChange = (e: any) => {
|
|
70
|
+
setQuery(e.target.value);
|
|
71
|
+
};
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Hooks with TypeScript
|
|
75
|
+
|
|
76
|
+
Type hooks properly.
|
|
77
|
+
|
|
78
|
+
```tsx
|
|
79
|
+
// Good - Typed useState
|
|
80
|
+
const [user, setUser] = useState<User | null>(null);
|
|
81
|
+
const [items, setItems] = useState<Item[]>([]);
|
|
82
|
+
const [loading, setLoading] = useState<boolean>(false);
|
|
83
|
+
|
|
84
|
+
// Good - Typed useRef
|
|
85
|
+
const inputRef = useRef<HTMLInputElement>(null);
|
|
86
|
+
const timerRef = useRef<NodeJS.Timeout | null>(null);
|
|
87
|
+
|
|
88
|
+
// Good - Typed useReducer
|
|
89
|
+
type State = { count: number; error: string | null };
|
|
90
|
+
type Action = { type: 'increment' } | { type: 'error'; payload: string };
|
|
91
|
+
|
|
92
|
+
const reducer = (state: State, action: Action): State => {
|
|
93
|
+
switch (action.type) {
|
|
94
|
+
case 'increment':
|
|
95
|
+
return { ...state, count: state.count + 1 };
|
|
96
|
+
case 'error':
|
|
97
|
+
return { ...state, error: action.payload };
|
|
98
|
+
default:
|
|
99
|
+
return state;
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
const [state, dispatch] = useReducer(reducer, { count: 0, error: null });
|
|
104
|
+
|
|
105
|
+
// Good - Typed custom hook
|
|
106
|
+
function useLocalStorage<T>(key: string, initialValue: T) {
|
|
107
|
+
const [value, setValue] = useState<T>(() => {
|
|
108
|
+
const stored = localStorage.getItem(key);
|
|
109
|
+
return stored ? JSON.parse(stored) : initialValue;
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
useEffect(() => {
|
|
113
|
+
localStorage.setItem(key, JSON.stringify(value));
|
|
114
|
+
}, [key, value]);
|
|
115
|
+
|
|
116
|
+
return [value, setValue] as const;
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## Children Props
|
|
121
|
+
|
|
122
|
+
Type children correctly.
|
|
123
|
+
|
|
124
|
+
```tsx
|
|
125
|
+
// Good - ReactNode for any children
|
|
126
|
+
interface CardProps {
|
|
127
|
+
children: React.ReactNode;
|
|
128
|
+
title: string;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Good - Specific child type
|
|
132
|
+
interface ListProps {
|
|
133
|
+
children: React.ReactElement<ItemProps> | React.ReactElement<ItemProps>[];
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// Good - Render prop
|
|
137
|
+
interface DataProviderProps<T> {
|
|
138
|
+
data: T[];
|
|
139
|
+
children: (item: T) => React.ReactNode;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const DataProvider = <T,>({ data, children }: DataProviderProps<T>) => (
|
|
143
|
+
<>{data.map(children)}</>
|
|
144
|
+
);
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## Generic Components
|
|
148
|
+
|
|
149
|
+
Create reusable generic components.
|
|
150
|
+
|
|
151
|
+
```tsx
|
|
152
|
+
// Good - Generic list component
|
|
153
|
+
interface ListProps<T> {
|
|
154
|
+
items: T[];
|
|
155
|
+
renderItem: (item: T) => React.ReactNode;
|
|
156
|
+
keyExtractor: (item: T) => string;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
function List<T>({ items, renderItem, keyExtractor }: ListProps<T>) {
|
|
160
|
+
return (
|
|
161
|
+
<ul>
|
|
162
|
+
{items.map(item => (
|
|
163
|
+
<li key={keyExtractor(item)}>
|
|
164
|
+
{renderItem(item)}
|
|
165
|
+
</li>
|
|
166
|
+
))}
|
|
167
|
+
</ul>
|
|
168
|
+
);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// Usage
|
|
172
|
+
<List
|
|
173
|
+
items={users}
|
|
174
|
+
renderItem={(user) => <UserCard user={user} />}
|
|
175
|
+
keyExtractor={(user) => user.id}
|
|
176
|
+
/>
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
## Context with TypeScript
|
|
180
|
+
|
|
181
|
+
Type context properly.
|
|
182
|
+
|
|
183
|
+
```tsx
|
|
184
|
+
// Good - Typed context
|
|
185
|
+
interface AuthContextValue {
|
|
186
|
+
user: User | null;
|
|
187
|
+
login: (email: string, password: string) => Promise<void>;
|
|
188
|
+
logout: () => void;
|
|
189
|
+
isAuthenticated: boolean;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
const AuthContext = createContext<AuthContextValue | undefined>(undefined);
|
|
193
|
+
|
|
194
|
+
export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
|
|
195
|
+
const [user, setUser] = useState<User | null>(null);
|
|
196
|
+
|
|
197
|
+
const login = async (email: string, password: string) => {
|
|
198
|
+
const user = await api.login(email, password);
|
|
199
|
+
setUser(user);
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
const logout = () => {
|
|
203
|
+
setUser(null);
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
const value: AuthContextValue = {
|
|
207
|
+
user,
|
|
208
|
+
login,
|
|
209
|
+
logout,
|
|
210
|
+
isAuthenticated: !!user
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
export const useAuth = (): AuthContextValue => {
|
|
217
|
+
const context = useContext(AuthContext);
|
|
218
|
+
if (!context) {
|
|
219
|
+
throw new Error('useAuth must be used within AuthProvider');
|
|
220
|
+
}
|
|
221
|
+
return context;
|
|
222
|
+
};
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
## Utility Types
|
|
226
|
+
|
|
227
|
+
Use TypeScript utility types.
|
|
228
|
+
|
|
229
|
+
```tsx
|
|
230
|
+
// Good - Utility types
|
|
231
|
+
type UserFormData = Pick<User, 'name' | 'email' | 'age'>;
|
|
232
|
+
type PartialUser = Partial<User>;
|
|
233
|
+
type ReadonlyUser = Readonly<User>;
|
|
234
|
+
type UserWithoutId = Omit<User, 'id'>;
|
|
235
|
+
type RequiredUser = Required<User>;
|
|
236
|
+
|
|
237
|
+
// Good - Component prop utilities
|
|
238
|
+
type ButtonVariant = 'primary' | 'secondary' | 'danger';
|
|
239
|
+
type ButtonSize = 'small' | 'medium' | 'large';
|
|
240
|
+
|
|
241
|
+
interface BaseButtonProps {
|
|
242
|
+
onClick: () => void;
|
|
243
|
+
disabled?: boolean;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
type PrimaryButtonProps = BaseButtonProps & {
|
|
247
|
+
variant: 'primary';
|
|
248
|
+
icon?: React.ReactNode;
|
|
249
|
+
};
|
|
250
|
+
|
|
251
|
+
type SecondaryButtonProps = BaseButtonProps & {
|
|
252
|
+
variant: 'secondary';
|
|
253
|
+
outline?: boolean;
|
|
254
|
+
};
|
|
255
|
+
|
|
256
|
+
type ButtonProps = PrimaryButtonProps | SecondaryButtonProps;
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
## Best Practices
|
|
260
|
+
|
|
261
|
+
1. **Always type props** - Use interfaces or types
|
|
262
|
+
2. **Type event handlers** - Use React event types
|
|
263
|
+
3. **Type hooks** - Provide generic types to hooks
|
|
264
|
+
4. **Use strict mode** - Enable strict TypeScript settings
|
|
265
|
+
5. **Avoid any** - Use unknown or proper types
|
|
266
|
+
6. **Use utility types** - Pick, Omit, Partial, etc.
|
|
267
|
+
7. **Type children** - Use React.ReactNode
|
|
268
|
+
8. **Export types** - Make types reusable
|
|
269
|
+
9. **Use const assertions** - For readonly arrays/objects
|
|
270
|
+
10. **Enable ESLint** - Use @typescript-eslint rules
|
|
271
|
+
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# API Design Guidelines
|
|
2
|
+
|
|
3
|
+
Comprehensive guidelines for designing robust, scalable, and maintainable APIs.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
This module provides detailed guidelines for API design including REST principles, GraphQL best practices, versioning strategies, and general API design patterns.
|
|
8
|
+
|
|
9
|
+
## Key Benefits
|
|
10
|
+
|
|
11
|
+
- **RESTful Design**: Proper REST API architecture
|
|
12
|
+
- **GraphQL Patterns**: Modern GraphQL API design
|
|
13
|
+
- **Versioning**: API versioning strategies
|
|
14
|
+
- **Security**: Authentication and authorization patterns
|
|
15
|
+
- **Documentation**: API documentation best practices
|
|
16
|
+
|
|
17
|
+
## Installation
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
augx link domain-rules/api-design
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Contents
|
|
24
|
+
|
|
25
|
+
### Rules
|
|
26
|
+
|
|
27
|
+
- **rest-api.md** - RESTful API design principles
|
|
28
|
+
- **graphql-api.md** - GraphQL API best practices
|
|
29
|
+
- **versioning.md** - API versioning strategies
|
|
30
|
+
- **authentication.md** - Authentication and authorization
|
|
31
|
+
- **error-handling.md** - API error handling patterns
|
|
32
|
+
- **documentation.md** - API documentation guidelines
|
|
33
|
+
|
|
34
|
+
## Character Count
|
|
35
|
+
|
|
36
|
+
~35,000 characters
|
|
37
|
+
|
|
38
|
+
## Version
|
|
39
|
+
|
|
40
|
+
1.0.0
|
|
41
|
+
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "api-design",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"displayName": "API Design Guidelines",
|
|
5
|
+
"description": "Comprehensive API design guidelines including REST, GraphQL, versioning, and best practices",
|
|
6
|
+
"type": "domain-rules",
|
|
7
|
+
"author": "Augment Extensions",
|
|
8
|
+
"license": "MIT",
|
|
9
|
+
"augment": {
|
|
10
|
+
"characterCount": 35000,
|
|
11
|
+
"priority": "high",
|
|
12
|
+
"category": "domain-rules"
|
|
13
|
+
},
|
|
14
|
+
"installation": {
|
|
15
|
+
"required": false,
|
|
16
|
+
"dependencies": []
|
|
17
|
+
},
|
|
18
|
+
"tags": [
|
|
19
|
+
"api",
|
|
20
|
+
"rest",
|
|
21
|
+
"graphql",
|
|
22
|
+
"versioning",
|
|
23
|
+
"http",
|
|
24
|
+
"best-practices"
|
|
25
|
+
]
|
|
26
|
+
}
|
|
27
|
+
|
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
# API Authentication & Authorization
|
|
2
|
+
|
|
3
|
+
Best practices for securing APIs with authentication and authorization.
|
|
4
|
+
|
|
5
|
+
## Authentication Methods
|
|
6
|
+
|
|
7
|
+
### JWT (JSON Web Tokens) - Recommended
|
|
8
|
+
|
|
9
|
+
Stateless authentication using signed tokens.
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
# Request
|
|
13
|
+
POST /api/v1/auth/login
|
|
14
|
+
{
|
|
15
|
+
"email": "user@example.com",
|
|
16
|
+
"password": "secret"
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
# Response
|
|
20
|
+
{
|
|
21
|
+
"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
|
|
22
|
+
"refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
|
|
23
|
+
"expiresIn": 3600
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
# Subsequent requests
|
|
27
|
+
GET /api/v1/users/me
|
|
28
|
+
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
|
|
29
|
+
|
|
30
|
+
# Advantages:
|
|
31
|
+
- Stateless (no server-side session storage)
|
|
32
|
+
- Scalable
|
|
33
|
+
- Works across domains
|
|
34
|
+
- Contains user claims
|
|
35
|
+
|
|
36
|
+
# Disadvantages:
|
|
37
|
+
- Cannot revoke before expiration (use short expiry + refresh tokens)
|
|
38
|
+
- Larger than session IDs
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### API Keys
|
|
42
|
+
|
|
43
|
+
Simple authentication for service-to-service communication.
|
|
44
|
+
|
|
45
|
+
```
|
|
46
|
+
# Request
|
|
47
|
+
GET /api/v1/data
|
|
48
|
+
X-API-Key: sk_live_abc123def456
|
|
49
|
+
|
|
50
|
+
# Or in query parameter (less secure)
|
|
51
|
+
GET /api/v1/data?api_key=sk_live_abc123def456
|
|
52
|
+
|
|
53
|
+
# Advantages:
|
|
54
|
+
- Simple to implement
|
|
55
|
+
- Good for service-to-service auth
|
|
56
|
+
|
|
57
|
+
# Disadvantages:
|
|
58
|
+
- No user context
|
|
59
|
+
- Hard to rotate
|
|
60
|
+
- Can be leaked in logs/URLs
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### OAuth 2.0
|
|
64
|
+
|
|
65
|
+
Delegated authorization for third-party access.
|
|
66
|
+
|
|
67
|
+
```
|
|
68
|
+
# Authorization Code Flow
|
|
69
|
+
1. Client redirects to authorization server
|
|
70
|
+
GET /oauth/authorize?
|
|
71
|
+
response_type=code&
|
|
72
|
+
client_id=abc123&
|
|
73
|
+
redirect_uri=https://app.com/callback&
|
|
74
|
+
scope=read:users
|
|
75
|
+
|
|
76
|
+
2. User approves, redirected back with code
|
|
77
|
+
https://app.com/callback?code=xyz789
|
|
78
|
+
|
|
79
|
+
3. Exchange code for token
|
|
80
|
+
POST /oauth/token
|
|
81
|
+
{
|
|
82
|
+
"grant_type": "authorization_code",
|
|
83
|
+
"code": "xyz789",
|
|
84
|
+
"client_id": "abc123",
|
|
85
|
+
"client_secret": "secret",
|
|
86
|
+
"redirect_uri": "https://app.com/callback"
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
4. Response with access token
|
|
90
|
+
{
|
|
91
|
+
"access_token": "...",
|
|
92
|
+
"refresh_token": "...",
|
|
93
|
+
"expires_in": 3600,
|
|
94
|
+
"token_type": "Bearer"
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
# Use access token
|
|
98
|
+
GET /api/v1/users
|
|
99
|
+
Authorization: Bearer <access_token>
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## Token Management
|
|
103
|
+
|
|
104
|
+
### Access & Refresh Tokens
|
|
105
|
+
|
|
106
|
+
```
|
|
107
|
+
# Access Token (short-lived: 15 minutes - 1 hour)
|
|
108
|
+
{
|
|
109
|
+
"sub": "user123",
|
|
110
|
+
"email": "user@example.com",
|
|
111
|
+
"role": "admin",
|
|
112
|
+
"exp": 1640000000,
|
|
113
|
+
"iat": 1639996400
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
# Refresh Token (long-lived: 7-30 days)
|
|
117
|
+
- Stored securely (httpOnly cookie or secure storage)
|
|
118
|
+
- Used to obtain new access tokens
|
|
119
|
+
- Can be revoked
|
|
120
|
+
|
|
121
|
+
# Refresh flow
|
|
122
|
+
POST /api/v1/auth/refresh
|
|
123
|
+
{
|
|
124
|
+
"refreshToken": "..."
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
Response:
|
|
128
|
+
{
|
|
129
|
+
"accessToken": "...",
|
|
130
|
+
"expiresIn": 3600
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### Token Storage
|
|
135
|
+
|
|
136
|
+
```
|
|
137
|
+
# Good - Secure storage
|
|
138
|
+
- Access token: Memory or sessionStorage (web)
|
|
139
|
+
- Refresh token: httpOnly cookie (web) or secure storage (mobile)
|
|
140
|
+
|
|
141
|
+
# Bad - Insecure storage
|
|
142
|
+
- localStorage (vulnerable to XSS)
|
|
143
|
+
- URL parameters (logged in server logs)
|
|
144
|
+
- Unencrypted storage
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## Authorization
|
|
148
|
+
|
|
149
|
+
### Role-Based Access Control (RBAC)
|
|
150
|
+
|
|
151
|
+
```
|
|
152
|
+
# User roles
|
|
153
|
+
{
|
|
154
|
+
"sub": "user123",
|
|
155
|
+
"role": "admin",
|
|
156
|
+
"permissions": ["read:users", "write:users", "delete:users"]
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
# Endpoint protection
|
|
160
|
+
GET /api/v1/users - Requires: read:users
|
|
161
|
+
POST /api/v1/users - Requires: write:users
|
|
162
|
+
DELETE /api/v1/users/123 - Requires: delete:users
|
|
163
|
+
|
|
164
|
+
# Implementation
|
|
165
|
+
if (!user.permissions.includes('write:users')) {
|
|
166
|
+
return 403 Forbidden
|
|
167
|
+
}
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### Attribute-Based Access Control (ABAC)
|
|
171
|
+
|
|
172
|
+
```
|
|
173
|
+
# More granular control
|
|
174
|
+
{
|
|
175
|
+
"sub": "user123",
|
|
176
|
+
"department": "engineering",
|
|
177
|
+
"level": "senior"
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
# Rules
|
|
181
|
+
- Users can edit their own profile
|
|
182
|
+
- Managers can edit profiles in their department
|
|
183
|
+
- Admins can edit all profiles
|
|
184
|
+
|
|
185
|
+
# Implementation
|
|
186
|
+
if (resource.userId === user.id) {
|
|
187
|
+
return true; // Own resource
|
|
188
|
+
}
|
|
189
|
+
if (user.role === 'manager' && resource.department === user.department) {
|
|
190
|
+
return true; // Same department
|
|
191
|
+
}
|
|
192
|
+
if (user.role === 'admin') {
|
|
193
|
+
return true; // Admin access
|
|
194
|
+
}
|
|
195
|
+
return false;
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
## Security Best Practices
|
|
199
|
+
|
|
200
|
+
### HTTPS Only
|
|
201
|
+
|
|
202
|
+
```
|
|
203
|
+
# Always use HTTPS
|
|
204
|
+
https://api.example.com/v1/users ✅
|
|
205
|
+
http://api.example.com/v1/users ❌
|
|
206
|
+
|
|
207
|
+
# Redirect HTTP to HTTPS
|
|
208
|
+
# Set HSTS header
|
|
209
|
+
Strict-Transport-Security: max-age=31536000; includeSubDomains
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
### Rate Limiting
|
|
213
|
+
|
|
214
|
+
```
|
|
215
|
+
# Response headers
|
|
216
|
+
X-RateLimit-Limit: 1000
|
|
217
|
+
X-RateLimit-Remaining: 999
|
|
218
|
+
X-RateLimit-Reset: 1640000000
|
|
219
|
+
|
|
220
|
+
# When exceeded
|
|
221
|
+
HTTP/1.1 429 Too Many Requests
|
|
222
|
+
Retry-After: 3600
|
|
223
|
+
|
|
224
|
+
{
|
|
225
|
+
"error": {
|
|
226
|
+
"code": "RATE_LIMIT_EXCEEDED",
|
|
227
|
+
"message": "Too many requests. Please try again later."
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
### CORS Configuration
|
|
233
|
+
|
|
234
|
+
```
|
|
235
|
+
# Proper CORS headers
|
|
236
|
+
Access-Control-Allow-Origin: https://app.example.com
|
|
237
|
+
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
|
|
238
|
+
Access-Control-Allow-Headers: Authorization, Content-Type
|
|
239
|
+
Access-Control-Max-Age: 86400
|
|
240
|
+
|
|
241
|
+
# Don't use wildcard with credentials
|
|
242
|
+
Access-Control-Allow-Origin: * ❌ (with credentials)
|
|
243
|
+
Access-Control-Allow-Credentials: true
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
## Best Practices
|
|
247
|
+
|
|
248
|
+
1. **Use HTTPS** - Always encrypt traffic
|
|
249
|
+
2. **Use JWT** - For stateless authentication
|
|
250
|
+
3. **Short-lived tokens** - Access tokens expire quickly
|
|
251
|
+
4. **Refresh tokens** - For obtaining new access tokens
|
|
252
|
+
5. **Secure storage** - httpOnly cookies or secure storage
|
|
253
|
+
6. **Validate tokens** - Verify signature and expiration
|
|
254
|
+
7. **Rate limiting** - Prevent abuse
|
|
255
|
+
8. **CORS properly** - Don't use wildcard with credentials
|
|
256
|
+
9. **Log auth events** - Track login attempts
|
|
257
|
+
10. **Use strong secrets** - For signing tokens
|
|
258
|
+
11. **Rotate secrets** - Periodically change signing keys
|
|
259
|
+
12. **Implement logout** - Invalidate refresh tokens
|
|
260
|
+
13. **Multi-factor auth** - For sensitive operations
|
|
261
|
+
14. **Monitor suspicious activity** - Detect brute force
|
|
262
|
+
15. **Document auth flow** - Clear documentation for clients
|
|
263
|
+
|