-
Notifications
You must be signed in to change notification settings - Fork 116
feat: Implement OIDC user management and authentication flow #126
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
pascalinthecloud
wants to merge
2
commits into
eduardolat:develop
Choose a base branch
from
pascalinthecloud:feat/add-oidc-auth
base: develop
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,180 @@ | ||
| # OpenID Connect (OIDC) Integration | ||
|
|
||
| This document describes the OIDC integration added to pgbackweb to support authentication via external providers like Authentik, Keycloak, and other OIDC-compliant identity providers. | ||
|
|
||
| ## Overview | ||
|
|
||
| The OIDC integration allows users to authenticate using external identity providers instead of local username/password combinations. This supports enterprise SSO workflows and centralized user management. | ||
|
|
||
| ## Features | ||
|
|
||
| - Support for any OIDC-compliant identity provider | ||
| - Automatic user creation on first login | ||
| - User information synchronization on each login | ||
| - Seamless integration with existing authentication system | ||
| - Configurable user attribute mapping | ||
|
|
||
| ## Configuration | ||
|
|
||
| Add the following environment variables to enable OIDC: | ||
|
|
||
| ```bash | ||
| # Enable OIDC authentication | ||
| PBW_OIDC_ENABLED=true | ||
|
|
||
| # OIDC Provider Configuration | ||
| PBW_OIDC_ISSUER_URL=https://your-provider.com/auth/realms/your-realm | ||
| PBW_OIDC_CLIENT_ID=pgbackweb | ||
| PBW_OIDC_CLIENT_SECRET=your-client-secret | ||
| PBW_OIDC_REDIRECT_URL=https://your-domain.com/auth/oidc/callback | ||
|
|
||
| # Optional: Customize OIDC scopes (default: "openid profile email") | ||
| PBW_OIDC_SCOPES="openid profile email" | ||
|
|
||
| # Optional: Customize claim mappings | ||
| PBW_OIDC_USERNAME_CLAIM=preferred_username # default: preferred_username | ||
| PBW_OIDC_EMAIL_CLAIM=email # default: email | ||
| PBW_OIDC_NAME_CLAIM=name # default: name | ||
| ``` | ||
|
|
||
| ## Provider-Specific Setup | ||
|
|
||
| ### Authentik | ||
|
|
||
| 1. Create a new **OAuth2/OpenID Provider** in Authentik | ||
| 2. Set the **Redirect URI** to: `https://your-domain.com/auth/oidc/callback` | ||
| 3. Configure the **Client Type** as **Confidential** | ||
| 4. Note the **Client ID** and **Client Secret** | ||
| 5. Create a new **Application** and link it to the provider | ||
| 6. Configure the **Issuer URL**: `https://your-authentik.com/application/o/your-app/` | ||
|
|
||
| ### Keycloak | ||
|
|
||
| 1. Create a new **Client** in your Keycloak realm | ||
| 2. Set **Client Protocol** to `openid-connect` | ||
| 3. Set **Access Type** to `confidential` | ||
| 4. Add `https://your-domain.com/auth/oidc/callback` to **Valid Redirect URIs** | ||
| 5. Note the **Client ID** and get the **Client Secret** from the Credentials tab | ||
| 6. Configure the **Issuer URL**: `https://your-keycloak.com/auth/realms/your-realm` | ||
|
|
||
| ### Generic OIDC Provider | ||
|
|
||
| For any OIDC-compliant provider: | ||
|
|
||
| 1. Create a new OIDC client/application | ||
| 2. Set the redirect URI to: `https://your-domain.com/auth/oidc/callback` | ||
| 3. Ensure the client can access `openid`, `profile`, and `email` scopes | ||
| 4. Note the issuer URL (usually ends with `/.well-known/openid_configuration`) | ||
|
|
||
| ## Database Schema Changes | ||
|
|
||
| The OIDC integration adds the following columns to the `users` table: | ||
|
|
||
| ```sql | ||
| ALTER TABLE users | ||
| ADD COLUMN oidc_provider TEXT, | ||
| ADD COLUMN oidc_subject TEXT; | ||
|
|
||
| -- Make password nullable for OIDC users | ||
| ALTER TABLE users ALTER COLUMN password DROP NOT NULL; | ||
|
|
||
| -- Create unique index for OIDC users | ||
| CREATE UNIQUE INDEX users_oidc_provider_subject_idx | ||
| ON users (oidc_provider, oidc_subject) | ||
| WHERE oidc_provider IS NOT NULL AND oidc_subject IS NOT NULL; | ||
|
|
||
| -- Ensure users have either password or OIDC authentication | ||
| ALTER TABLE users ADD CONSTRAINT users_auth_method_check | ||
| CHECK ( | ||
| (password IS NOT NULL AND oidc_provider IS NULL AND oidc_subject IS NULL) OR | ||
| (password IS NULL AND oidc_provider IS NOT NULL AND oidc_subject IS NOT NULL) | ||
| ); | ||
| ``` | ||
|
|
||
| ## User Flow | ||
|
|
||
| 1. **First-time users**: When an OIDC user logs in for the first time, a new user account is automatically created with information from the OIDC provider. | ||
|
|
||
| 2. **Returning users**: Existing OIDC users are matched by their provider and subject ID. User information (name, email) is updated from the OIDC provider on each login. | ||
|
|
||
| 3. **Mixed authentication**: The system supports both local users (with passwords) and OIDC users in the same instance. | ||
|
|
||
| ## Security Considerations | ||
|
|
||
| - **State parameter**: CSRF protection using a random state parameter | ||
| - **Token validation**: ID tokens are cryptographically verified | ||
| - **Secure cookies**: State is stored in secure, HTTP-only cookies | ||
| - **Provider validation**: Only configured OIDC providers are accepted | ||
|
|
||
| ## User Interface | ||
|
|
||
| When OIDC is enabled, the login page displays: | ||
| - A "Login with SSO" button at the top | ||
| - A divider separating SSO from traditional login | ||
| - The existing email/password form below | ||
|
|
||
| ## Implementation Details | ||
|
|
||
| ### Services | ||
|
|
||
| - **`internal/service/oidc/`**: Core OIDC authentication logic | ||
| - **`internal/view/web/oidc/`**: Web routes for OIDC authentication flow | ||
| - **`internal/config/`**: Environment variable configuration and validation | ||
|
|
||
| ### Routes | ||
|
|
||
| - `GET /auth/oidc/login`: Initiates OIDC authentication flow | ||
| - `GET /auth/oidc/callback`: Handles OIDC provider callback | ||
|
|
||
| ### Database Queries | ||
|
|
||
| - `OIDCServiceCreateUser`: Creates a new OIDC user | ||
| - `OIDCServiceGetUserByOIDC`: Retrieves user by provider and subject | ||
| - `OIDCServiceUpdateUser`: Updates existing OIDC user information | ||
|
|
||
| ## Troubleshooting | ||
|
|
||
| ### Common Issues | ||
|
|
||
| 1. **Invalid redirect URI**: Ensure the redirect URI in your OIDC provider matches exactly: `https://your-domain.com/auth/oidc/callback` | ||
|
|
||
| 2. **Certificate errors**: If using self-signed certificates, ensure your Go application trusts the certificates | ||
|
|
||
| 3. **Claim mapping**: Verify that your OIDC provider returns the expected claims (`email`, `name`, `preferred_username`) | ||
|
|
||
| 4. **Scopes**: Ensure your OIDC client has access to the required scopes (`openid`, `profile`, `email`) | ||
|
|
||
| ### Debug Logging | ||
|
|
||
| The application logs OIDC authentication events. Check logs for: | ||
| - OIDC provider initialization errors | ||
| - Token exchange failures | ||
| - User creation/update events | ||
|
|
||
| ## Migration from Local Authentication | ||
|
|
||
| Existing local users are unaffected by OIDC integration. To migrate users to OIDC: | ||
|
|
||
| 1. Enable OIDC authentication | ||
| 2. Users can continue using local authentication or switch to OIDC | ||
| 3. No automatic migration is performed - users choose their preferred method | ||
|
|
||
| ## Development | ||
|
|
||
| To run the application with OIDC in development: | ||
|
|
||
| ```bash | ||
| # Set environment variables in .env file | ||
| echo "PBW_OIDC_ENABLED=true" >> .env | ||
| echo "PBW_OIDC_ISSUER_URL=https://your-dev-provider.com" >> .env | ||
| # ... other OIDC variables | ||
|
|
||
| # Run database migrations | ||
| task migrate up | ||
|
|
||
| # Generate database code | ||
| task gen-db | ||
|
|
||
| # Build and run | ||
| task dev | ||
| ``` |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
35 changes: 35 additions & 0 deletions
35
internal/database/migrations/20250708000000_add_oidc_support_to_users.sql
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| -- +goose Up | ||
| -- +goose StatementBegin | ||
| ALTER TABLE users | ||
| ADD COLUMN oidc_provider TEXT, | ||
| ADD COLUMN oidc_subject TEXT, | ||
| ADD COLUMN password_nullable TEXT; | ||
|
|
||
| -- Make password nullable and copy existing passwords | ||
| UPDATE users SET password_nullable = password; | ||
| ALTER TABLE users DROP COLUMN password; | ||
| ALTER TABLE users RENAME COLUMN password_nullable TO password; | ||
|
|
||
| -- Create unique index for OIDC users | ||
| CREATE UNIQUE INDEX users_oidc_provider_subject_idx | ||
| ON users (oidc_provider, oidc_subject) | ||
| WHERE oidc_provider IS NOT NULL AND oidc_subject IS NOT NULL; | ||
|
|
||
| -- Add constraint to ensure either password or OIDC is set | ||
| ALTER TABLE users ADD CONSTRAINT users_auth_method_check | ||
| CHECK ( | ||
| (password IS NOT NULL AND oidc_provider IS NULL AND oidc_subject IS NULL) OR | ||
| (password IS NULL AND oidc_provider IS NOT NULL AND oidc_subject IS NOT NULL) | ||
| ); | ||
| -- +goose StatementEnd | ||
|
|
||
| -- +goose Down | ||
| -- +goose StatementBegin | ||
| DROP INDEX IF EXISTS users_oidc_provider_subject_idx; | ||
| ALTER TABLE users DROP CONSTRAINT IF EXISTS users_auth_method_check; | ||
| ALTER TABLE users DROP COLUMN IF EXISTS oidc_provider; | ||
| ALTER TABLE users DROP COLUMN IF EXISTS oidc_subject; | ||
|
|
||
| -- Make password required again (this will fail if there are OIDC users) | ||
| ALTER TABLE users ALTER COLUMN password SET NOT NULL; | ||
| -- +goose StatementEnd | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add safety check before making password NOT NULL in down migration.
The down migration will fail with a constraint violation if any OIDC users exist (users with null passwords). Consider adding a check or removing such users first.
📝 Committable suggestion
🤖 Prompt for AI Agents