-
Notifications
You must be signed in to change notification settings - Fork 63
OIDC Documentation #100
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
base: master
Are you sure you want to change the base?
OIDC Documentation #100
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| import {createMarkdownRenderer} from 'vitepress'; | ||
|
|
||
| const SOURCE = 'https://raw.githubusercontent.com/gotify/server/master/gotify-server.env.example'; | ||
|
|
||
| const uncomment = (line: string): string => line.replace(/^#( ?)/, ''); | ||
| const codeBlock = (text: string) => '```\n' + text.trimEnd() + '\n```'; | ||
|
|
||
| const renderSetting = (block: string[]): string => { | ||
| const assignment = block.find((l) => /^[A-Z][A-Z0-9_]*=/.test(uncomment(l))); | ||
| if (!assignment) throw Error('could not find assignment ' + block); | ||
|
|
||
| const name = uncomment(assignment).split('=')[0]; | ||
| return ['### ' + name, codeBlock(block.join('\n'))].join('\n\n'); | ||
| }; | ||
|
|
||
| export default { | ||
| async load() { | ||
| const res = await fetch(SOURCE); | ||
| if (!res.ok) throw Error('could not fetch gotify-server.env.example'); | ||
|
|
||
| const [header, ...blocks] = (await res.text()) | ||
| .trimEnd() | ||
| .split(/\n *\n/) | ||
| .map((b) => b.split('\n')) | ||
| .filter((b) => b.some((l) => l.trim())); | ||
|
|
||
| const markdown = [ | ||
| codeBlock(header.map(uncomment).join('\n')), | ||
| ...blocks.map(renderSetting), | ||
| ].join('\n\n'); | ||
|
|
||
| return (await createMarkdownRenderer('.')).render(markdown); | ||
| }, | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,115 @@ | ||
| # Migrate to 3.x | ||
|
|
||
| - The `config.yml` file is no longer supported, convert it to the new env format | ||
| with [`migrate-config`](#migrating-your-config). | ||
| - If you set list or map environment variables, their syntax changed, see | ||
| [List and map syntax](#list-and-map-syntax). | ||
| - If you have scripts hitting client-token endpoints, they may now need | ||
| [elevation](#adapting-your-scripts). | ||
|
|
||
| ## Config Changes | ||
|
|
||
| ### YAML config file removed | ||
|
|
||
| The YAML config file (`config.yml`) is no longer supported. Gotify can now be | ||
| only configured by environment variables, which can be loaded from an env file. | ||
| The first existing file from this search order is loaded: | ||
|
|
||
| 1. `gotify-server.env` (in the working directory) | ||
| 2. `$XDG_CONFIG_HOME/gotify/gotify-server.env` (`$XDG_CONFIG_HOME` falls back to `$HOME/.config` when unset) | ||
| 3. `/etc/gotify/server.env` | ||
|
|
||
| See the [Configuration](/docs/config) page for the full list of variables. | ||
|
|
||
| ### Migrating your config | ||
|
|
||
| The `migrate-config` command converts an existing `config.yml` to the new env | ||
| format. It prints the result to stdout. | ||
|
|
||
| ```bash | ||
| $ gotify-server migrate-config config.yml > gotify-server.env | ||
| ``` | ||
|
|
||
| With Docker: | ||
|
|
||
| ```bash | ||
| $ docker run --rm -v "$(pwd)/config.yml:/app/config.yml" gotify/server \ | ||
| migrate-config config.yml > gotify-server.env | ||
| ``` | ||
|
|
||
| ### Environment List and map syntax | ||
|
|
||
| Defining settings via environment variables was already possible, but the syntax | ||
| for list and map values has changed. If you set any of the variables below, update | ||
| their format. | ||
|
|
||
| **Lists** are now comma-separated instead of a YAML array: | ||
|
|
||
| - `GOTIFY_SERVER_TRUSTEDPROXIES` | ||
| - `GOTIFY_SERVER_CORS_ALLOWORIGINS` | ||
| - `GOTIFY_SERVER_CORS_ALLOWMETHODS` | ||
| - `GOTIFY_SERVER_CORS_ALLOWHEADERS` | ||
| - `GOTIFY_SERVER_STREAM_ALLOWEDORIGINS` | ||
| - `GOTIFY_SERVER_SSL_LETSENCRYPT_HOSTS` | ||
| - `GOTIFY_OIDC_SCOPES` | ||
|
|
||
| ```bash | ||
| # before | ||
| GOTIFY_SERVER_TRUSTEDPROXIES=[127.0.0.1/32, ::1] | ||
| # after | ||
| GOTIFY_SERVER_TRUSTEDPROXIES=127.0.0.1/32,::1 | ||
| ``` | ||
|
|
||
| **Maps** are now a JSON object instead of a YAML map: | ||
|
|
||
| - `GOTIFY_SERVER_RESPONSEHEADERS` | ||
|
|
||
| ```bash | ||
| # before | ||
| GOTIFY_SERVER_RESPONSEHEADERS={X-Custom-Header: "custom value"} | ||
| # after | ||
| GOTIFY_SERVER_RESPONSEHEADERS={"X-Custom-Header":"custom value"} | ||
| ``` | ||
|
|
||
| ## API Changes | ||
|
|
||
| Gotify 3.x introduces [session elevation](./session-elevation.md). A client | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "Introduces step up authentication via a session elevation timer" feels more self explanatory? |
||
| tokens requires special elevation for sensitive, hard-to-undo actions. | ||
|
|
||
| HTTP Basic auth and application tokens are unaffected. | ||
|
|
||
| ### Endpoints that now require elevation | ||
|
|
||
| With a non-elevated client token these return `403`: | ||
|
|
||
| | Endpoint | Action | | ||
| | :-------------------------------------------- | :----------------------------- | | ||
| | `POST /current/user/password` | Change current user's password | | ||
| | `DELETE /client/{id}` | Delete a client | | ||
| | `DELETE /application/{id}` | Delete an application | | ||
| | `POST /client/{id}/elevate` | Elevate a client token | | ||
| | `GET /user`, `GET`/`POST`/`DELETE /user/{id}` | Manage users (admin) | | ||
|
|
||
| The `Client` and `CurrentUser` models have gotten elevation-related fields. See the | ||
| [API documentation](/api-docs) for details. | ||
|
|
||
| ### Adapting your scripts | ||
|
|
||
| Scripts that hit the endpoints above with a client token now need that token to | ||
| be elevated. Either: | ||
|
|
||
| - Use HTTP Basic auth as they are elevated by default. | ||
| - Elevate the client in the WebUI or the api with basic auth. | ||
|
|
||
| ## CLI Changes | ||
|
|
||
| The binary now uses subcommands. You should migrate to using the `serve` | ||
| subcommand. For backwards compatibility running goverter without a command will | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The project name is wrong (?) |
||
| continue to serve the server. | ||
|
|
||
| ```bash | ||
| $ ./gotify-linux-amd64 serve | ||
| ``` | ||
|
|
||
| The Docker image already defaults to `serve`, so `docker run` and Docker Compose | ||
| setups keep working unchanged. | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,106 @@ | ||
| # OpenID Connect (OIDC) | ||
|
|
||
| [[toc]] | ||
|
|
||
| Gotify supports OpenID Connect for Single Sign-On (SSO), allowing users to authenticate via an external identity provider such as Authelia or Dex. | ||
|
|
||
| ::: warning | ||
| The identity provider **must** support [PKCE](https://oauth.net/2/pkce/) (Proof Key for Code Exchange). IdPs without PKCE support are currently unsupported. | ||
| ::: | ||
|
|
||
| ## Configuration | ||
|
|
||
| | Variable | Description | | ||
| | :----------------------------- | :--------------------------------------------------------------------------------------------------------- | | ||
| | `GOTIFY_OIDC_ENABLED` | Enable OIDC login. | | ||
| | `GOTIFY_OIDC_ISSUER` | The OIDC issuer URL. Used to discover endpoints via `/.well-known/openid-configuration`. | | ||
| | `GOTIFY_OIDC_CLIENTID` | The client ID registered with your identity provider. | | ||
| | `GOTIFY_OIDC_CLIENTSECRET` | The client secret. | | ||
| | `GOTIFY_OIDC_REDIRECTURL` | The callback URL the identity provider redirects to after authentication. Must match your provider config. | | ||
| | `GOTIFY_OIDC_AUTOREGISTER` | Automatically create a new Gotify user on first OIDC login. | | ||
| | `GOTIFY_OIDC_USERNAMECLAIM` | The OIDC claim used to determine the username. Common values: `preferred_username` or `email`. | | ||
| | `GOTIFY_OIDC_LINK_BY_USERNAME` | Link an OIDC identity to an existing local user with the same username. Disabled by default. | | ||
| | `GOTIFY_OIDC_SCOPES` | Comma-separated scopes to request. Defaults to `openid,profile,email`. | | ||
|
|
||
| ```bash | ||
| GOTIFY_OIDC_ENABLED=true | ||
| GOTIFY_OIDC_ISSUER=https://auth.example.org | ||
| GOTIFY_OIDC_CLIENTID=gotify | ||
| GOTIFY_OIDC_CLIENTSECRET=YOUR_CLIENT_SECRET | ||
| GOTIFY_OIDC_REDIRECTURL=https://gotify.example.org/auth/oidc/callback | ||
| GOTIFY_OIDC_AUTOREGISTER=true | ||
| GOTIFY_OIDC_USERNAMECLAIM=preferred_username | ||
| GOTIFY_OIDC_LINK_BY_USERNAME=false | ||
| GOTIFY_OIDC_SCOPES=openid,profile,email | ||
| ``` | ||
|
|
||
| See the [Configuration](/docs/config) page for the full config reference. | ||
|
|
||
| ### Redirect URL | ||
|
|
||
| - The redirect URL must always end with `/auth/oidc/callback`. | ||
| - If Gotify is served at the root, the redirect URL is `https://gotify.example.org/auth/oidc/callback`. | ||
| - If Gotify is served on a sub-path (e.g. behind a reverse proxy at `/gotify/`), the sub-path must be included: `https://example.org/gotify/auth/oidc/callback`. | ||
| - For the **Android app** to support OIDC login, you must add `gotify://oidc/callback` as an additional redirect URL in your identity provider's client configuration. | ||
|
|
||
| This URL must match **exactly** between the Gotify config and your identity provider's client configuration. | ||
|
|
||
| ## Linking by username | ||
|
|
||
| Gotify identifies users by username. When the OIDC username claim clashes with an existing local user that is not yet bound to an OIDC identity, this login is rejected by default. Set `GOTIFY_OIDC_LINK_BY_USERNAME=true` to bind OIDC identities to existing local users. | ||
|
|
||
| Only enable it if you trust that usernames in your identity provider map to the same people as your Gotify usernames. | ||
|
|
||
| ## Authelia | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe put a "sample IdP config" section and out Authelia as a subsection |
||
|
|
||
| [Authelia](https://www.authelia.com/) is a self-hosted authentication and authorization server. | ||
|
|
||
| ::: details Authelia configuration (configuration.yml) | ||
|
|
||
| ```yml | ||
| identity_providers: | ||
| oidc: | ||
| clients: | ||
| - client_id: 'gotify' | ||
| client_name: 'gotify' | ||
| client_secret: '$pbkdf2-sha512$310000$...' # generate with: authelia crypto hash generate pbkdf2 | ||
| public: false | ||
| authorization_policy: 'two_factor' | ||
| require_pkce: true | ||
| pkce_challenge_method: 'S256' | ||
| consent_mode: implicit | ||
| redirect_uris: | ||
| - 'https://gotify.example.org/auth/oidc/callback' # See redirect url docs | ||
| - 'gotify://oidc/callback' # Required for Android app OIDC login | ||
| scopes: | ||
| - 'openid' | ||
| - 'profile' | ||
| - 'email' | ||
| response_types: | ||
| - 'code' | ||
| grant_types: | ||
| - 'authorization_code' | ||
| access_token_signed_response_alg: 'none' | ||
| userinfo_signed_response_alg: 'none' | ||
| token_endpoint_auth_method: 'client_secret_basic' | ||
| ``` | ||
|
|
||
| ::: | ||
|
|
||
| ## Dex | ||
|
|
||
| [Dex](https://dexidp.io/) is a federated OpenID Connect provider. | ||
|
|
||
| ::: details Dex configuration | ||
|
|
||
| ```yml | ||
| staticClients: | ||
| - id: gotify | ||
| redirectURIs: | ||
| - 'https://gotify.example.org/auth/oidc/callback' # See redirect url docs | ||
| - 'gotify://oidc/callback' # Required for Android app OIDC login | ||
| name: 'Gotify' | ||
| secret: secret | ||
| ``` | ||
|
|
||
| ::: | ||
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.
Unless we intend to maintain the 2.x trunk after 3.x release this probably should go in the migration section (or removed in place of the migration CLI usage)