Add SSO setup guides for Google, Microsoft, Keycloak, Auth0, Authentik
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
699cbabfcb
commit
029d985149
1 changed files with 144 additions and 3 deletions
147
ADMIN.md
147
ADMIN.md
|
|
@ -168,12 +168,153 @@ Key settings in `backend/.env`:
|
|||
| `LITELLM_API_KEY` | API key for LiteLLM proxy |
|
||||
| `TURNSTILE_SITE_KEY` / `TURNSTILE_SECRET_KEY` | Cloudflare Turnstile bot protection |
|
||||
| `BBB_SERVER_URL` / `BBB_SECRET` | BigBlueButton integration for live sessions |
|
||||
| `OIDC_PROVIDER_URL` | OIDC discovery URL (see SSO section below) |
|
||||
| `OIDC_CLIENT_ID` | OAuth client ID from your identity provider |
|
||||
| `OIDC_CLIENT_SECRET` | OAuth client secret |
|
||||
| `OIDC_PROVIDER_NAME` | Display name on login button (default: "SSO") |
|
||||
|
||||
## SSO / OIDC Setup
|
||||
|
||||
PedsHub supports any OpenID Connect provider. When configured, a "Sign in with {provider}" button appears on the login page. Users who sign in via SSO are auto-created with a verified email — no separate registration or email verification needed.
|
||||
|
||||
### How it works
|
||||
|
||||
1. User clicks "Sign in with SSO" on the login page
|
||||
2. Browser redirects to your identity provider (Google, Microsoft, etc.)
|
||||
3. After authentication, provider redirects back to `{APP_URL}/api/auth/sso/callback`
|
||||
4. PedsHub reads the `email` and `name` claims from the OIDC token
|
||||
5. If no account exists, one is created automatically (role: `user`, email verified)
|
||||
6. User gets a JWT and is logged in
|
||||
|
||||
### Required env vars
|
||||
|
||||
Add these to `backend/.env`:
|
||||
|
||||
```
|
||||
OIDC_PROVIDER_URL=https://accounts.google.com
|
||||
OIDC_CLIENT_ID=your-client-id-here
|
||||
OIDC_CLIENT_SECRET=your-client-secret-here
|
||||
OIDC_PROVIDER_NAME=Google
|
||||
OIDC_SCOPES=openid email profile
|
||||
```
|
||||
|
||||
Then rebuild: `docker compose build --no-cache backend celery && docker compose up -d backend celery --force-recreate`
|
||||
|
||||
### SSO-only mode
|
||||
|
||||
In **Admin > Settings**, toggle "SSO-Only Login" to disable password login entirely. Users will only see the SSO button. Admins can still reset passwords via CLI for emergency access.
|
||||
|
||||
---
|
||||
|
||||
### Google
|
||||
|
||||
1. Go to [Google Cloud Console](https://console.cloud.google.com/apis/credentials)
|
||||
2. Create a new project (or select existing)
|
||||
3. Go to **APIs & Services > Credentials > Create Credentials > OAuth client ID**
|
||||
4. Application type: **Web application**
|
||||
5. Authorized redirect URIs: `https://pedshub.com/api/auth/sso/callback`
|
||||
6. Copy the Client ID and Client Secret
|
||||
|
||||
```
|
||||
OIDC_PROVIDER_URL=https://accounts.google.com
|
||||
OIDC_CLIENT_ID=123456789.apps.googleusercontent.com
|
||||
OIDC_CLIENT_SECRET=GOCSPX-xxxxxxxx
|
||||
OIDC_PROVIDER_NAME=Google
|
||||
```
|
||||
|
||||
> You may need to enable the "Google+ API" or configure the OAuth consent screen first.
|
||||
|
||||
### Microsoft / Azure AD
|
||||
|
||||
1. Go to [Azure Portal > App registrations](https://portal.azure.com/#blade/Microsoft_AAD_RegisteredApps/ApplicationsListBlade)
|
||||
2. Click **New registration**
|
||||
3. Name: "PedsHub", Redirect URI: `https://pedshub.com/api/auth/sso/callback` (type: Web)
|
||||
4. Note the **Application (client) ID** and **Directory (tenant) ID**
|
||||
5. Go to **Certificates & secrets > New client secret** — copy the value
|
||||
|
||||
```
|
||||
OIDC_PROVIDER_URL=https://login.microsoftonline.com/{tenant-id}/v2.0
|
||||
OIDC_CLIENT_ID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
||||
OIDC_CLIENT_SECRET=your-client-secret
|
||||
OIDC_PROVIDER_NAME=Microsoft
|
||||
```
|
||||
|
||||
Replace `{tenant-id}` with your Azure AD tenant ID. For personal Microsoft accounts, use `common` instead.
|
||||
|
||||
> Under **API permissions**, ensure `openid`, `email`, and `profile` are granted.
|
||||
|
||||
### Keycloak
|
||||
|
||||
1. In your Keycloak admin, go to **Clients > Create client**
|
||||
2. Client ID: `pedshub`, Client type: OpenID Connect
|
||||
3. Valid redirect URIs: `https://pedshub.com/api/auth/sso/callback`
|
||||
4. Copy the client secret from the **Credentials** tab
|
||||
|
||||
```
|
||||
OIDC_PROVIDER_URL=https://keycloak.example.com/realms/your-realm
|
||||
OIDC_CLIENT_ID=pedshub
|
||||
OIDC_CLIENT_SECRET=your-client-secret
|
||||
OIDC_PROVIDER_NAME=Keycloak
|
||||
```
|
||||
|
||||
### Auth0
|
||||
|
||||
1. Go to [Auth0 Dashboard > Applications](https://manage.auth0.com/#/applications)
|
||||
2. Create a **Regular Web Application**
|
||||
3. In Settings, add Allowed Callback URL: `https://pedshub.com/api/auth/sso/callback`
|
||||
4. Note the Domain, Client ID, and Client Secret
|
||||
|
||||
```
|
||||
OIDC_PROVIDER_URL=https://your-tenant.auth0.com
|
||||
OIDC_CLIENT_ID=your-client-id
|
||||
OIDC_CLIENT_SECRET=your-client-secret
|
||||
OIDC_PROVIDER_NAME=Auth0
|
||||
```
|
||||
|
||||
### Authentik
|
||||
|
||||
1. In Authentik admin, go to **Applications > Providers > Create OAuth2/OpenID Provider**
|
||||
2. Redirect URI: `https://pedshub.com/api/auth/sso/callback`
|
||||
3. Create an Application linked to this provider
|
||||
|
||||
```
|
||||
OIDC_PROVIDER_URL=https://auth.example.com/application/o/pedshub
|
||||
OIDC_CLIENT_ID=your-client-id
|
||||
OIDC_CLIENT_SECRET=your-client-secret
|
||||
OIDC_PROVIDER_NAME=Authentik
|
||||
```
|
||||
|
||||
### Troubleshooting SSO
|
||||
|
||||
**"SSO login failed" after redirect:**
|
||||
- Check that `APP_URL` in `.env` matches your actual domain (with https)
|
||||
- Verify the redirect URI in your provider matches exactly: `{APP_URL}/api/auth/sso/callback`
|
||||
- Check backend logs: `docker compose logs backend --tail=30 | grep -i "sso\|oidc\|oauth"`
|
||||
|
||||
**User created but wrong name:**
|
||||
- The app reads `name` from the OIDC token, falling back to `preferred_username`, then the email prefix
|
||||
- Some providers require the `profile` scope to include the name — make sure `OIDC_SCOPES=openid email profile`
|
||||
|
||||
**Existing user can't SSO:**
|
||||
- If a user registered with email/password and later tries SSO with the same email, it works — SSO login finds the existing account by email and logs them in (doesn't create a duplicate)
|
||||
|
||||
**SSO-only mode lockout:**
|
||||
- If SSO breaks while in SSO-only mode, use the CLI to disable it:
|
||||
```bash
|
||||
docker compose exec backend python3 -c "
|
||||
import redis; r = redis.from_url('redis://redis:6379/0', decode_responses=True)
|
||||
r.set('settings:sso_only', 'false')
|
||||
print('SSO-only mode disabled')
|
||||
"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Security Notes
|
||||
|
||||
- Passwords are hashed with **bcrypt** (one-way, irreversible)
|
||||
- Registration checks passwords against **Have I Been Pwned** breach database (warns, doesn't block)
|
||||
- Only the first 5 characters of the SHA-1 hash are sent to HIBP (k-anonymity)
|
||||
- JWT tokens auto-refresh via sliding expiration (12h age or <1h remaining)
|
||||
- Rate limiting on login (10 attempts per IP per 15 min) via Redis
|
||||
- Email verification required for new accounts
|
||||
- Email verification required for new accounts (SSO users are auto-verified)
|
||||
- Quiz reminders skip deleted quizzes and course quizzes
|
||||
- Users can opt out of reminders in Settings > Notifications
|
||||
|
|
|
|||
Loading…
Reference in a new issue