trishul-oauth-client 0.1.0__tar.gz
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.
- trishul_oauth_client-0.1.0/.gitignore +134 -0
- trishul_oauth_client-0.1.0/PKG-INFO +205 -0
- trishul_oauth_client-0.1.0/README.md +169 -0
- trishul_oauth_client-0.1.0/playground.py +43 -0
- trishul_oauth_client-0.1.0/pyproject.toml +53 -0
- trishul_oauth_client-0.1.0/tests/__init__.py +1 -0
- trishul_oauth_client-0.1.0/tests/test_client.py +110 -0
- trishul_oauth_client-0.1.0/trishul_oauth/__init__.py +33 -0
- trishul_oauth_client-0.1.0/trishul_oauth/client.py +727 -0
- trishul_oauth_client-0.1.0/trishul_oauth/integrations/__init__.py +1 -0
- trishul_oauth_client-0.1.0/trishul_oauth/integrations/django.py +81 -0
- trishul_oauth_client-0.1.0/trishul_oauth/integrations/fastapi.py +63 -0
- trishul_oauth_client-0.1.0/trishul_oauth/integrations/flask.py +77 -0
- trishul_oauth_client-0.1.0/trishul_oauth/storage.py +80 -0
- trishul_oauth_client-0.1.0/trishul_oauth/types.py +95 -0
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
# Logs
|
|
2
|
+
logs
|
|
3
|
+
*.log
|
|
4
|
+
npm-debug.log*
|
|
5
|
+
yarn-debug.log*
|
|
6
|
+
yarn-error.log*
|
|
7
|
+
lerna-debug.log*
|
|
8
|
+
.pnpm-debug.log*
|
|
9
|
+
|
|
10
|
+
# Diagnostic reports (https://nodejs.org/api/report.html)
|
|
11
|
+
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
|
12
|
+
|
|
13
|
+
# Runtime data
|
|
14
|
+
pids
|
|
15
|
+
*.pid
|
|
16
|
+
*.seed
|
|
17
|
+
*.pid.lock
|
|
18
|
+
|
|
19
|
+
# Directory for instrumented libs generated by jscoverage/JSCover
|
|
20
|
+
lib-cov
|
|
21
|
+
|
|
22
|
+
# Coverage directory used by tools like istanbul
|
|
23
|
+
coverage
|
|
24
|
+
*.lcov
|
|
25
|
+
|
|
26
|
+
# nyc test coverage
|
|
27
|
+
.nyc_output
|
|
28
|
+
|
|
29
|
+
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
|
30
|
+
.grunt
|
|
31
|
+
|
|
32
|
+
# Bower dependency directory (https://bower.io/)
|
|
33
|
+
bower_components
|
|
34
|
+
|
|
35
|
+
# node-waf configuration
|
|
36
|
+
.lock-wscript
|
|
37
|
+
|
|
38
|
+
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
|
39
|
+
build/Release
|
|
40
|
+
|
|
41
|
+
# Dependency directories
|
|
42
|
+
node_modules/
|
|
43
|
+
jspm_packages/
|
|
44
|
+
|
|
45
|
+
# Snowpack dependency directory (https://snowpack.dev/)
|
|
46
|
+
web_modules/
|
|
47
|
+
|
|
48
|
+
# TypeScript cache
|
|
49
|
+
*.tsbuildinfo
|
|
50
|
+
|
|
51
|
+
# Optional npm cache directory
|
|
52
|
+
.npm
|
|
53
|
+
|
|
54
|
+
# Optional eslint cache
|
|
55
|
+
.eslintcache
|
|
56
|
+
|
|
57
|
+
# Microbundle cache
|
|
58
|
+
.rpt2_cache/
|
|
59
|
+
.rts2_cache_cjs/
|
|
60
|
+
.rts2_cache_es/
|
|
61
|
+
.rts2_cache_umd/
|
|
62
|
+
|
|
63
|
+
# Optional REPL history
|
|
64
|
+
.node_repl_history
|
|
65
|
+
|
|
66
|
+
# Output of 'npm pack'
|
|
67
|
+
*.tgz
|
|
68
|
+
|
|
69
|
+
# Yarn Integrity file
|
|
70
|
+
.yarn-integrity
|
|
71
|
+
|
|
72
|
+
# dotenv environment variables file
|
|
73
|
+
.env
|
|
74
|
+
.env.test
|
|
75
|
+
.env.production
|
|
76
|
+
.env.local
|
|
77
|
+
.env.development.local
|
|
78
|
+
.env.test.local
|
|
79
|
+
.env.production.local
|
|
80
|
+
|
|
81
|
+
# parcel-bundler cache (https://parceljs.org/)
|
|
82
|
+
.cache
|
|
83
|
+
.parcel-cache
|
|
84
|
+
|
|
85
|
+
# Next.js build output
|
|
86
|
+
.next
|
|
87
|
+
out
|
|
88
|
+
|
|
89
|
+
# Nuxt.js build output
|
|
90
|
+
.nuxt
|
|
91
|
+
dist
|
|
92
|
+
|
|
93
|
+
# Gatsby files
|
|
94
|
+
.cache/
|
|
95
|
+
# Comment in the public line in if your project uses Gatsby and not Next.js
|
|
96
|
+
# public
|
|
97
|
+
|
|
98
|
+
# Identity service React build output (generated by vite build)
|
|
99
|
+
services/identity-service/src/public/auth-ui/
|
|
100
|
+
|
|
101
|
+
# vuepress build output
|
|
102
|
+
.vuepress/dist
|
|
103
|
+
|
|
104
|
+
# Serverless directories
|
|
105
|
+
.serverless/
|
|
106
|
+
|
|
107
|
+
# FuseBox cache
|
|
108
|
+
.fusebox/
|
|
109
|
+
|
|
110
|
+
# DynamoDB Local files
|
|
111
|
+
.dynamodb/
|
|
112
|
+
|
|
113
|
+
# TernJS port file
|
|
114
|
+
.tern-port
|
|
115
|
+
|
|
116
|
+
# Stores VSCode versions used for testing VSCode extensions
|
|
117
|
+
.vscode-test
|
|
118
|
+
|
|
119
|
+
# yarn v2
|
|
120
|
+
.yarn/cache
|
|
121
|
+
.yarn/unplugged
|
|
122
|
+
.yarn/build-state.yml
|
|
123
|
+
.yarn/install-state.gz
|
|
124
|
+
.pnp.*
|
|
125
|
+
|
|
126
|
+
.DS_Store
|
|
127
|
+
|
|
128
|
+
# Enterprise Roadmap
|
|
129
|
+
docs/enterprise_roadmap.md
|
|
130
|
+
|
|
131
|
+
scratch/*
|
|
132
|
+
|
|
133
|
+
# Claude
|
|
134
|
+
.claude/settings.local.json
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: trishul-oauth-client
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Enterprise-grade OIDC/OAuth client library for Python (FastAPI, Flask, Django)
|
|
5
|
+
Project-URL: Homepage, https://trishuliam.com
|
|
6
|
+
Project-URL: Repository, https://github.com/shubhamssinghs/trishul-iam
|
|
7
|
+
Author-email: TrishulIAM Team <team@trishuliam.com>
|
|
8
|
+
License: MIT
|
|
9
|
+
Classifier: Development Status :: 4 - Beta
|
|
10
|
+
Classifier: Intended Audience :: Developers
|
|
11
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Topic :: Security
|
|
19
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
20
|
+
Requires-Python: >=3.8
|
|
21
|
+
Requires-Dist: httpx>=0.24.0
|
|
22
|
+
Requires-Dist: pyjwt[crypto]>=2.8.0
|
|
23
|
+
Provides-Extra: dev
|
|
24
|
+
Requires-Dist: black>=23.0.0; extra == 'dev'
|
|
25
|
+
Requires-Dist: mypy>=1.0.0; extra == 'dev'
|
|
26
|
+
Requires-Dist: pytest-asyncio>=0.21.0; extra == 'dev'
|
|
27
|
+
Requires-Dist: pytest>=7.0.0; extra == 'dev'
|
|
28
|
+
Requires-Dist: respx>=0.20.0; extra == 'dev'
|
|
29
|
+
Provides-Extra: django
|
|
30
|
+
Requires-Dist: django>=4.0.0; extra == 'django'
|
|
31
|
+
Provides-Extra: fastapi
|
|
32
|
+
Requires-Dist: fastapi>=0.100.0; extra == 'fastapi'
|
|
33
|
+
Provides-Extra: flask
|
|
34
|
+
Requires-Dist: flask>=2.0.0; extra == 'flask'
|
|
35
|
+
Description-Content-Type: text/markdown
|
|
36
|
+
|
|
37
|
+
# Trishul OAuth Client for Python
|
|
38
|
+
|
|
39
|
+
An enterprise-grade, highly secure OIDC/OAuth 2.0 client library for Python. Supports standard OIDC authorization code flow with secure PKCE validation, state validation, and plug-and-play integrations for **FastAPI**, **Flask**, and **Django**.
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Features
|
|
44
|
+
|
|
45
|
+
- **Sync & Async Core Engine**: Fully support both sync and async frameworks out-of-the-box.
|
|
46
|
+
- **Secure PKCE (S256)**: Auto-generated PKCE verification pairs for absolute security against code interception attacks.
|
|
47
|
+
- **OIDC Discovery Configuration**: Automatic parsing and local caching of the openid-configuration metadata.
|
|
48
|
+
- **Cryptographic Signature Verification**: Validates ID Token signatures locally using the server's JWKS endpoint.
|
|
49
|
+
- **Automatic Silent Token Rotation**: Seamless refresh-token based token rotation without user disruption.
|
|
50
|
+
- **Out-of-the-Box Web Framework Integrations** for:
|
|
51
|
+
- **FastAPI / Starlette**
|
|
52
|
+
- **Flask**
|
|
53
|
+
- **Django**
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## Installation
|
|
58
|
+
|
|
59
|
+
Install from PyPI (once published):
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
pip install trishul-oauth-client
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Or install with framework-specific dependency packages:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
# For FastAPI
|
|
69
|
+
pip install "trishul-oauth-client[fastapi]"
|
|
70
|
+
|
|
71
|
+
# For Flask
|
|
72
|
+
pip install "trishul-oauth-client[flask]"
|
|
73
|
+
|
|
74
|
+
# For Django
|
|
75
|
+
pip install "trishul-oauth-client[django]"
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## Quickstart
|
|
81
|
+
|
|
82
|
+
### 1. Initialize Client
|
|
83
|
+
```python
|
|
84
|
+
from trishul_oauth import TrishulOAuth, MemoryStorage
|
|
85
|
+
|
|
86
|
+
client = TrishulOAuth({
|
|
87
|
+
"issuer": "https://identity.yourdomain.com",
|
|
88
|
+
"clientId": "your_client_id",
|
|
89
|
+
"clientSecret": "your_client_secret",
|
|
90
|
+
"redirectUri": "http://localhost:8000/callback",
|
|
91
|
+
"usePKCE": True,
|
|
92
|
+
})
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## Web Framework Integrations
|
|
98
|
+
|
|
99
|
+
### 1. FastAPI / Starlette
|
|
100
|
+
Fully async dependency injection provider:
|
|
101
|
+
|
|
102
|
+
```python
|
|
103
|
+
from fastapi import FastAPI, Depends, HTTPException
|
|
104
|
+
from trishul_oauth import TrishulOAuth
|
|
105
|
+
from trishul_oauth.integrations.fastapi import TrishulSecurity
|
|
106
|
+
|
|
107
|
+
app = FastAPI()
|
|
108
|
+
client = TrishulOAuth({
|
|
109
|
+
"issuer": "https://identity.yourdomain.com",
|
|
110
|
+
"clientId": "your_client_id",
|
|
111
|
+
"redirectUri": "http://localhost:8000/callback",
|
|
112
|
+
})
|
|
113
|
+
|
|
114
|
+
# Initialize FastAPI Security provider
|
|
115
|
+
security = TrishulSecurity(client)
|
|
116
|
+
|
|
117
|
+
@app.get("/api/dashboard")
|
|
118
|
+
async def dashboard(user = Depends(security.require_auth(scopes=["profile"]))):
|
|
119
|
+
return {
|
|
120
|
+
"status": "success",
|
|
121
|
+
"message": f"Welcome back, {user.get('name')}!",
|
|
122
|
+
"profile": user
|
|
123
|
+
}
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### 2. Flask
|
|
127
|
+
Clean view decorators and session injectors:
|
|
128
|
+
|
|
129
|
+
```python
|
|
130
|
+
from flask import Flask, session, render_template
|
|
131
|
+
from trishul_oauth import TrishulOAuth
|
|
132
|
+
from trishul_oauth.integrations.flask import FlaskOAuth
|
|
133
|
+
|
|
134
|
+
app = Flask(__name__)
|
|
135
|
+
app.secret_key = "your_super_secret_session_key"
|
|
136
|
+
|
|
137
|
+
client = TrishulOAuth({
|
|
138
|
+
"issuer": "https://identity.yourdomain.com",
|
|
139
|
+
"clientId": "your_client_id",
|
|
140
|
+
"clientSecret": "your_client_secret",
|
|
141
|
+
"redirectUri": "http://localhost:5000/callback",
|
|
142
|
+
})
|
|
143
|
+
|
|
144
|
+
oauth = FlaskOAuth(client)
|
|
145
|
+
|
|
146
|
+
@app.route("/dashboard")
|
|
147
|
+
@oauth.require_auth(scopes=["profile"])
|
|
148
|
+
def dashboard():
|
|
149
|
+
# Retrieve user info from global Flask context
|
|
150
|
+
user = oauth.current_user
|
|
151
|
+
return f"Welcome back, {user['name']}!"
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### 3. Django
|
|
155
|
+
Middleware and view decorators for robust authentication:
|
|
156
|
+
|
|
157
|
+
```python
|
|
158
|
+
# settings.py
|
|
159
|
+
INSTALLED_APPS = [
|
|
160
|
+
...
|
|
161
|
+
'django.contrib.sessions',
|
|
162
|
+
]
|
|
163
|
+
|
|
164
|
+
MIDDLEWARE = [
|
|
165
|
+
...
|
|
166
|
+
'django.contrib.sessions.middleware.SessionMiddleware',
|
|
167
|
+
'trishul_oauth.integrations.django.TrishulOAuthMiddleware',
|
|
168
|
+
]
|
|
169
|
+
|
|
170
|
+
from trishul_oauth import TrishulOAuth
|
|
171
|
+
TRISHUL_OAUTH_CLIENT = TrishulOAuth({
|
|
172
|
+
"issuer": "https://identity.yourdomain.com",
|
|
173
|
+
"clientId": "your_client_id",
|
|
174
|
+
"clientSecret": "your_client_secret",
|
|
175
|
+
})
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
# views.py
|
|
179
|
+
from django.http import JsonResponse
|
|
180
|
+
from trishul_oauth.integrations.django import require_auth
|
|
181
|
+
|
|
182
|
+
@require_auth(scopes=["profile"])
|
|
183
|
+
def dashboard_view(request):
|
|
184
|
+
user = request.trishul_user
|
|
185
|
+
return JsonResponse({
|
|
186
|
+
"status": "success",
|
|
187
|
+
"user": user
|
|
188
|
+
})
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
---
|
|
192
|
+
|
|
193
|
+
## Running Package Tests
|
|
194
|
+
|
|
195
|
+
Verify everything runs cleanly using `pytest`:
|
|
196
|
+
|
|
197
|
+
```bash
|
|
198
|
+
pytest tests/
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
---
|
|
202
|
+
|
|
203
|
+
## License
|
|
204
|
+
|
|
205
|
+
MIT License. See [LICENSE](LICENSE) for details.
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
# Trishul OAuth Client for Python
|
|
2
|
+
|
|
3
|
+
An enterprise-grade, highly secure OIDC/OAuth 2.0 client library for Python. Supports standard OIDC authorization code flow with secure PKCE validation, state validation, and plug-and-play integrations for **FastAPI**, **Flask**, and **Django**.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- **Sync & Async Core Engine**: Fully support both sync and async frameworks out-of-the-box.
|
|
10
|
+
- **Secure PKCE (S256)**: Auto-generated PKCE verification pairs for absolute security against code interception attacks.
|
|
11
|
+
- **OIDC Discovery Configuration**: Automatic parsing and local caching of the openid-configuration metadata.
|
|
12
|
+
- **Cryptographic Signature Verification**: Validates ID Token signatures locally using the server's JWKS endpoint.
|
|
13
|
+
- **Automatic Silent Token Rotation**: Seamless refresh-token based token rotation without user disruption.
|
|
14
|
+
- **Out-of-the-Box Web Framework Integrations** for:
|
|
15
|
+
- **FastAPI / Starlette**
|
|
16
|
+
- **Flask**
|
|
17
|
+
- **Django**
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Installation
|
|
22
|
+
|
|
23
|
+
Install from PyPI (once published):
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
pip install trishul-oauth-client
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Or install with framework-specific dependency packages:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
# For FastAPI
|
|
33
|
+
pip install "trishul-oauth-client[fastapi]"
|
|
34
|
+
|
|
35
|
+
# For Flask
|
|
36
|
+
pip install "trishul-oauth-client[flask]"
|
|
37
|
+
|
|
38
|
+
# For Django
|
|
39
|
+
pip install "trishul-oauth-client[django]"
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## Quickstart
|
|
45
|
+
|
|
46
|
+
### 1. Initialize Client
|
|
47
|
+
```python
|
|
48
|
+
from trishul_oauth import TrishulOAuth, MemoryStorage
|
|
49
|
+
|
|
50
|
+
client = TrishulOAuth({
|
|
51
|
+
"issuer": "https://identity.yourdomain.com",
|
|
52
|
+
"clientId": "your_client_id",
|
|
53
|
+
"clientSecret": "your_client_secret",
|
|
54
|
+
"redirectUri": "http://localhost:8000/callback",
|
|
55
|
+
"usePKCE": True,
|
|
56
|
+
})
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## Web Framework Integrations
|
|
62
|
+
|
|
63
|
+
### 1. FastAPI / Starlette
|
|
64
|
+
Fully async dependency injection provider:
|
|
65
|
+
|
|
66
|
+
```python
|
|
67
|
+
from fastapi import FastAPI, Depends, HTTPException
|
|
68
|
+
from trishul_oauth import TrishulOAuth
|
|
69
|
+
from trishul_oauth.integrations.fastapi import TrishulSecurity
|
|
70
|
+
|
|
71
|
+
app = FastAPI()
|
|
72
|
+
client = TrishulOAuth({
|
|
73
|
+
"issuer": "https://identity.yourdomain.com",
|
|
74
|
+
"clientId": "your_client_id",
|
|
75
|
+
"redirectUri": "http://localhost:8000/callback",
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
# Initialize FastAPI Security provider
|
|
79
|
+
security = TrishulSecurity(client)
|
|
80
|
+
|
|
81
|
+
@app.get("/api/dashboard")
|
|
82
|
+
async def dashboard(user = Depends(security.require_auth(scopes=["profile"]))):
|
|
83
|
+
return {
|
|
84
|
+
"status": "success",
|
|
85
|
+
"message": f"Welcome back, {user.get('name')}!",
|
|
86
|
+
"profile": user
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### 2. Flask
|
|
91
|
+
Clean view decorators and session injectors:
|
|
92
|
+
|
|
93
|
+
```python
|
|
94
|
+
from flask import Flask, session, render_template
|
|
95
|
+
from trishul_oauth import TrishulOAuth
|
|
96
|
+
from trishul_oauth.integrations.flask import FlaskOAuth
|
|
97
|
+
|
|
98
|
+
app = Flask(__name__)
|
|
99
|
+
app.secret_key = "your_super_secret_session_key"
|
|
100
|
+
|
|
101
|
+
client = TrishulOAuth({
|
|
102
|
+
"issuer": "https://identity.yourdomain.com",
|
|
103
|
+
"clientId": "your_client_id",
|
|
104
|
+
"clientSecret": "your_client_secret",
|
|
105
|
+
"redirectUri": "http://localhost:5000/callback",
|
|
106
|
+
})
|
|
107
|
+
|
|
108
|
+
oauth = FlaskOAuth(client)
|
|
109
|
+
|
|
110
|
+
@app.route("/dashboard")
|
|
111
|
+
@oauth.require_auth(scopes=["profile"])
|
|
112
|
+
def dashboard():
|
|
113
|
+
# Retrieve user info from global Flask context
|
|
114
|
+
user = oauth.current_user
|
|
115
|
+
return f"Welcome back, {user['name']}!"
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### 3. Django
|
|
119
|
+
Middleware and view decorators for robust authentication:
|
|
120
|
+
|
|
121
|
+
```python
|
|
122
|
+
# settings.py
|
|
123
|
+
INSTALLED_APPS = [
|
|
124
|
+
...
|
|
125
|
+
'django.contrib.sessions',
|
|
126
|
+
]
|
|
127
|
+
|
|
128
|
+
MIDDLEWARE = [
|
|
129
|
+
...
|
|
130
|
+
'django.contrib.sessions.middleware.SessionMiddleware',
|
|
131
|
+
'trishul_oauth.integrations.django.TrishulOAuthMiddleware',
|
|
132
|
+
]
|
|
133
|
+
|
|
134
|
+
from trishul_oauth import TrishulOAuth
|
|
135
|
+
TRISHUL_OAUTH_CLIENT = TrishulOAuth({
|
|
136
|
+
"issuer": "https://identity.yourdomain.com",
|
|
137
|
+
"clientId": "your_client_id",
|
|
138
|
+
"clientSecret": "your_client_secret",
|
|
139
|
+
})
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
# views.py
|
|
143
|
+
from django.http import JsonResponse
|
|
144
|
+
from trishul_oauth.integrations.django import require_auth
|
|
145
|
+
|
|
146
|
+
@require_auth(scopes=["profile"])
|
|
147
|
+
def dashboard_view(request):
|
|
148
|
+
user = request.trishul_user
|
|
149
|
+
return JsonResponse({
|
|
150
|
+
"status": "success",
|
|
151
|
+
"user": user
|
|
152
|
+
})
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
---
|
|
156
|
+
|
|
157
|
+
## Running Package Tests
|
|
158
|
+
|
|
159
|
+
Verify everything runs cleanly using `pytest`:
|
|
160
|
+
|
|
161
|
+
```bash
|
|
162
|
+
pytest tests/
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
## License
|
|
168
|
+
|
|
169
|
+
MIT License. See [LICENSE](LICENSE) for details.
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
import os
|
|
3
|
+
import sys
|
|
4
|
+
|
|
5
|
+
from trishul_oauth import TrishulOAuth, TrishulOAuthError
|
|
6
|
+
|
|
7
|
+
async def main():
|
|
8
|
+
print("=== Trishul OAuth Client Python Playground ===")
|
|
9
|
+
|
|
10
|
+
# 1. Initialize Client pointing to local identity service
|
|
11
|
+
config = {
|
|
12
|
+
"issuer": os.getenv("TRISHUL_ISSUER", "http://localhost:3001"),
|
|
13
|
+
"clientId": os.getenv("TRISHUL_CLIENT_ID", "test_client"),
|
|
14
|
+
"redirectUri": "http://localhost:8000/callback",
|
|
15
|
+
"usePKCE": True,
|
|
16
|
+
"debug": True,
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
print(f"Connecting to Identity Issuer: {config['issuer']}")
|
|
20
|
+
client = TrishulOAuth(config)
|
|
21
|
+
|
|
22
|
+
try:
|
|
23
|
+
# 2. Fetch OIDC Configuration
|
|
24
|
+
print("\n1. Querying OpenID Discovery endpoint...")
|
|
25
|
+
discovery = await client.async_get_discovery()
|
|
26
|
+
print(f"✅ Success! Token Endpoint: {discovery['token_endpoint']}")
|
|
27
|
+
|
|
28
|
+
# 3. Create redirect authorize URL
|
|
29
|
+
print("\n2. Generating OIDC Authorization redirect URL...")
|
|
30
|
+
auth_data = await client.async_create_authorization_url()
|
|
31
|
+
print(f"✅ Authorization URL: {auth_data['url']}")
|
|
32
|
+
print(f"🔑 Saved Verification State: {auth_data['state']}")
|
|
33
|
+
|
|
34
|
+
print("\nReady to authenticate. Push to repository to trigger GHA pipeline!")
|
|
35
|
+
|
|
36
|
+
except TrishulOAuthError as e:
|
|
37
|
+
print(f"❌ Error during OIDC communication: {str(e)}")
|
|
38
|
+
if e.original_error:
|
|
39
|
+
print(f"Details: {e.original_error}")
|
|
40
|
+
sys.exit(1)
|
|
41
|
+
|
|
42
|
+
if __name__ == "__main__":
|
|
43
|
+
asyncio.run(main())
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "trishul-oauth-client"
|
|
7
|
+
dynamic = ["version"]
|
|
8
|
+
description = "Enterprise-grade OIDC/OAuth client library for Python (FastAPI, Flask, Django)"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.8"
|
|
11
|
+
license = { text = "MIT" }
|
|
12
|
+
authors = [
|
|
13
|
+
{ name = "TrishulIAM Team", email = "team@trishuliam.com" }
|
|
14
|
+
]
|
|
15
|
+
classifiers = [
|
|
16
|
+
"Development Status :: 4 - Beta",
|
|
17
|
+
"Intended Audience :: Developers",
|
|
18
|
+
"License :: OSI Approved :: MIT License",
|
|
19
|
+
"Programming Language :: Python :: 3",
|
|
20
|
+
"Programming Language :: Python :: 3.8",
|
|
21
|
+
"Programming Language :: Python :: 3.9",
|
|
22
|
+
"Programming Language :: Python :: 3.10",
|
|
23
|
+
"Programming Language :: Python :: 3.11",
|
|
24
|
+
"Programming Language :: Python :: 3.12",
|
|
25
|
+
"Topic :: Security",
|
|
26
|
+
"Topic :: Software Development :: Libraries :: Python Modules"
|
|
27
|
+
]
|
|
28
|
+
dependencies = [
|
|
29
|
+
"httpx>=0.24.0",
|
|
30
|
+
"pyjwt[crypto]>=2.8.0",
|
|
31
|
+
]
|
|
32
|
+
|
|
33
|
+
[project.optional-dependencies]
|
|
34
|
+
fastapi = ["fastapi>=0.100.0"]
|
|
35
|
+
flask = ["flask>=2.0.0"]
|
|
36
|
+
django = ["django>=4.0.0"]
|
|
37
|
+
dev = [
|
|
38
|
+
"pytest>=7.0.0",
|
|
39
|
+
"pytest-asyncio>=0.21.0",
|
|
40
|
+
"respx>=0.20.0",
|
|
41
|
+
"black>=23.0.0",
|
|
42
|
+
"mypy>=1.0.0"
|
|
43
|
+
]
|
|
44
|
+
|
|
45
|
+
[project.urls]
|
|
46
|
+
Homepage = "https://trishuliam.com"
|
|
47
|
+
Repository = "https://github.com/shubhamssinghs/trishul-iam"
|
|
48
|
+
|
|
49
|
+
[tool.hatch.version]
|
|
50
|
+
path = "trishul_oauth/__init__.py"
|
|
51
|
+
|
|
52
|
+
[tool.hatch.build.targets.wheel]
|
|
53
|
+
packages = ["trishul_oauth"]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# Trishul OAuth Client tests subpackage.
|