8.7 KiB
8.7 KiB
Quick Start Guide
Get your application integrated with this OIDC provider in 10 minutes.
For the Impatient
# 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
- Navigate to:
https://your-idp.com/admin/login - Login with admin credentials
- Go to "Clients" → "Create New Client"
- Fill in:
- Client Name:
My App - Redirect URIs:
http://localhost:3000/callback(one per line) - Allowed Scopes:
openid, profile, email
- Client Name:
- Click "Create"
- 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 |
| Node.js + Express | Node.js Example |
| PHP + Laravel | PHP Example |
| Any other | Generic HTTP Flow |
Python (Flask)
Install Dependencies
pip install flask authlib requests
Code (app.py)
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
python app.py
# Open http://localhost:3000
Node.js (Express)
Install Dependencies
npm install express express-session passport openid-client
Code (server.js)
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
node server.js
# Open http://localhost:3000
PHP (Laravel)
Install Socialite
composer require laravel/socialite
composer require socialiteproviders/oidc
Configure (config/services.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)
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)
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
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
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
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:
{
"access_token": "eyJhbGci...",
"id_token": "eyJhbGci...",
"token_type": "Bearer",
"expires_in": 3600
}
Step 4: Get User Info
curl https://your-idp.com/userinfo \
-H "Authorization: Bearer ACCESS_TOKEN"
Response:
{
"sub": "user-123",
"email": "john@example.com",
"name": "John Doe",
"preferred_username": "john"
}
Testing Your Integration
1. Start Your App
# 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:
- Check exact match (including trailing slash)
- Update in admin panel if needed
"Invalid Client"
Problem: Wrong client ID or secret.
Fix:
- Double-check credentials
- No extra spaces or line breaks
"Connection Refused"
Problem: OIDC provider not accessible.
Fix:
- Verify provider is running:
curl https://your-idp.com/health - 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:
- Add User Persistence: Store user in your database
- Handle Logout: Clear session and optionally redirect to IdP logout
- Refresh Tokens: Implement token refresh (when available)
- Error Handling: Add proper error pages
- 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
- 🏗️ Architecture
- 🚀 Deployment
- 🐛 Report issues on GitHub
You're all set! 🎉
Your users can now log in via OIDC in just a few clicks.