first commit

This commit is contained in:
2025-11-30 00:07:24 +01:00
commit b5e642aecb
78 changed files with 15162 additions and 0 deletions

438
docs/QUICKSTART.md Normal file
View File

@ -0,0 +1,438 @@
# Quick Start Guide
Get your application integrated with this OIDC provider in 10 minutes.
---
## For the Impatient
```bash
# 1. Get credentials from admin panel
https://your-idp.com/admin/login
# 2. Add to your app (Python example)
pip install authlib flask
# 3. Copy this code
# (see Python example below)
# 4. Done! Users can now log in via OIDC
```
---
## Prerequisites
- ✅ OIDC Provider deployed and accessible
- ✅ Admin access to register your client
- ✅ A web application with a backend (Node.js, Python, PHP, etc.)
---
## Step 1: Register Your Application (2 minutes)
### Via Admin Panel
1. **Navigate** to: `https://your-idp.com/admin/login`
2. **Login** with admin credentials
3. **Go to** "Clients" → "Create New Client"
4. **Fill in**:
- Client Name: `My App`
- Redirect URIs: `http://localhost:3000/callback` (one per line)
- Allowed Scopes: `openid, profile, email`
5. **Click** "Create"
6. **Copy** your credentials:
```
Client ID: abc123def456
Client Secret: xyz789... (⚠️ save this - shown only once!)
```
---
## Step 2: Choose Your Integration Method (1 minute)
Pick the method that matches your tech stack:
| If you use... | Go to |
|---------------|-------|
| Python + Flask | [Python Example](#python-flask) |
| Node.js + Express | [Node.js Example](#nodejs-express) |
| PHP + Laravel | [PHP Example](#php-laravel) |
| Any other | [Generic HTTP Flow](#generic-http-flow) |
---
## Python (Flask)
### Install Dependencies
```bash
pip install flask authlib requests
```
### Code (`app.py`)
```python
from flask import Flask, redirect, url_for, session, jsonify
from authlib.integrations.flask_client import OAuth
import os
app = Flask(__name__)
app.secret_key = os.urandom(24)
# Configure OIDC
oauth = OAuth(app)
oauth.register(
name='myidp',
client_id='YOUR_CLIENT_ID',
client_secret='YOUR_CLIENT_SECRET',
server_metadata_url='https://your-idp.com/.well-known/openid-configuration',
client_kwargs={'scope': 'openid profile email'}
)
@app.route('/')
def index():
user = session.get('user')
if user:
return jsonify(user)
return '<a href="/login">Login with OIDC</a>'
@app.route('/login')
def login():
redirect_uri = url_for('callback', _external=True)
return oauth.myidp.authorize_redirect(redirect_uri)
@app.route('/callback')
def callback():
token = oauth.myidp.authorize_access_token()
session['user'] = token['userinfo']
return redirect('/')
@app.route('/logout')
def logout():
session.pop('user', None)
return redirect('/')
if __name__ == '__main__':
app.run(port=3000, debug=True)
```
### Run
```bash
python app.py
# Open http://localhost:3000
```
---
## Node.js (Express)
### Install Dependencies
```bash
npm install express express-session passport openid-client
```
### Code (`server.js`)
```javascript
const express = require('express');
const session = require('express-session');
const passport = require('passport');
const { Issuer, Strategy } = require('openid-client');
const app = express();
app.use(session({
secret: 'keyboard cat',
resave: false,
saveUninitialized: true
}));
app.use(passport.initialize());
app.use(passport.session());
passport.serializeUser((user, done) => done(null, user));
passport.deserializeUser((user, done) => done(null, user));
// Discover and configure OIDC
Issuer.discover('https://your-idp.com/.well-known/openid-configuration')
.then(issuer => {
const client = new issuer.Client({
client_id: 'YOUR_CLIENT_ID',
client_secret: 'YOUR_CLIENT_SECRET',
redirect_uris: ['http://localhost:3000/callback'],
response_types: ['code'],
});
passport.use('oidc', new Strategy({ client }, (tokenSet, userinfo, done) => {
return done(null, userinfo);
}));
// Routes
app.get('/', (req, res) => {
if (req.isAuthenticated()) {
res.send(`<h1>Hello, ${req.user.name}!</h1><a href="/logout">Logout</a>`);
} else {
res.send('<a href="/login">Login with OIDC</a>');
}
});
app.get('/login', passport.authenticate('oidc'));
app.get('/callback',
passport.authenticate('oidc', { failureRedirect: '/' }),
(req, res) => res.redirect('/')
);
app.get('/logout', (req, res) => {
req.logout(() => res.redirect('/'));
});
app.listen(3000, () => console.log('App running on http://localhost:3000'));
});
```
### Run
```bash
node server.js
# Open http://localhost:3000
```
---
## PHP (Laravel)
### Install Socialite
```bash
composer require laravel/socialite
composer require socialiteproviders/oidc
```
### Configure (`config/services.php`)
```php
'oidc' => [
'client_id' => env('OIDC_CLIENT_ID'),
'client_secret' => env('OIDC_CLIENT_SECRET'),
'redirect' => env('OIDC_REDIRECT_URI'),
'base_url' => env('OIDC_ISSUER'),
],
```
### Environment (`.env`)
```bash
OIDC_CLIENT_ID=YOUR_CLIENT_ID
OIDC_CLIENT_SECRET=YOUR_CLIENT_SECRET
OIDC_REDIRECT_URI=http://localhost:8000/callback
OIDC_ISSUER=https://your-idp.com
```
### Routes (`routes/web.php`)
```php
use Laravel\Socialite\Facades\Socialite;
use Illuminate\Support\Facades\Auth;
Route::get('/login', function () {
return Socialite::driver('oidc')->redirect();
});
Route::get('/callback', function () {
$user = Socialite::driver('oidc')->user();
// Find or create user in database
$localUser = User::updateOrCreate(
['email' => $user->email],
['name' => $user->name]
);
Auth::login($localUser);
return redirect('/dashboard');
});
Route::get('/logout', function () {
Auth::logout();
return redirect('/');
});
```
### Run
```bash
php artisan serve
# Open http://localhost:8000
```
---
## Generic HTTP Flow
If you can't use a library, here's the manual flow:
### Step 1: Redirect to Authorization Endpoint
```http
GET https://your-idp.com/authorize?
client_id=YOUR_CLIENT_ID&
redirect_uri=http://localhost:3000/callback&
response_type=code&
scope=openid%20profile%20email&
state=RANDOM_STATE_TOKEN
```
### Step 2: Handle Callback
User is redirected back with a code:
```
http://localhost:3000/callback?code=ABC123&state=RANDOM_STATE_TOKEN
```
**Verify state token** to prevent CSRF!
### Step 3: Exchange Code for Token
```bash
curl -X POST https://your-idp.com/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=authorization_code" \
-d "code=ABC123" \
-d "redirect_uri=http://localhost:3000/callback" \
-d "client_id=YOUR_CLIENT_ID" \
-d "client_secret=YOUR_CLIENT_SECRET"
```
**Response:**
```json
{
"access_token": "eyJhbGci...",
"id_token": "eyJhbGci...",
"token_type": "Bearer",
"expires_in": 3600
}
```
### Step 4: Get User Info
```bash
curl https://your-idp.com/userinfo \
-H "Authorization: Bearer ACCESS_TOKEN"
```
**Response:**
```json
{
"sub": "user-123",
"email": "john@example.com",
"name": "John Doe",
"preferred_username": "john"
}
```
---
## Testing Your Integration
### 1. Start Your App
```bash
# Your app should now be running on localhost
```
### 2. Click "Login"
Navigate to your app's login link. You should be redirected to:
```
https://your-idp.com/authorize?client_id=...
```
### 3. Login
Use test credentials:
```
Username: test
Password: test123
```
### 4. Verify
After login, you should:
- ✅ Be redirected back to your app
- ✅ See user information
- ✅ Have an active session
---
## Common Issues
### "Invalid Redirect URI"
**Problem**: Redirect URI doesn't match.
**Fix**:
1. Check exact match (including trailing slash)
2. Update in admin panel if needed
### "Invalid Client"
**Problem**: Wrong client ID or secret.
**Fix**:
1. Double-check credentials
2. No extra spaces or line breaks
### "Connection Refused"
**Problem**: OIDC provider not accessible.
**Fix**:
1. Verify provider is running: `curl https://your-idp.com/health`
2. Check network/firewall
### CORS Errors (for SPAs)
**Problem**: Browser blocks cross-origin requests.
**Solution**: Don't call OIDC endpoints from frontend. Use a backend proxy.
---
## Next Steps
Once basic login works:
1. **Add User Persistence**: Store user in your database
2. **Handle Logout**: Clear session and optionally redirect to IdP logout
3. **Refresh Tokens**: Implement token refresh (when available)
4. **Error Handling**: Add proper error pages
5. **Production Setup**: Use HTTPS, secure cookies
---
## Complete Examples
Check out complete example applications:
- **Python Flask**: `examples/python-flask/` (coming soon)
- **Node.js Express**: `examples/nodejs-express/` (coming soon)
- **PHP Laravel**: `examples/php-laravel/` (coming soon)
---
## Need Help?
- 📖 [Full API Guide](API_GUIDE.md)
- 🏗️ [Architecture](ARCHITECTURE.md)
- 🚀 [Deployment](deployment.md)
- 🐛 Report issues on GitHub
---
**You're all set!** 🎉
Your users can now log in via OIDC in just a few clicks.