kailash 0.4.1__py3-none-any.whl → 0.4.2__py3-none-any.whl

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.
@@ -1,4 +1,4 @@
1
- kailash/__init__.py,sha256=FdEB2WokgGOcUMo19ACxoI2MowIWcSm3zeZvWt5nVAc,1792
1
+ kailash/__init__.py,sha256=DNNHLV-T781fKqEzh6k-FKu74CJHZG9hsjx6a9xxV48,1724
2
2
  kailash/__main__.py,sha256=vr7TVE5o16V6LsTmRFKG6RDKUXHpIWYdZ6Dok2HkHnI,198
3
3
  kailash/access_control.py,sha256=2ctdRFeSeu-d7DU04Aovxh6Rt_4t3IyQfkKEjTeQiMM,25519
4
4
  kailash/access_control_abac.py,sha256=FPfa_8PuDP3AxTjdWfiH3ntwWO8NodA0py9W8SE5dno,30263
@@ -33,19 +33,21 @@ kailash/mcp/utils/cache.py,sha256=dLEseovPaXL4lRzMSw7tqd3tJHwnWfhdZ-HKGyScJXI,84
33
33
  kailash/mcp/utils/config.py,sha256=DyZxgdy3vqI5pwhQ_E-42mhueVGNHiuOtTUOrM9HC_U,8124
34
34
  kailash/mcp/utils/formatters.py,sha256=D-2j1nvmprApiUI13HWY-L2_WPSAcJDtVdHcshAuOdo,9740
35
35
  kailash/mcp/utils/metrics.py,sha256=MNUjWGQyq1EGdeqzAKCCZJNgcWHOyaYAV8MlS2cb-4k,13754
36
- kailash/middleware/__init__.py,sha256=bHTPBzAOLfSXmKZHU-g0qOgrIQbIdoNxx5A_6S34EDw,10269
37
- kailash/middleware/auth/__init__.py,sha256=ZiF8U2EWtJv4-blfKYAG3K6xhOcwQfajpJe0eeWOaLI,934
36
+ kailash/middleware/__init__.py,sha256=ZGo0qujL-qWn82nIrojY96N1rMPTWFKHumW6CGGpb4Y,10409
37
+ kailash/middleware/auth/__init__.py,sha256=VkKM8H-zVFx2PLGL7kyxE2IfSiV1HiwveSysbmxMcg0,2077
38
38
  kailash/middleware/auth/access_control.py,sha256=u8jlfTXRkRteHXi-kiwSGfFFKzAfabxWR6t6L4dU2bk,14954
39
39
  kailash/middleware/auth/auth_manager.py,sha256=d1XFJ9jOCrOTwV26qO0b7wBOSbroTvTxaJADII-mCz0,14057
40
- kailash/middleware/auth/jwt_auth.py,sha256=k_X4yZEMWTNSViIYgPfVNKjnXCHWxo1gA_9q8mcPI6k,15388
41
- kailash/middleware/auth/kailash_jwt_auth.py,sha256=NdbOUMBr7kh5E0yGfh8sRstiXo6UTLbAadvoQWziFDU,19974
40
+ kailash/middleware/auth/exceptions.py,sha256=tPDQgaX9nMQ9BJZR3Y5tv2LwLy8pZcUz-uFATQjALRA,2496
41
+ kailash/middleware/auth/jwt_auth.py,sha256=r4dauFKcoARHj0yb4f4WwBmY9YQpLNBGyk4gdBZEI1k,21626
42
+ kailash/middleware/auth/models.py,sha256=RSLiP3GeOFgQ6p1ZSV0zIsfo8a_3nkbF9ctPoAKtYEA,3509
43
+ kailash/middleware/auth/utils.py,sha256=AW4fYJ2opQvOr_1YgSQi_MsC_RoFPq0XVOEgbxoXWtw,6555
42
44
  kailash/middleware/communication/__init__.py,sha256=keQ2db4WI2-oZ_nJ5sLE1Tum_RkUt7M2VLTmqOlt0zA,778
43
45
  kailash/middleware/communication/ai_chat.py,sha256=T4R2dujQ40cFH3mI09FTpc6UCbjTItvFLwG0JGe48BQ,36045
44
- kailash/middleware/communication/api_gateway.py,sha256=czRaYOLUpjaVQPR8feb1nuvA4rJwGR8u4z0aBpPjAlY,30048
46
+ kailash/middleware/communication/api_gateway.py,sha256=NMO-Kysvv_z0c8LORvPViPj31nTnkExV0vvlieVni9w,31724
45
47
  kailash/middleware/communication/events.py,sha256=MEjgcibNyjA4tSFK8CeXDn1oCE75My7K_saxdCBz2HY,15367
46
48
  kailash/middleware/communication/realtime.py,sha256=JS7lMV1_Ta5orvTJPQsetdCdvIiUdsgYt7M7NSQu6fs,24951
47
49
  kailash/middleware/core/__init__.py,sha256=4yQkOWC4b88zSogs1YVqtKG1PugbncqNCwNNWxTdIZA,545
48
- kailash/middleware/core/agent_ui.py,sha256=GtUASP2hhA_cV6X_J5uLQK7zNTdZW3Jr2Zw-QUUn7Zo,32579
50
+ kailash/middleware/core/agent_ui.py,sha256=MVmKznG2OcSF3quIr_uNR7rbPv7aaB2VgkHu2hA1AU4,36097
49
51
  kailash/middleware/core/schema.py,sha256=uVF-5ZJlLYHOQdsKrG46FnTO1bq_QtDjhUSkIIDL9dY,23584
50
52
  kailash/middleware/core/workflows.py,sha256=kjwwP69-T6eCY7kWIMLUBwVy2CapoPR34cqCETquq0s,12480
51
53
  kailash/middleware/database/__init__.py,sha256=UMws94L-vja94AjfzPWIgn0h4_5BGQzI3YaSdqtzeLk,1682
@@ -58,7 +60,7 @@ kailash/middleware/database/repositories.py,sha256=3sdHvUv6a0K5ZOoijLt_MLnYPnd8x
58
60
  kailash/middleware/database/session_manager.py,sha256=Pzj7c2TZnM3GRty2igSaxmLOf0-Fs67NVe2Q5lR_C-Q,379
59
61
  kailash/middleware/mcp/__init__.py,sha256=EdZB8zOMSBEEmudRzs8ksz9QZJYWQMEx7Tm1MOwIWnI,922
60
62
  kailash/middleware/mcp/client_integration.py,sha256=opzhB5TUts_ND8gARXh93nKCc1u4kwo6SqNMMWqMcSU,18258
61
- kailash/middleware/mcp/enhanced_server.py,sha256=I82oRfzADPBM0ExxFNhZ-tI2kJTVBF0Hjx4uHfWkA2o,18456
63
+ kailash/middleware/mcp/enhanced_server.py,sha256=ydU265wAoC2d2sFLuuVzmETowzH9qsqvrzJ5mrwEVvU,18458
62
64
  kailash/nodes/__init__.py,sha256=E6CEp1ooq4GgFhKtwVAczOhPt5N3x-AVQ-R0n3_IFyA,936
63
65
  kailash/nodes/base.py,sha256=5selOpaQvLXoy4VaiTbMxB7NbUhQ4tXdUF31-nPSGnc,51291
64
66
  kailash/nodes/base_async.py,sha256=cjp0tedoxvwqr9fdC385vqInb3WTR0Wcx3ecLxhHiY0,6593
@@ -102,7 +104,7 @@ kailash/nodes/auth/risk_assessment.py,sha256=ZVKYCXp8saTBsVxonh2YAM_BkqBPg5HtulR
102
104
  kailash/nodes/auth/session_management.py,sha256=FzOxic3hjmRlMiAQy7ps8a7XO7AoxYToZL9ywAcwKxY,38694
103
105
  kailash/nodes/auth/sso.py,sha256=m-sYRNGEWwKfpvAzaHikGC3Wy45h0o-JhqgeYLTTV24,38507
104
106
  kailash/nodes/code/__init__.py,sha256=L3QBfnITPb6v-Wbq2ezNWt8xDlC4uGaTgrkqIJ9vGKU,1191
105
- kailash/nodes/code/python.py,sha256=RHolFWCkN-NFUv3ZvL5wPd4gxy9rEqg7uXSnpbAXtHU,50571
107
+ kailash/nodes/code/python.py,sha256=v5pGJms-0CWKHGn8TI7c_lyPEYrNdl3A9azddTfDFuc,51417
106
108
  kailash/nodes/compliance/__init__.py,sha256=6a_FL4ofc8MAVuZ-ARW5uYenZLS4mBFVM9AI2QsnoF8,214
107
109
  kailash/nodes/compliance/data_retention.py,sha256=rP85W9mIbbVb4LqxPFYYFySgUJXI5Q5mdoYLY0o3Mnw,69419
108
110
  kailash/nodes/compliance/gdpr.py,sha256=iEAVU7Faqp0HVHk2KLw51oXr6VyJPycvsVL5IQR4ciY,70528
@@ -219,9 +221,9 @@ kailash/workflow/state.py,sha256=UTZxs5-Ona6uvBhx1__i6-RX8gB4qazkBIWE7uyRmWQ,760
219
221
  kailash/workflow/templates.py,sha256=MTIMHGyQML6omLbqeKDbTVIVykfXG6pIFWTTsGBUHN0,48591
220
222
  kailash/workflow/validation.py,sha256=JIbIajWVIaWHSvWtgZ4WUVJaBaUOCz5B9cyTwM--dL4,33060
221
223
  kailash/workflow/visualization.py,sha256=ICMWCWqh5fOQ7eJygbvu2PMWHxe-H5_0epwdZuz8cMw,19737
222
- kailash-0.4.1.dist-info/licenses/LICENSE,sha256=Axe6g7bTrJkToK9h9j2SpRUKKNaDZDCo2lQ2zPxCE6s,1065
223
- kailash-0.4.1.dist-info/METADATA,sha256=KN5COKUq4zgWFi10SlSZFDln22hgMj9qb7TyZAJTLq8,24793
224
- kailash-0.4.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
225
- kailash-0.4.1.dist-info/entry_points.txt,sha256=M_q3b8PG5W4XbhSgESzIJjh3_4OBKtZFYFsOdkr2vO4,45
226
- kailash-0.4.1.dist-info/top_level.txt,sha256=z7GzH2mxl66498pVf5HKwo5wwfPtt9Aq95uZUpH6JV0,8
227
- kailash-0.4.1.dist-info/RECORD,,
224
+ kailash-0.4.2.dist-info/licenses/LICENSE,sha256=Axe6g7bTrJkToK9h9j2SpRUKKNaDZDCo2lQ2zPxCE6s,1065
225
+ kailash-0.4.2.dist-info/METADATA,sha256=wIi6fCs-YFsZuXGSqGeqRd3-GpbioEwmLUhIaCQX32o,24793
226
+ kailash-0.4.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
227
+ kailash-0.4.2.dist-info/entry_points.txt,sha256=M_q3b8PG5W4XbhSgESzIJjh3_4OBKtZFYFsOdkr2vO4,45
228
+ kailash-0.4.2.dist-info/top_level.txt,sha256=z7GzH2mxl66498pVf5HKwo5wwfPtt9Aq95uZUpH6JV0,8
229
+ kailash-0.4.2.dist-info/RECORD,,
@@ -1,616 +0,0 @@
1
- """
2
- Kailash SDK-based JWT Authentication Manager
3
-
4
- Built entirely with Kailash SDK components - uses nodes and workflows
5
- for all authentication operations. This demonstrates enterprise-grade
6
- authentication using only Kailash patterns.
7
- """
8
-
9
- import json
10
- import logging
11
- import uuid
12
- from datetime import datetime, timedelta, timezone
13
- from typing import Any, Dict, List, Optional
14
-
15
- # Import Kailash SDK components only
16
- from kailash.nodes.base import Node, NodeParameter, register_node
17
- from kailash.nodes.code import PythonCodeNode
18
- from kailash.nodes.data import JSONReaderNode
19
- from kailash.nodes.logic import MergeNode, SwitchNode
20
- from kailash.nodes.security import CredentialManagerNode
21
- from kailash.runtime.local import LocalRuntime
22
- from kailash.workflow.builder import WorkflowBuilder
23
-
24
- logger = logging.getLogger(__name__)
25
-
26
-
27
- @register_node()
28
- class JWTConfigNode(Node):
29
- """Kailash node for JWT configuration management."""
30
-
31
- def __init__(self, name: str = "jwt_config"):
32
- super().__init__(name=name)
33
- self.algorithm = "HS256" # Use symmetric for simplicity with Kailash
34
- self.access_token_expire_minutes = 15
35
- self.refresh_token_expire_days = 7
36
- self.issuer = "kailash-middleware"
37
- self.audience = "kailash-api"
38
-
39
- def get_parameters(self) -> Dict[str, NodeParameter]:
40
- return {
41
- "algorithm": NodeParameter(
42
- name="algorithm",
43
- type=str,
44
- required=False,
45
- default="HS256",
46
- description="JWT signing algorithm",
47
- ),
48
- "access_expire_minutes": NodeParameter(
49
- name="access_expire_minutes",
50
- type=int,
51
- required=False,
52
- default=15,
53
- description="Access token expiration in minutes",
54
- ),
55
- "refresh_expire_days": NodeParameter(
56
- name="refresh_expire_days",
57
- type=int,
58
- required=False,
59
- default=7,
60
- description="Refresh token expiration in days",
61
- ),
62
- }
63
-
64
- def run(self, **kwargs) -> Dict[str, Any]:
65
- """Return JWT configuration."""
66
- return {
67
- "config": {
68
- "algorithm": getattr(self, "algorithm", "HS256"),
69
- "access_token_expire_minutes": getattr(
70
- self, "access_token_expire_minutes", 15
71
- ),
72
- "refresh_token_expire_days": getattr(
73
- self, "refresh_token_expire_days", 7
74
- ),
75
- "issuer": getattr(self, "issuer", "kailash-middleware"),
76
- "audience": getattr(self, "audience", "kailash-api"),
77
- }
78
- }
79
-
80
- async def process(self, inputs: Dict[str, Any]) -> Dict[str, Any]:
81
- """Async wrapper for middleware compatibility."""
82
- return self.run(**inputs)
83
-
84
-
85
- class TokenGeneratorNode(PythonCodeNode):
86
- """Kailash node for generating JWT tokens."""
87
-
88
- def __init__(self, name: str = "token_generator"):
89
- super().__init__(
90
- name=name,
91
- code="""
92
- import jwt
93
- import uuid
94
- from datetime import datetime, timedelta, timezone
95
-
96
- def generate_token(user_id, token_type='access', config=None, **claims):
97
- '''Generate JWT token using Kailash patterns'''
98
- config = config or {}
99
-
100
- now = datetime.now(timezone.utc)
101
-
102
- # Set expiration based on token type
103
- if token_type == 'access':
104
- expire_minutes = config.get('access_token_expire_minutes', 15)
105
- exp = now + timedelta(minutes=expire_minutes)
106
- else: # refresh
107
- expire_days = config.get('refresh_token_expire_days', 7)
108
- exp = now + timedelta(days=expire_days)
109
-
110
- # Create payload with Kailash conventions
111
- payload = {
112
- 'sub': user_id,
113
- 'iss': config.get('issuer', 'kailash-middleware'),
114
- 'aud': config.get('audience', 'kailash-api'),
115
- 'exp': int(exp.timestamp()),
116
- 'iat': int(now.timestamp()),
117
- 'jti': str(uuid.uuid4()),
118
- 'token_type': token_type,
119
- **claims
120
- }
121
-
122
- # Use simple secret for Kailash demo (in production, use proper key management)
123
- secret = config.get('secret', 'kailash-jwt-secret-key')
124
- algorithm = config.get('algorithm', 'HS256')
125
-
126
- token = jwt.encode(payload, secret, algorithm=algorithm)
127
-
128
- return {
129
- 'token': token,
130
- 'payload': payload,
131
- 'expires_at': exp.isoformat(),
132
- 'token_type': token_type
133
- }
134
-
135
- # Main execution
136
- user_id = input_data.get('user_id')
137
- token_type = input_data.get('token_type', 'access')
138
- config = input_data.get('config', {})
139
- claims = input_data.get('claims', {})
140
-
141
- if not user_id:
142
- result = {'error': 'user_id is required'}
143
- else:
144
- result = generate_token(user_id, token_type, config, **claims)
145
- """,
146
- )
147
-
148
-
149
- class TokenVerifierNode(PythonCodeNode):
150
- """Kailash node for verifying JWT tokens."""
151
-
152
- def __init__(self, name: str = "token_verifier"):
153
- super().__init__(
154
- name=name,
155
- code="""
156
- import jwt
157
- from datetime import datetime, timezone
158
-
159
- def verify_token(token, config=None, blacklisted_tokens=None):
160
- '''Verify JWT token using Kailash patterns'''
161
- config = config or {}
162
- blacklisted_tokens = blacklisted_tokens or set()
163
-
164
- try:
165
- # Check if token is blacklisted
166
- if token in blacklisted_tokens:
167
- return {
168
- 'valid': False,
169
- 'error': 'Token has been revoked',
170
- 'error_type': 'revoked'
171
- }
172
-
173
- # Verify token
174
- secret = config.get('secret', 'kailash-jwt-secret-key')
175
- algorithm = config.get('algorithm', 'HS256')
176
-
177
- payload = jwt.decode(
178
- token,
179
- secret,
180
- algorithms=[algorithm],
181
- issuer=config.get('issuer'),
182
- audience=config.get('audience')
183
- )
184
-
185
- return {
186
- 'valid': True,
187
- 'payload': payload,
188
- 'user_id': payload.get('sub'),
189
- 'token_type': payload.get('token_type', 'access'),
190
- 'expires_at': payload.get('exp'),
191
- 'permissions': payload.get('permissions', []),
192
- 'roles': payload.get('roles', []),
193
- 'tenant_id': payload.get('tenant_id'),
194
- 'session_id': payload.get('session_id')
195
- }
196
-
197
- except jwt.ExpiredSignatureError:
198
- return {
199
- 'valid': False,
200
- 'error': 'Token has expired',
201
- 'error_type': 'expired'
202
- }
203
- except jwt.InvalidTokenError as e:
204
- return {
205
- 'valid': False,
206
- 'error': str(e),
207
- 'error_type': 'invalid'
208
- }
209
- except Exception as e:
210
- return {
211
- 'valid': False,
212
- 'error': f'Token verification failed: {str(e)}',
213
- 'error_type': 'error'
214
- }
215
-
216
- # Main execution
217
- token = input_data.get('token')
218
- config = input_data.get('config', {})
219
- blacklisted_tokens = input_data.get('blacklisted_tokens', set())
220
-
221
- if not token:
222
- result = {'valid': False, 'error': 'Token is required', 'error_type': 'missing'}
223
- else:
224
- result = verify_token(token, config, blacklisted_tokens)
225
- """,
226
- )
227
-
228
-
229
- class RefreshTokenNode(PythonCodeNode):
230
- """Kailash node for handling token refresh."""
231
-
232
- def __init__(self, name: str = "refresh_token"):
233
- super().__init__(
234
- name=name,
235
- code="""
236
- def refresh_access_token(refresh_token_data, config, refresh_tracking):
237
- '''Refresh access token using Kailash patterns'''
238
-
239
- if not refresh_token_data.get('valid'):
240
- return {
241
- 'success': False,
242
- 'error': 'Invalid refresh token',
243
- 'error_type': 'invalid_refresh'
244
- }
245
-
246
- payload = refresh_token_data.get('payload', {})
247
-
248
- # Check token type
249
- if payload.get('token_type') != 'refresh':
250
- return {
251
- 'success': False,
252
- 'error': 'Token is not a refresh token',
253
- 'error_type': 'wrong_type'
254
- }
255
-
256
- jti = payload.get('jti')
257
- user_id = payload.get('sub')
258
-
259
- # Check refresh count (Kailash pattern for security)
260
- refresh_info = refresh_tracking.get(jti, {})
261
- max_refresh_count = config.get('max_refresh_count', 10)
262
-
263
- if refresh_info.get('refresh_count', 0) >= max_refresh_count:
264
- return {
265
- 'success': False,
266
- 'error': 'Refresh token has exceeded usage limit',
267
- 'error_type': 'limit_exceeded'
268
- }
269
-
270
- # Update refresh tracking
271
- refresh_info['refresh_count'] = refresh_info.get('refresh_count', 0) + 1
272
- refresh_info['last_used'] = datetime.now().isoformat()
273
- refresh_tracking[jti] = refresh_info
274
-
275
- # Prepare new token creation data
276
- return {
277
- 'success': True,
278
- 'user_id': user_id,
279
- 'tenant_id': payload.get('tenant_id'),
280
- 'session_id': payload.get('session_id'),
281
- 'permissions': payload.get('permissions', []),
282
- 'roles': payload.get('roles', []),
283
- 'refresh_tracking': refresh_tracking
284
- }
285
-
286
- # Main execution
287
- refresh_token_data = input_data.get('refresh_token_data', {})
288
- config = input_data.get('config', {})
289
- refresh_tracking = input_data.get('refresh_tracking', {})
290
-
291
- result = refresh_access_token(refresh_token_data, config, refresh_tracking)
292
- """,
293
- )
294
-
295
-
296
- class KailashJWTAuthManager:
297
- """
298
- JWT Authentication Manager built entirely with Kailash SDK components.
299
-
300
- This demonstrates enterprise-grade authentication using only Kailash
301
- nodes and workflows - no external dependencies beyond JWT library.
302
- """
303
-
304
- def __init__(self, secret_key: str = "kailash-jwt-secret-key"):
305
- self.secret_key = secret_key
306
- self.runtime = LocalRuntime()
307
-
308
- # State management using Kailash patterns
309
- self.blacklisted_tokens = set()
310
- self.refresh_tracking = {}
311
-
312
- # Create authentication workflows
313
- self._create_workflows()
314
-
315
- def _get_token_generator_code(self):
316
- """Get token generator code for PythonCodeNode."""
317
- return """
318
- import jwt
319
- import uuid
320
- from datetime import datetime, timedelta, timezone
321
-
322
- def generate_token(user_id, token_type='access', config=None, **claims):
323
- '''Generate JWT token using Kailash patterns'''
324
- config = config or {}
325
-
326
- now = datetime.now(timezone.utc)
327
-
328
- # Set expiration based on token type
329
- if token_type == 'access':
330
- expire_minutes = config.get('access_token_expire_minutes', 15)
331
- exp = now + timedelta(minutes=expire_minutes)
332
- else: # refresh
333
- expire_days = config.get('refresh_token_expire_days', 7)
334
- exp = now + timedelta(days=expire_days)
335
-
336
- # Create payload with Kailash conventions
337
- payload = {
338
- 'sub': user_id,
339
- 'iss': config.get('issuer', 'kailash-middleware'),
340
- 'aud': config.get('audience', 'kailash-api'),
341
- 'exp': int(exp.timestamp()),
342
- 'iat': int(now.timestamp()),
343
- 'jti': str(uuid.uuid4()),
344
- 'token_type': token_type,
345
- **claims
346
- }
347
-
348
- # Use simple secret for Kailash demo (in production, use proper key management)
349
- secret = config.get('secret', 'kailash-jwt-secret-key')
350
- algorithm = config.get('algorithm', 'HS256')
351
-
352
- token = jwt.encode(payload, secret, algorithm=algorithm)
353
-
354
- return {
355
- 'token': token,
356
- 'payload': payload,
357
- 'expires_at': exp.isoformat(),
358
- 'token_type': token_type
359
- }
360
-
361
- # Main execution
362
- user_id = input_data.get('user_id')
363
- token_type = input_data.get('token_type', 'access')
364
- config = input_data.get('config', {})
365
- claims = input_data.get('claims', {})
366
-
367
- if not user_id:
368
- result = {'error': 'user_id is required'}
369
- else:
370
- result = generate_token(user_id, token_type, config, **claims)
371
- """
372
-
373
- def _get_token_verifier_code(self):
374
- """Get token verifier code for PythonCodeNode."""
375
- return """
376
- import jwt
377
- from datetime import datetime, timezone
378
-
379
- def verify_token(token, config=None, blacklisted_tokens=None):
380
- config = config or {}
381
- blacklisted_tokens = blacklisted_tokens or set()
382
-
383
- try:
384
- if token in blacklisted_tokens:
385
- return {'valid': False, 'error': 'Token has been revoked', 'error_type': 'revoked'}
386
-
387
- secret = config.get('secret', 'kailash-jwt-secret-key')
388
- algorithm = config.get('algorithm', 'HS256')
389
-
390
- payload = jwt.decode(token, secret, algorithms=[algorithm])
391
-
392
- return {
393
- 'valid': True,
394
- 'payload': payload,
395
- 'user_id': payload.get('sub'),
396
- 'token_type': payload.get('token_type', 'access')
397
- }
398
-
399
- except jwt.ExpiredSignatureError:
400
- return {'valid': False, 'error': 'Token has expired', 'error_type': 'expired'}
401
- except jwt.InvalidTokenError as e:
402
- return {'valid': False, 'error': str(e), 'error_type': 'invalid'}
403
- except Exception as e:
404
- return {'valid': False, 'error': f'Token verification failed: {str(e)}', 'error_type': 'error'}
405
-
406
- token = input_data.get('token')
407
- config = input_data.get('config', {})
408
- blacklisted_tokens = input_data.get('blacklisted_tokens', set())
409
-
410
- if not token:
411
- result = {'valid': False, 'error': 'Token is required', 'error_type': 'missing'}
412
- else:
413
- result = verify_token(token, config, blacklisted_tokens)
414
- """
415
-
416
- def _create_workflows(self):
417
- """Create Kailash workflows for authentication operations."""
418
-
419
- # Token Creation Workflow
420
- self.token_workflow = WorkflowBuilder()
421
-
422
- config_id = self.token_workflow.add_node(
423
- "JWTConfigNode", "jwt_config", {"name": "jwt_config"}
424
- )
425
- token_id = self.token_workflow.add_node(
426
- "PythonCodeNode",
427
- "generate_token",
428
- {"name": "generate_token", "code": self._get_token_generator_code()},
429
- )
430
-
431
- self.token_workflow.add_connection(config_id, "config", token_id, "config")
432
-
433
- # Token Verification Workflow
434
- self.verify_workflow = WorkflowBuilder()
435
-
436
- config_verify_id = self.verify_workflow.add_node(
437
- "JWTConfigNode", "jwt_config_verify", {"name": "jwt_config_verify"}
438
- )
439
- verify_id = self.verify_workflow.add_node(
440
- "PythonCodeNode",
441
- "verify_token",
442
- {"name": "verify_token", "code": self._get_token_verifier_code()},
443
- )
444
-
445
- self.verify_workflow.add_connection(
446
- config_verify_id, "config", verify_id, "config"
447
- )
448
-
449
- # For simplicity, we'll use direct verification in methods instead of complex workflows
450
-
451
- def create_access_token(
452
- self,
453
- user_id: str,
454
- tenant_id: str = None,
455
- session_id: str = None,
456
- permissions: List[str] = None,
457
- roles: List[str] = None,
458
- ) -> str:
459
- """Create access token using Kailash workflow."""
460
-
461
- claims = {}
462
- if tenant_id:
463
- claims["tenant_id"] = tenant_id
464
- if session_id:
465
- claims["session_id"] = session_id
466
- if permissions:
467
- claims["permissions"] = permissions
468
- if roles:
469
- claims["roles"] = roles
470
-
471
- inputs = {
472
- "user_id": user_id,
473
- "token_type": "access",
474
- "claims": claims,
475
- "config": {"secret": self.secret_key},
476
- }
477
-
478
- # Execute Kailash workflow
479
- workflow = self.token_workflow.build()
480
- results, _ = self.runtime.execute(workflow, parameters=inputs)
481
-
482
- return results.get("generate_token", {}).get("token")
483
-
484
- def create_refresh_token(
485
- self, user_id: str, tenant_id: str = None, session_id: str = None
486
- ) -> str:
487
- """Create refresh token using Kailash workflow."""
488
-
489
- claims = {}
490
- if tenant_id:
491
- claims["tenant_id"] = tenant_id
492
- if session_id:
493
- claims["session_id"] = session_id
494
-
495
- inputs = {
496
- "user_id": user_id,
497
- "token_type": "refresh",
498
- "claims": claims,
499
- "config": {"secret": self.secret_key},
500
- }
501
-
502
- # Execute Kailash workflow
503
- workflow = self.token_workflow.build()
504
- results, _ = self.runtime.execute(workflow, parameters=inputs)
505
-
506
- token_result = results.get("generate_token", {})
507
- token = token_result.get("token")
508
-
509
- # Track refresh token in Kailash pattern
510
- if token:
511
- payload = token_result.get("payload", {})
512
- jti = payload.get("jti")
513
- if jti:
514
- self.refresh_tracking[jti] = {
515
- "user_id": user_id,
516
- "tenant_id": tenant_id,
517
- "session_id": session_id,
518
- "created_at": datetime.now(timezone.utc).isoformat(),
519
- "refresh_count": 0,
520
- }
521
-
522
- return token
523
-
524
- def create_token_pair(
525
- self,
526
- user_id: str,
527
- tenant_id: str = None,
528
- session_id: str = None,
529
- permissions: List[str] = None,
530
- roles: List[str] = None,
531
- ) -> Dict[str, Any]:
532
- """Create access and refresh token pair using Kailash workflows."""
533
-
534
- access_token = self.create_access_token(
535
- user_id, tenant_id, session_id, permissions, roles
536
- )
537
- refresh_token = self.create_refresh_token(user_id, tenant_id, session_id)
538
-
539
- return {
540
- "access_token": access_token,
541
- "refresh_token": refresh_token,
542
- "token_type": "Bearer",
543
- "expires_in": 15 * 60, # 15 minutes in seconds
544
- "scope": "kailash-api",
545
- }
546
-
547
- def verify_token(self, token: str) -> Dict[str, Any]:
548
- """Verify token using Kailash workflow."""
549
-
550
- inputs = {
551
- "token": token,
552
- "config": {"secret": self.secret_key},
553
- "blacklisted_tokens": self.blacklisted_tokens,
554
- }
555
-
556
- # Execute Kailash verification workflow
557
- workflow = self.verify_workflow.build()
558
- results, _ = self.runtime.execute(workflow, parameters=inputs)
559
-
560
- return results.get("verify_token", {})
561
-
562
- def refresh_access_token(self, refresh_token: str) -> Dict[str, Any]:
563
- """Refresh access token using simplified Kailash pattern."""
564
-
565
- # Verify the refresh token
566
- verify_result = self.verify_token(refresh_token)
567
-
568
- if not verify_result.get("valid"):
569
- return {"success": False, "error": "Invalid refresh token"}
570
-
571
- payload = verify_result.get("payload", {})
572
-
573
- if payload.get("token_type") != "refresh":
574
- return {"success": False, "error": "Token is not a refresh token"}
575
-
576
- # Create new token pair
577
- return self.create_token_pair(
578
- user_id=payload.get("sub"),
579
- tenant_id=payload.get("tenant_id"),
580
- session_id=payload.get("session_id"),
581
- permissions=payload.get("permissions", []),
582
- roles=payload.get("roles", []),
583
- )
584
-
585
- def revoke_token(self, token: str):
586
- """Revoke token by adding to blacklist (Kailash pattern)."""
587
- self.blacklisted_tokens.add(token)
588
- logger.info(f"Revoked token (length: {len(token)})")
589
-
590
- def revoke_all_user_tokens(self, user_id: str):
591
- """Revoke all tokens for a user (Kailash pattern)."""
592
- # Remove all refresh tokens for user
593
- to_remove = []
594
- for jti, data in self.refresh_tracking.items():
595
- if data.get("user_id") == user_id:
596
- to_remove.append(jti)
597
-
598
- for jti in to_remove:
599
- del self.refresh_tracking[jti]
600
-
601
- logger.info(f"Revoked all tokens for user {user_id}")
602
-
603
- def get_stats(self) -> Dict[str, Any]:
604
- """Get authentication statistics (Kailash pattern)."""
605
- return {
606
- "active_refresh_tokens": len(self.refresh_tracking),
607
- "blacklisted_tokens": len(self.blacklisted_tokens),
608
- "auth_manager": "KailashJWTAuthManager",
609
- "workflow_runtime": "LocalRuntime",
610
- "nodes_used": [
611
- "JWTConfigNode",
612
- "TokenGeneratorNode",
613
- "TokenVerifierNode",
614
- "RefreshTokenNode",
615
- ],
616
- }