SCG JWT Token for Python
A simple, secure, and universal JWT library for web and mobile applications.
Installation
pip install scg-jwt-token
Quick Start
from scg_jwt_token import SCGJwtToken
# Create JWT instance
jwt = SCGJwtToken("your-secret-key")
# Create token
token = jwt.sign({
"user_id": 123,
"email": "user@example.com",
"role": "user"
})
# Verify token
try:
payload = jwt.verify(token)
print(f"User: {payload['email']}")
except ValueError as e:
print(f"Invalid token: {e}")
Features
- Stateless: No database storage needed for tokens
- Secure: Uses HMAC SHA-256 with proper JWT standards
- Universal: Works with web apps, mobile apps, APIs, and microservices
- Zero Dependencies: Pure Python implementation
- Type Hints: Full TypeScript-style type annotations
- Production Ready: Comprehensive error handling and validation
API Reference
SCGJwtToken
Constructor
jwt = SCGJwtToken(secret_key)
Methods
sign(payload, expires_in=3600, issuer=None, audience=None)
Create a JWT token.
token = jwt.sign(
{"user_id": 123, "role": "admin"},
expires_in=86400, # 24 hours
issuer="my-app",
audience="app-users"
)
verify(token, issuer=None, audience=None)
Verify and decode a token.
payload = jwt.verify(token)
decode(token)
Decode without verification (for debugging).
decoded = jwt.decode(token)
print(decoded['header'])
print(decoded['payload'])
is_expired(token)
Check if token is expired.
if jwt.is_expired(token):
print("Token expired")
refresh(token, expires_in=3600)
Create new token with updated expiration.
new_token = jwt.refresh(old_token, expires_in=86400)
get_stats()
Get performance statistics.
stats = jwt.get_stats()
print(f"Tokens created: {stats['tokens_created']}")
Quick Operations
from scg_jwt_token import QuickJWT
# Quick sign with auto-generated secret
result = QuickJWT.quick_sign({"user_id": 123})
print(f"Token: {result['token']}")
print(f"Secret: {result['secret']}")
# Quick verify
payload = QuickJWT.quick_verify(token, secret)
Web Framework Examples
Flask
from flask import Flask, request, jsonify
from scg_jwt_token import SCGJwtToken
import os
app = Flask(__name__)
jwt = SCGJwtToken(os.getenv('JWT_SECRET'))
@app.route('/api/login', methods=['POST'])
def login():
# Validate user credentials here
user = validate_user(request.json['email'], request.json['password'])
if user:
token = jwt.sign({
'user_id': user['id'],
'email': user['email'],
'role': user['role']
}, expires_in=86400)
return jsonify({'token': token, 'user': user})
return jsonify({'error': 'Invalid credentials'}), 401
@app.route('/api/protected', methods=['GET'])
def protected():
auth_header = request.headers.get('Authorization')
if not auth_header or not auth_header.startswith('Bearer '):
return jsonify({'error': 'Token required'}), 401
token = auth_header.split(' ')[1]
try:
user = jwt.verify(token)
return jsonify({'message': 'Access granted', 'user': user})
except ValueError:
return jsonify({'error': 'Invalid token'}), 403
Django
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
from scg_jwt_token import SCGJwtToken
import json
import os
jwt = SCGJwtToken(os.getenv('JWT_SECRET'))
@csrf_exempt
def login_view(request):
if request.method == 'POST':
data = json.loads(request.body)
user = authenticate_user(data['email'], data['password'])
if user:
token = jwt.sign({
'user_id': user.id,
'email': user.email,
'role': user.role
})
return JsonResponse({'token': token})
return JsonResponse({'error': 'Invalid credentials'}, status=401)
def protected_view(request):
auth_header = request.META.get('HTTP_AUTHORIZATION')
if not auth_header or not auth_header.startswith('Bearer '):
return JsonResponse({'error': 'Token required'}, status=401)
token = auth_header.split(' ')[1]
try:
user = jwt.verify(token)
return JsonResponse({'user': user})
except ValueError:
return JsonResponse({'error': 'Invalid token'}, status=403)
FastAPI
from fastapi import FastAPI, HTTPException, Depends, Header
from scg_jwt_token import SCGJwtToken
import os
app = FastAPI()
jwt = SCGJwtToken(os.getenv('JWT_SECRET'))
async def verify_token(authorization: str = Header(None)):
if not authorization or not authorization.startswith('Bearer '):
raise HTTPException(status_code=401, detail='Token required')
token = authorization.split(' ')[1]
try:
return jwt.verify(token)
except ValueError:
raise HTTPException(status_code=403, detail='Invalid token')
@app.post('/api/login')
async def login(credentials: dict):
user = await authenticate_user(credentials['email'], credentials['password'])
if user:
token = jwt.sign({
'user_id': user['id'],
'email': user['email'],
'role': user['role']
})
return {'token': token}
raise HTTPException(status_code=401, detail='Invalid credentials')
@app.get('/api/protected')
async def protected(user: dict = Depends(verify_token)):
return {'user': user}
Why JWT Over Sessions
Traditional Session-Based Auth
- User Login → Create Session → Store in Database → Return Session ID
- User Request → Database Lookup → Validate Session → Process Request
- Every request = Database query = Slow & Resource Heavy
SCG JWT Token-Based Auth
- User Login → Create JWT Token → Return Token (NO database storage)
- User Request → Verify JWT Signature → Process Request
- No database queries = Lightning Fast & Highly Scalable
Security Best Practices
-
Use environment variables for secrets:
jwt = SCGJwtToken(os.getenv('JWT_SECRET'))
-
Set reasonable expiration times:
token = jwt.sign(payload, expires_in=86400) # 24 hours
-
Always use HTTPS in production
-
Validate tokens on server side:
try: payload = jwt.verify(token) except ValueError as e: return error_response('Invalid token')
-
Use proper Authorization headers:
Authorization: Bearer <your-jwt-token>
Testing
import unittest
from scg_jwt_token import SCGJwtToken
class TestSCGJwt(unittest.TestCase):
def setUp(self):
self.jwt = SCGJwtToken("test-secret")
def test_create_and_verify_token(self):
payload = {"user_id": 123, "role": "admin"}
token = self.jwt.sign(payload)
decoded = self.jwt.verify(token)
self.assertEqual(decoded['user_id'], 123)
self.assertEqual(decoded['role'], "admin")
def test_expired_token(self):
token = self.jwt.sign({"user_id": 123}, expires_in=-1)
with self.assertRaises(ValueError):
self.jwt.verify(token)
if __name__ == '__main__':
unittest.main()
Use Cases
Perfect for:
- Web Applications: Flask, Django, FastAPI applications
- Mobile APIs: REST APIs for mobile apps
- Microservices: Service-to-service authentication
- Single Page Apps: React, Vue, Angular frontends
- Cross-platform: Same authentication across all platforms
Requirements
- Python 3.7+
- No external dependencies
License
MIT License
Support
- GitHub Repository
- Report Issues
- Email: hemantthapa1998@gmail.com
- Business: contact@squidconsultancy.com
Built by Analytics With Harry and Squid Consultancy Group Limited.
Metadata
Release files for scg-jwt-token 2.0.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| scg_jwt_token-2.0.1.tar.gz | 8.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| scg_jwt_token-2.0.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 16.3 kB
Release files / scg_jwt_token-2.0.1.tar.gz
| Download URL | scg_jwt_token-2.0.1.tar.gz |
|---|---|
| Size | 8.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
2b5dbd3e9d7434192ad36ed86335eb039fdb092b064b1ab9a75d8e061f1aa2b8
|
|
BLAKE2b-256 checksum How to use checksums |
2466b6a5b299f7036a02fbeeb1965d08def085301f09207ca5ededb7932cdd6b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.4
|
Release files / scg_jwt_token-2.0.1-py3-none-any.whl
| Download URL | scg_jwt_token-2.0.1-py3-none-any.whl |
|---|---|
| Size | 8.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
59a0344486b2fad1fc770bc4b630bdc526c6deb7168eb6f9b031186ac01cc161
|
|
BLAKE2b-256 checksum How to use checksums |
ab6a544fbeba571d0907d34edac4378d9f796914e099c8cbeff7d3506e5b693d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.4
|