OpenID Connect (OIDC) and OAuth2 Authentication Server
This project implements a fully custom authentication and authorization service using Django and Django REST Framework. It provides secure user authentication, token generation (JWT), and OpenID Connect discovery endpoints, designed for integration with Spring Boot or any OAuth2-compliant resource server.
This service provides the following functionality:
- User registration and credential management
- OAuth2 password grant authentication flow
- JWT-based access tokens signed with RSA keys (RS256)
- OpenID Connect discovery and JWKS endpoints for resource servers
- Integration-ready with Spring Security or any OAuth2 client
| Dependency | Version |
|---|---|
| Python | ≥ 3.10 |
| Django | ≥ 4.2, < 5 |
| Django REST Framework | ≥ 3.14 |
| PyJWT | ≥ 2.8 |
| jwcrypto | ≥ 1.4 |
| cryptography | ≥ 41.0 |
| python-dotenv | ≥ 1.0 |
| bcrypt | ~ 5.0 |
| psycopg2-binary | ≥ 2.9 (PostgreSQL) |
openid-connect-oauth2/
│
├── manage.py
├── .env
├── requirements.txt
├── erp_auth/ # Django project settings
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
│
└── apps/
└── security/
├── models.py # User model
├── auth_utils.py # JWT and password utilities
├── views.py # API views
├── urls_auth.py # OAuth endpoints (/oauth/*)
├── urls_wellknown.py # OpenID discovery endpoints
└── keys/ # RSA private.pem / public.pem
git clone https://github.com/gersimuca/openid-connect-oauth2.git
cd openid-connect-oauth2python -m venv venv
venv\Scripts\activatepython3 -m venv venv
source venv/bin/activatepip install -r requirements.txtThese keys are used for signing and verifying JWT tokens.
mkdir -p apps/security/keys
openssl genrsa -out apps/security/keys/private.pem 2048
openssl rsa -in apps/security/keys/private.pem -pubout -out apps/security/keys/public.pemEnsure that both files exist:
private.pempublic.pem
Never commit these files to version control.
Create a .env file in the project root:
DEBUG=True
SECRET_KEY=your_django_secret_key_here
ALLOWED_HOSTS=*
DATABASE_URL=postgres://user:password@localhost:5432/erp_authIf not using PostgreSQL, update your database configuration in erp_auth/settings.py.
Run initial migrations to create database tables:
python manage.py makemigrations
python manage.py migrateStart the Django development server:
python manage.py runserverAccess it at: http://localhost:8000
| Endpoint | Method | Description |
|---|---|---|
/oauth/register |
POST | Register a new user |
/oauth/token |
POST | Obtain JWT via password grant |
/.well-known/openid-configuration |
GET | OpenID Connect discovery document |
/oauth/jwks.json |
GET | JWKS endpoint (public signing keys) |
curl -X POST http://localhost:8000/oauth/register \
-H "Content-Type: application/json" \
-d "{\"username\": \"alice\", \"email\": \"[email protected]\", \"password\": \"mypassword123\"}"Response:
{"message": "User registered."}curl -X POST http://localhost:8000/oauth/token \
-H "Content-Type: application/json" \
-d "{\"username\": \"alice\", \"password\": \"mypassword123\"}"Response:
{
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "Bearer",
"expires_in": 3600
}curl http://localhost:8000/.well-known/openid-configurationResponse:
{
"issuer": "http://localhost:8000",
"authorization_endpoint": "http://localhost:8000/oauth/authorize",
"token_endpoint": "http://localhost:8000/oauth/token",
"jwks_uri": "http://localhost:8000/oauth/jwks.json",
"response_types_supported": ["code", "token"],
"subject_types_supported": ["public"],
"id_token_signing_alg_values_supported": ["RS256"]
}Tokens can be decoded and verified using your public.pem file or an online tool such as jwt.io.
Example decoded payload:
{
"iss": "http://localhost:8000",
"sub": "alice",
"iat": 1730216578,
"exp": 1730218378
}In your Spring Boot application, configure the following in application.yml:
spring:
security:
oauth2:
resourceserver:
jwt:
jwk-set-uri: http://localhost:8000/oauth/jwks.jsonThis instructs Spring Security to validate all incoming JWTs against your Django authentication server’s public key.
After this, any valid token issued by your Django Auth Service will be accepted by your Spring Boot application.
For all API requests to your resource servers, include the token in the Authorization header:
Authorization: Bearer <access_token>
Each microservice should verify the token against the JWKS URI (/oauth/jwks.json).
Once you add a protected API (for example /api/userinfo), test access using:
curl -H "Authorization: Bearer <token>" http://localhost:8000/api/userinfoCreate a user manually via Django shell:
python manage.py shellfrom apps.security.models import User
from apps.security.auth_utils import hash_password
user = User(username="admin", email="[email protected]", password=hash_password("admin123"))
user.save()
exit()Reset database:
python manage.py flushCreate Django superuser (for admin access):
python manage.py createsuperuser- Always set
DEBUG=Falsein production. - Use HTTPS in production environments.
- Never commit RSA private keys (
private.pem) or.envfiles to version control. - Use a strong Django
SECRET_KEY. - Rotate JWT signing keys periodically.
This project is distributed under the MIT License.