feat: allow multiple auth sources per user (#500,#477) (#612)

* feat: allow multiple auth sources per user (#500,#477)

* only override isAdmin flag if it is provided by the authentication source
This commit is contained in:
h44z
2026-01-21 22:22:22 +01:00
committed by GitHub
parent d2fe267be7
commit e0f6c1d04b
44 changed files with 1158 additions and 798 deletions

View File

@@ -0,0 +1,152 @@
WireGuard Portal supports multiple authentication mechanisms to manage user access. This includes
- Local user accounts
- LDAP authentication
- OAuth2 and OIDC authentication
- Passkey authentication (WebAuthn)
Users can have two roles which limit their permissions in WireGuard Portal:
- **User**: Can manage their own account and peers.
- **Admin**: Can manage all users and peers, including the ability to manage WireGuard interfaces.
In general, each user is identified by a _unique identifier_. If the same user identifier exists across multiple authentication sources, WireGuard Portal automatically merges those accounts into a single user record.
When a user is associated with multiple authentication sources, their information in WireGuard Portal is updated based on the most recently logged-in source. For more details, see [User Synchronization](./user-sync.md) documentation.
## Password Authentication
WireGuard Portal supports username and password authentication for both local and LDAP-backed accounts.
Local users are stored in the database, while LDAP users are authenticated against an external LDAP server.
On initial startup, WireGuard Portal automatically creates a local admin account with the password `wgportal-default`.
> :warning: This password must be changed immediately after the first login.
The minimum password length for all local users can be configured in the [`auth`](../configuration/overview.md#auth)
section of the configuration file. The default value is **16** characters, see [`min_password_length`](../configuration/overview.md#min_password_length).
The minimum password length is also enforced for the default admin user.
## Passkey (WebAuthn) Authentication
Besides the standard authentication mechanisms, WireGuard Portal supports Passkey authentication.
This feature is enabled by default and can be configured in the [`webauthn`](../configuration/overview.md#webauthn-passkeys) section of the configuration file.
Users can register multiple Passkeys to their account. These Passkeys can be used to log in to the web UI as long as the user is not locked.
> :warning: Passkey authentication does not disable password authentication. The password can still be used to log in (e.g., as a fallback).
To register a Passkey, open the settings page *(1)* in the web UI and click on the "Register Passkey" *(2)* button.
![Passkey UI](../../assets/images/passkey_setup.png)
## OAuth2 and OIDC Authentication
WireGuard Portal supports OAuth2 and OIDC authentication. You can use any OAuth2 or OIDC provider that supports the authorization code flow,
such as Google, GitHub, or Keycloak.
For OAuth2 or OIDC to work, you need to configure the [`external_url`](../configuration/overview.md#external_url) property in the [`web`](../configuration/overview.md#web) section of the configuration file.
If you are planning to expose the portal to the internet, make sure that the `external_url` is configured to use HTTPS.
To add OIDC or OAuth2 authentication to WireGuard Portal, create a Client-ID and Client-Secret in your OAuth2 provider and
configure a new authentication provider in the [`auth`](../configuration/overview.md#auth) section of the configuration file.
Make sure that each configured provider has a unique `provider_name` property set. Samples can be seen [here](../configuration/examples.md).
#### Limiting Login to Specific Domains
You can limit the login to specific domains by setting the `allowed_domains` property for OAuth2 or OIDC providers.
This property is a comma-separated list of domains that are allowed to log in. The user's email address is checked against this list.
For example, if you want to allow only users with an email address ending in `outlook.com` to log in, set the property as follows:
```yaml
auth:
oidc:
- provider_name: "oidc1"
# ... other settings
allowed_domains:
- "outlook.com"
```
#### Limit Login to Existing Users
You can limit the login to existing users only by setting the `registration_enabled` property to `false` for OAuth2 or OIDC providers.
If registration is enabled, new users will be created in the database when they log in for the first time.
#### Admin Mapping
You can map users to admin roles based on their attributes in the OAuth2 or OIDC provider. To do this, set the `admin_mapping` property for the provider.
Administrative access can either be mapped by a specific attribute or by group membership.
**Attribute specific mapping** can be achieved by setting the `admin_value_regex` and the `is_admin` property.
The `admin_value_regex` property is a regular expression that is matched against the value of the `is_admin` attribute.
The user is granted admin access if the regex matches the attribute value.
Example:
```yaml
auth:
oidc:
- provider_name: "oidc1"
# ... other settings
field_map:
is_admin: "wg_admin_prop"
admin_mapping:
admin_value_regex: "^true$"
```
The example above will grant admin access to users with the `wg_admin_prop` attribute set to `true`.
**Group membership mapping** can be achieved by setting the `admin_group_regex` and `user_groups` property.
The `admin_group_regex` property is a regular expression that is matched against the group names of the user.
The user is granted admin access if the regex matches any of the group names.
Example:
```yaml
auth:
oidc:
- provider_name: "oidc1"
# ... other settings
field_map:
user_groups: "groups"
admin_mapping:
admin_group_regex: "^the-admin-group$"
```
The example above will grant admin access to users who are members of the `the-admin-group` group.
## LDAP Authentication
WireGuard Portal supports LDAP authentication. You can use any LDAP server that supports the LDAP protocol, such as Active Directory or OpenLDAP.
Multiple LDAP servers can be configured in the [`auth`](../configuration/overview.md#auth) section of the configuration file.
WireGuard Portal remembers the authentication provider of the user and therefore avoids conflicts between multiple LDAP providers.
To configure LDAP authentication, create a new [`ldap`](../configuration/overview.md#ldap) authentication provider in the [`auth`](../configuration/overview.md#auth) section of the configuration file.
### Limiting Login to Specific Users
You can limit the login to specific users by setting the `login_filter` property for LDAP provider. This filter uses the LDAP search filter syntax.
The username can be inserted into the query by placing the `{{login_identifier}}` placeholder in the filter. This placeholder will then be replaced with the username entered by the user during login.
For example, if you want to allow only users with the `objectClass` attribute set to `organizationalPerson` to log in, set the property as follows:
```yaml
auth:
ldap:
- provider_name: "ldap1"
# ... other settings
login_filter: "(&(objectClass=organizationalPerson)(uid={{login_identifier}}))"
```
The `login_filter` should always be designed to return at most one user.
### Limit Login to Existing Users
You can limit the login to existing users only by setting the `registration_enabled` property to `false` for LDAP providers.
If registration is enabled, new users will be created in the database when they log in for the first time.
### Admin Mapping
You can map users to admin roles based on their group membership in the LDAP server. To do this, set the `admin_group` and `memberof` property for the provider.
The `admin_group` property defines the distinguished name of the group that is allowed to log in as admin.
All groups that are listed in the `memberof` attribute of the user will be checked against this group. If one of the groups matches, the user is granted admin access.
## User Synchronization

View File

@@ -14,7 +14,7 @@ WireGuard Interfaces can be categorized into three types:
## Accessing the Web UI
The web UI should be accessed via the URL specified in the `external_url` property of the configuration file.
By default, WireGuard Portal listens on port `8888` for HTTP connections. Check the [Security](security.md) section for more information on securing the web UI.
By default, WireGuard Portal listens on port `8888` for HTTP connections. Check the [Security](security.md) or [Authentication](authentication.md) sections for more information on securing the web UI.
So the default URL to access the web UI is:

View File

@@ -1,37 +0,0 @@
WireGuard Portal lets you hook up any LDAP server such as Active Directory or OpenLDAP for both authentication and user sync.
You can even register multiple LDAP servers side-by-side. When someone logs in via LDAP, their specific provider is remembered,
so there's no risk of cross-provider conflicts. Details on the log-in process can be found in the [Security](security.md#ldap-authentication) documentation.
If you enable LDAP synchronization, all users within the LDAP directory will be created automatically in the WireGuard Portal database if they do not exist.
If a user is disabled or deleted in LDAP, the user will be disabled in WireGuard Portal as well.
The synchronization process can be fine-tuned by multiple parameters, which are described below.
## LDAP Synchronization
WireGuard Portal can automatically synchronize users from LDAP to the database.
To enable this feature, set the `sync_interval` property in the LDAP provider configuration to a value greater than "0".
The value is a string representing a duration, such as "15m" for 15 minutes or "1h" for 1 hour (check the [exact format definition](https://pkg.go.dev/time#ParseDuration) for details).
The synchronization process will run in the background and synchronize users from LDAP to the database at the specified interval.
Also make sure that the `sync_filter` property is a well-formed LDAP filter, or synchronization will fail.
### Limiting Synchronization to Specific Users
Use the `sync_filter` property in your LDAP provider block to restrict which users get synchronized.
It accepts any valid LDAP search filter, only entries matching that filter will be pulled into the portal's database.
For example, to import only users with a `mail` attribute:
```yaml
auth:
ldap:
- id: ldap
# ... other settings
sync_filter: (mail=*)
```
### Disable Missing Users
If you set the `disable_missing` property to `true`, any user that is not found in LDAP during synchronization will be disabled in WireGuard Portal.
All peers associated with that user will also be disabled.
If you want a user and its peers to be automatically re-enabled once they are found in LDAP again, set the `auto_re_enable` property to `true`.
This will only re-enable the user if they where disabled by the synchronization process. Manually disabled users will not be re-enabled.

View File

@@ -1,153 +1,12 @@
This section describes the security features available to administrators for hardening WireGuard Portal and protecting its data.
## Authentication
## Database Encryption
WireGuard Portal supports multiple authentication methods, including:
- Local user accounts
- LDAP authentication
- OAuth and OIDC authentication
- Passkey authentication (WebAuthn)
Users can have two roles which limit their permissions in WireGuard Portal:
- **User**: Can manage their own account and peers.
- **Admin**: Can manage all users and peers, including the ability to manage WireGuard interfaces.
### Password Security
WireGuard Portal supports username and password authentication for both local and LDAP-backed accounts.
Local users are stored in the database, while LDAP users are authenticated against an external LDAP server.
On initial startup, WireGuard Portal automatically creates a local admin account with the password `wgportal-default`.
> :warning: This password must be changed immediately after the first login.
The minimum password length for all local users can be configured in the [`auth`](../configuration/overview.md#auth)
section of the configuration file. The default value is **16** characters, see [`min_password_length`](../configuration/overview.md#min_password_length).
The minimum password length is also enforced for the default admin user.
### Passkey (WebAuthn) Authentication
Besides the standard authentication mechanisms, WireGuard Portal supports Passkey authentication.
This feature is enabled by default and can be configured in the [`webauthn`](../configuration/overview.md#webauthn-passkeys) section of the configuration file.
Users can register multiple Passkeys to their account. These Passkeys can be used to log in to the web UI as long as the user is not locked.
> :warning: Passkey authentication does not disable password authentication. The password can still be used to log in (e.g., as a fallback).
To register a Passkey, open the settings page *(1)* in the web UI and click on the "Register Passkey" *(2)* button.
![Passkey UI](../../assets/images/passkey_setup.png)
### OAuth and OIDC Authentication
WireGuard Portal supports OAuth and OIDC authentication. You can use any OAuth or OIDC provider that supports the authorization code flow,
such as Google, GitHub, or Keycloak.
For OAuth or OIDC to work, you need to configure the [`external_url`](../configuration/overview.md#external_url) property in the [`web`](../configuration/overview.md#web) section of the configuration file.
If you are planning to expose the portal to the internet, make sure that the `external_url` is configured to use HTTPS.
To add OIDC or OAuth authentication to WireGuard Portal, create a Client-ID and Client-Secret in your OAuth provider and
configure a new authentication provider in the [`auth`](../configuration/overview.md#auth) section of the configuration file.
Make sure that each configured provider has a unique `provider_name` property set. Samples can be seen [here](../configuration/examples.md).
#### Limiting Login to Specific Domains
You can limit the login to specific domains by setting the `allowed_domains` property for OAuth or OIDC providers.
This property is a comma-separated list of domains that are allowed to log in. The user's email address is checked against this list.
For example, if you want to allow only users with an email address ending in `outlook.com` to log in, set the property as follows:
```yaml
auth:
oidc:
- provider_name: "oidc1"
# ... other settings
allowed_domains:
- "outlook.com"
```
#### Limit Login to Existing Users
You can limit the login to existing users only by setting the `registration_enabled` property to `false` for OAuth or OIDC providers.
If registration is enabled, new users will be created in the database when they log in for the first time.
#### Admin Mapping
You can map users to admin roles based on their attributes in the OAuth or OIDC provider. To do this, set the `admin_mapping` property for the provider.
Administrative access can either be mapped by a specific attribute or by group membership.
**Attribute specific mapping** can be achieved by setting the `admin_value_regex` and the `is_admin` property.
The `admin_value_regex` property is a regular expression that is matched against the value of the `is_admin` attribute.
The user is granted admin access if the regex matches the attribute value.
Example:
```yaml
auth:
oidc:
- provider_name: "oidc1"
# ... other settings
field_map:
is_admin: "wg_admin_prop"
admin_mapping:
admin_value_regex: "^true$"
```
The example above will grant admin access to users with the `wg_admin_prop` attribute set to `true`.
**Group membership mapping** can be achieved by setting the `admin_group_regex` and `user_groups` property.
The `admin_group_regex` property is a regular expression that is matched against the group names of the user.
The user is granted admin access if the regex matches any of the group names.
Example:
```yaml
auth:
oidc:
- provider_name: "oidc1"
# ... other settings
field_map:
user_groups: "groups"
admin_mapping:
admin_group_regex: "^the-admin-group$"
```
The example above will grant admin access to users who are members of the `the-admin-group` group.
### LDAP Authentication
WireGuard Portal supports LDAP authentication. You can use any LDAP server that supports the LDAP protocol, such as Active Directory or OpenLDAP.
Multiple LDAP servers can be configured in the [`auth`](../configuration/overview.md#auth) section of the configuration file.
WireGuard Portal remembers the authentication provider of the user and therefore avoids conflicts between multiple LDAP providers.
To configure LDAP authentication, create a new [`ldap`](../configuration/overview.md#ldap) authentication provider in the [`auth`](../configuration/overview.md#auth) section of the configuration file.
#### Limiting Login to Specific Users
You can limit the login to specific users by setting the `login_filter` property for LDAP provider. This filter uses the LDAP search filter syntax.
The username can be inserted into the query by placing the `{{login_identifier}}` placeholder in the filter. This placeholder will then be replaced with the username entered by the user during login.
For example, if you want to allow only users with the `objectClass` attribute set to `organizationalPerson` to log in, set the property as follows:
```yaml
auth:
ldap:
- provider_name: "ldap1"
# ... other settings
login_filter: "(&(objectClass=organizationalPerson)(uid={{login_identifier}}))"
```
The `login_filter` should always be designed to return at most one user.
#### Limit Login to Existing Users
You can limit the login to existing users only by setting the `registration_enabled` property to `false` for LDAP providers.
If registration is enabled, new users will be created in the database when they log in for the first time.
#### Admin Mapping
You can map users to admin roles based on their group membership in the LDAP server. To do this, set the `admin_group` and `memberof` property for the provider.
The `admin_group` property defines the distinguished name of the group that is allowed to log in as admin.
All groups that are listed in the `memberof` attribute of the user will be checked against this group. If one of the groups matches, the user is granted admin access.
WireGuard Portal supports multiple database backends. To reduce the risk of data exposure, sensitive information stored in the database can be encrypted.
To enable encryption, set the [`encryption_passphrase`](../configuration/overview.md#database) in the database configuration section.
> :warning: Important: Once encryption is enabled, it cannot be disabled, and the passphrase cannot be changed!
> Only new or updated records will be encrypted; existing data remains in plaintext until its next modified.
## UI and API Access
@@ -157,4 +16,9 @@ WireGuard Portal provides a web UI and a REST API for user interaction. It is im
It is recommended to use HTTPS for all communication with the portal to prevent eavesdropping.
Event though, WireGuard Portal supports HTTPS out of the box, it is recommended to use a reverse proxy like Nginx or Traefik to handle SSL termination and other security features.
A detailed explanation is available in the [Reverse Proxy](../getting-started/reverse-proxy.md) section.
A detailed explanation is available in the [Reverse Proxy](../getting-started/reverse-proxy.md) section.
### Secure Authentication
To prevent unauthorized access, WireGuard Portal supports integrating with secure authentication providers such as LDAP, OAuth2, or Passkeys, see [Authentication](./authentication.md) for more details.
When possible, use centralized authentication and enforce multi-factor authentication (MFA) at the provider level for enhanced account security.
For local accounts, administrators should enforce strong password requirements.

View File

@@ -0,0 +1,46 @@
For all external authentication providers (LDAP, OIDC, OAuth2), WireGuard Portal can automatically create a local user record upon the user's first successful login.
This behavior is controlled by the `registration_enabled` setting in each authentication provider's configuration.
User information from external authentication sources is merged into the corresponding local WireGuard Portal user record whenever the user logs in.
Additionally, WireGuard Portal supports periodic synchronization of user data from an LDAP directory.
To prevent overwriting local changes, WireGuard Portal allows you to set a per-user flag that disables synchronization of external attributes.
When this flag is set, the user in WireGuard Portal will not be updated automatically during log-ins or LDAP synchronization.
### LDAP Synchronization
WireGuard Portal lets you hook up any LDAP server such as Active Directory or OpenLDAP for both authentication and user sync.
You can even register multiple LDAP servers side-by-side. Details on the log-in process can be found in the [LDAP Authentication](./authentication.md#ldap-authentication) section.
If you enable LDAP synchronization, all users within the LDAP directory will be created automatically in the WireGuard Portal database if they do not exist.
If a user is disabled or deleted in LDAP, the user will be disabled in WireGuard Portal as well.
The synchronization process can be fine-tuned by multiple parameters, which are described below.
#### Synchronization Parameters
To enable the LDAP sycnhronization this feature, set the `sync_interval` property in the LDAP provider configuration to a value greater than "0".
The value is a string representing a duration, such as "15m" for 15 minutes or "1h" for 1 hour (check the [exact format definition](https://pkg.go.dev/time#ParseDuration) for details).
The synchronization process will run in the background and synchronize users from LDAP to the database at the specified interval.
Also make sure that the `sync_filter` property is a well-formed LDAP filter, or synchronization will fail.
##### Limiting Synchronization to Specific Users
Use the `sync_filter` property in your LDAP provider block to restrict which users get synchronized.
It accepts any valid LDAP search filter, only entries matching that filter will be pulled into the portal's database.
For example, to import only users with a `mail` attribute:
```yaml
auth:
ldap:
- id: ldap
# ... other settings
sync_filter: (mail=*)
```
##### Disable Missing Users
If you set the `disable_missing` property to `true`, any user that is not found in LDAP during synchronization will be disabled in WireGuard Portal.
All peers associated with that user will also be disabled.
If you want a user and its peers to be automatically re-enabled once they are found in LDAP again, set the `auto_re_enable` property to `true`.
This will only re-enable the user if they were disabled by the synchronization process. Manually disabled users will not be re-enabled.

View File

@@ -68,26 +68,32 @@ All payload models are encoded as JSON objects. Fields with empty values might b
#### User Payload (entity: `user`)
| JSON Field | Type | Description |
|----------------|-------------|-----------------------------------|
| CreatedBy | string | Creator identifier |
| UpdatedBy | string | Last updater identifier |
| CreatedAt | time.Time | Time of creation |
| UpdatedAt | time.Time | Time of last update |
| Identifier | string | Unique user identifier |
| Email | string | User email |
| Source | string | Authentication source |
| ProviderName | string | Name of auth provider |
| IsAdmin | bool | Whether user has admin privileges |
| Firstname | string | User's first name (optional) |
| Lastname | string | User's last name (optional) |
| Phone | string | Contact phone number (optional) |
| Department | string | User's department (optional) |
| Notes | string | Additional notes (optional) |
| Disabled | *time.Time | When user was disabled |
| DisabledReason | string | Reason for deactivation |
| Locked | *time.Time | When user account was locked |
| LockedReason | string | Reason for being locked |
| JSON Field | Type | Description |
|----------------|---------------|-----------------------------------|
| CreatedBy | string | Creator identifier |
| UpdatedBy | string | Last updater identifier |
| CreatedAt | time.Time | Time of creation |
| UpdatedAt | time.Time | Time of last update |
| Identifier | string | Unique user identifier |
| Email | string | User email |
| AuthSources | []AuthSource | Authentication sources |
| IsAdmin | bool | Whether user has admin privileges |
| Firstname | string | User's first name (optional) |
| Lastname | string | User's last name (optional) |
| Phone | string | Contact phone number (optional) |
| Department | string | User's department (optional) |
| Notes | string | Additional notes (optional) |
| Disabled | *time.Time | When user was disabled |
| DisabledReason | string | Reason for deactivation |
| Locked | *time.Time | When user account was locked |
| LockedReason | string | Reason for being locked |
`AuthSource`:
| JSON Field | Type | Description |
|--------------|---------------|-----------------------------------------------------|
| Source | string | The authentication source (e.g. LDAP, OAuth, or DB) |
| ProviderName | string | The identifier of the authentication provider |
#### Peer Payload (entity: `peer`)