Merge remote-tracking branch 'origin/master' into feat-settings-ui

# Conflicts:
#	web/package.json
#	web/pnpm-lock.yaml
feat-otp-verification
James Elliott 2023-02-05 19:59:02 +11:00
commit 9e5aa1c1a9
No known key found for this signature in database
GPG Key ID: 0F1C4A096E857E49
84 changed files with 997 additions and 734 deletions

View File

@ -11,6 +11,10 @@ insert_final_newline = true
indent_style = space indent_style = space
indent_size = 2 indent_size = 2
[{.github/pre-commit,.github/required-apps,.github/commit-msg}]
indent_style = space
indent_size = 2
[.buildkite/hooks/**] [.buildkite/hooks/**]
indent_style = space indent_style = space
indent_size = 2 indent_size = 2

3
.github/commit-msg vendored
View File

@ -1,5 +1,6 @@
#!/bin/sh #!/bin/sh
. "$(dirname "$0")/_/husky.sh" . "$(dirname "$0")/_/husky.sh"
. "$(dirname "$0")/required-apps" . "$(dirname "$0")/required-apps"
cd web && ${PMGR} commitlint --edit "$1" cd web && ${PMGR_EXEC} commitlint --edit "$1"

2
.github/pre-commit vendored
View File

@ -8,4 +8,4 @@ fi
. "$(dirname "$0")/required-apps" . "$(dirname "$0")/required-apps"
golangci-lint run -v --fix && \ golangci-lint run -v --fix && \
cd web && "${PMGR}" lint cd web && ${PMGR_RUN} lint

23
.github/required-apps vendored
View File

@ -1,19 +1,20 @@
#!/bin/sh #!/bin/sh
export PMGR=pnpm
if [ ! -x "$(command -v golangci-lint)" ]; then if [ ! -x "$(command -v golangci-lint)" ]; then
echo "You must install golangci-lint." echo "You must install golangci-lint."
exit 1 exit 1
fi fi
if [ ! -x "$(command -v pnpm)" ]; then if [ -x "$(command -v pnpm)" ]; then
export PMGR=yarn export PMGR_RUN="pnpm"
if [ ! -x "$(command -v yarn)" ]; then export PMGR_EXEC="pnpm"
export PMGR=npm elif [ -x "$(command -v yarn)" ]; then
if [ ! -x "$(command -v npm)" ]; then export PMGR_RUN="yarn run"
echo "You must install a node package manager." export PMGR_EXEC="yarn dlx"
exit 1 elif [ -x "$(command -v npm)" ]; then
fi export PMGR_RUN="npm run"
fi export PMGR_EXEC="npx"
else
echo "You must install a node package manager (pnpm, yarn, or npm)."
exit 1
fi fi

View File

@ -15,7 +15,7 @@ RUN yarn global add pnpm && \
# ======================================= # =======================================
# ===== Build image for the backend ===== # ===== Build image for the backend =====
# ======================================= # =======================================
FROM golang:1.19.5-alpine AS builder-backend FROM golang:1.20.0-alpine AS builder-backend
WORKDIR /go/src/app WORKDIR /go/src/app

View File

@ -13,7 +13,7 @@ RUN yarn install --frozen-lockfile && yarn build
# ======================================= # =======================================
# ===== Build image for the backend ===== # ===== Build image for the backend =====
# ======================================= # =======================================
FROM golang:1.19.5-alpine AS builder-backend FROM golang:1.20.0-alpine AS builder-backend
WORKDIR /go/src/app WORKDIR /go/src/app

View File

@ -855,7 +855,7 @@ paths:
summary: OAuth 2.0 Authorization Server Metadata summary: OAuth 2.0 Authorization Server Metadata
description: > description: >
This endpoint retrieves the OAuth 2.0 Authorization Server Metadata document (RFC8414) used by clients to This endpoint retrieves the OAuth 2.0 Authorization Server Metadata document (RFC8414) used by clients to
perform discovery for an OAuth 2.0 Authorization Server. See https://www.rfc-editor.org/rfc/rfc8414. perform discovery for an OAuth 2.0 Authorization Server. See https://datatracker.ietf.org/doc/html/rfc8414.
responses: responses:
"200": "200":
description: OK description: OK
@ -2878,8 +2878,8 @@ components:
description: > description: >
JSON array containing a list of the JWS [JWS] signing algorithms (alg values) [JWA] supported by the JSON array containing a list of the JWS [JWS] signing algorithms (alg values) [JWA] supported by the
UserInfo Endpoint to encode the Claims in a JWT [JWT]. The value none MAY be included. See Also: UserInfo Endpoint to encode the Claims in a JWT [JWT]. The value none MAY be included. See Also:
JWS: https://datatracker.ietf.org/doc/html/rfc7515 JWA: https://datatracker.ietf.org/doc/html/rfc7518 JWT: JWS: https://datatracker.ietf.org/doc/html/rfc7515 JWA: https://datatracker.ietf.org/doc/html/rfc7518
https://datatracker.ietf.org/doc/html/rfc7519 JWT: https://datatracker.ietf.org/doc/html/rfc7519
type: array type: array
example: ["none", "RS256"] example: ["none", "RS256"]
items: items:

View File

@ -426,7 +426,7 @@ authentication_backend:
## changed once attributed to a user otherwise it would break the configuration for that user. Technically, ## changed once attributed to a user otherwise it would break the configuration for that user. Technically,
## non-unique attributes like 'mail' can also be used but we don't recommend using them, we instead advise to use ## non-unique attributes like 'mail' can also be used but we don't recommend using them, we instead advise to use
## a filter to perform alternative lookups and the attributes mentioned above (sAMAccountName and uid) to ## a filter to perform alternative lookups and the attributes mentioned above (sAMAccountName and uid) to
## follow https://www.ietf.org/rfc/rfc2307.txt. ## follow https://datatracker.ietf.org/doc/html/rfc2307.
# username_attribute: uid # username_attribute: uid
## The additional_users_dn is prefixed to base_dn and delimited by a comma when searching for users. ## The additional_users_dn is prefixed to base_dn and delimited by a comma when searching for users.

View File

@ -1 +1 @@
canonifyURLs = false baseurl = "https://authelia-staging.netlify.app/"

View File

@ -1 +0,0 @@
canonifyURLs = false

View File

@ -1,2 +1 @@
canonifyURLs = false
baseurl = "https://authelia-staging.netlify.app/" baseurl = "https://authelia-staging.netlify.app/"

View File

@ -256,8 +256,8 @@ truncation that [Bcrypt] does. It is not supported by many other systems.*
Controls the hashing cost when hashing passwords using [Bcrypt]. Controls the hashing cost when hashing passwords using [Bcrypt].
[Argon2]: https://www.rfc-editor.org/rfc/rfc9106.html [Argon2]: https://datatracker.ietf.org/doc/html/rfc9106
[Scrypt]: https://en.wikipedia.org/wiki/Scrypt [Scrypt]: https://en.wikipedia.org/wiki/Scrypt
[PBKDF2]: https://www.ietf.org/rfc/rfc2898.html [PBKDF2]: https://datatracker.ietf.org/doc/html/rfc2898
[SHA2 Crypt]: https://www.akkadia.org/drepper/SHA-crypt.txt [SHA2 Crypt]: https://www.akkadia.org/drepper/SHA-crypt.txt
[Bcrypt]: https://en.wikipedia.org/wiki/Bcrypt [Bcrypt]: https://en.wikipedia.org/wiki/Bcrypt

View File

@ -316,4 +316,4 @@ for your users.
[username attribute]: #usernameattribute [username attribute]: #usernameattribute
[TechNet wiki]: https://social.technet.microsoft.com/wiki/contents/articles/5392.active-directory-ldap-syntax-filters.aspx [TechNet wiki]: https://social.technet.microsoft.com/wiki/contents/articles/5392.active-directory-ldap-syntax-filters.aspx
[RFC2307]: https://www.rfc-editor.org/rfc/rfc2307.html [RFC2307]: https://datatracker.ietf.org/doc/html/rfc2307

View File

@ -119,7 +119,7 @@ identity_providers:
clients: clients:
- id: myapp - id: myapp
description: My Application description: My Application
secret: '$plaintext$this_is_a_secret' secret: '$pbkdf2-sha512$310000$c8p78n7pUMln0jzvd4aK4Q$JNRBzwAo0ek5qKn50cFzzvE9RXV88h1wJn5KGiHrD0YKtZaR/nCb2CJPOsKaPK0hjf.9yHxzQGZziziccp6Yng' # The digest of 'insecure_secret'.
sector_identifier: '' sector_identifier: ''
public: false public: false
authorization_policy: two_factor authorization_policy: two_factor
@ -170,9 +170,9 @@ encoded PEM format used to sign/encrypt the [OpenID Connect 1.0] [JWT]'s. When c
JSON key's in the JWKs [Discoverable Endpoint](../../integration/openid-connect/introduction.md#discoverable-endpoints) JSON key's in the JWKs [Discoverable Endpoint](../../integration/openid-connect/introduction.md#discoverable-endpoints)
as per [RFC7517]. as per [RFC7517].
[RFC7517]: https://www.rfc-editor.org/rfc/rfc7517 [RFC7517]: https://datatracker.ietf.org/doc/html/rfc7517
[x5c]: https://www.rfc-editor.org/rfc/rfc7517#section-4.7 [x5c]: https://datatracker.ietf.org/doc/html/rfc7517#section-4.7
[x5t]: https://www.rfc-editor.org/rfc/rfc7517#section-4.8 [x5t]: https://datatracker.ietf.org/doc/html/rfc7517#section-4.8
The first certificate in the chain must have the public key for the [issuer_private_key](#issuerprivatekey), each The first certificate in the chain must have the public key for the [issuer_private_key](#issuerprivatekey), each
certificate in the chain must be valid for the current date, and each certificate in the chain should be signed by the certificate in the chain must be valid for the current date, and each certificate in the chain should be signed by the
@ -251,7 +251,7 @@ this value.
{{< confkey type="string" default="public_clients_only" required="no" >}} {{< confkey type="string" default="public_clients_only" required="no" >}}
[Proof Key for Code Exchange](https://www.rfc-editor.org/rfc/rfc7636.html) enforcement policy: if specified, must be [Proof Key for Code Exchange](https://datatracker.ietf.org/doc/html/rfc7636) enforcement policy: if specified, must be
either `never`, `public_clients_only` or `always`. either `never`, `public_clients_only` or `always`.
If set to `public_clients_only` (default), [PKCE] will be required for public clients using the If set to `public_clients_only` (default), [PKCE] will be required for public clients using the
@ -530,12 +530,12 @@ To integrate Authelia's [OpenID Connect 1.0] implementation with a relying party
[token lifespan]: https://docs.apigee.com/api-platform/antipatterns/oauth-long-expiration [token lifespan]: https://docs.apigee.com/api-platform/antipatterns/oauth-long-expiration
[OpenID Connect 1.0]: https://openid.net/connect/ [OpenID Connect 1.0]: https://openid.net/connect/
[JWT]: https://www.rfc-editor.org/rfc/rfc7519.html [JWT]: https://datatracker.ietf.org/doc/html/rfc7519
[RFC6234]: https://www.rfc-editor.org/rfc/rfc6234.html [RFC6234]: https://datatracker.ietf.org/doc/html/rfc6234
[RFC4648]: https://www.rfc-editor.org/rfc/rfc4648.html [RFC4648]: https://datatracker.ietf.org/doc/html/rfc4648
[RFC7468]: https://www.rfc-editor.org/rfc/rfc7468.html [RFC7468]: https://datatracker.ietf.org/doc/html/rfc7468
[RFC6749 Section 2.1]: https://www.rfc-editor.org/rfc/rfc6749.html#section-2.1 [RFC6749 Section 2.1]: https://datatracker.ietf.org/doc/html/rfc6749#section-2.1
[PKCE]: https://www.rfc-editor.org/rfc/rfc7636.html [PKCE]: https://datatracker.ietf.org/doc/html/rfc7636
[Authorization Code Flow]: https://openid.net/specs/openid-connect-core-1_0.html#CodeFlowAuth [Authorization Code Flow]: https://openid.net/specs/openid-connect-core-1_0.html#CodeFlowAuth
[Subject Identifier Type]: https://openid.net/specs/openid-connect-core-1_0.html#SubjectIDTypes [Subject Identifier Type]: https://openid.net/specs/openid-connect-core-1_0.html#SubjectIDTypes
[Pairwise Identifier Algorithm]: https://openid.net/specs/openid-connect-core-1_0.html#PairwiseAlg [Pairwise Identifier Algorithm]: https://openid.net/specs/openid-connect-core-1_0.html#PairwiseAlg

View File

@ -164,7 +164,7 @@ characters and the user password is changed to this value.
{{< confkey type="string" required="yes" >}} {{< confkey type="string" required="yes" >}}
The sender is used to construct both the SMTP command `MAIL FROM` and to add the `FROM` header. This address must be The sender is used to construct both the SMTP command `MAIL FROM` and to add the `FROM` header. This address must be
in [RFC5322](https://www.rfc-editor.org/rfc/rfc5322.html#section-3.4) format. This means it must one of two formats: in [RFC5322](https://datatracker.ietf.org/doc/html/rfc5322#section-3.4) format. This means it must one of two formats:
* jsmith@domain.com * jsmith@domain.com
* John Smith <jsmith@domain.com> * John Smith <jsmith@domain.com>

View File

@ -154,7 +154,7 @@ The value must be one or more certificates encoded in the DER base64 ([RFC4648])
### private_key ### private_key
{{< confkey type="string" required="yes" >}} {{< confkey type="string" required="no" >}}
*__Important Note:__ This can also be defined using a [secret](../methods/secrets.md) which is __strongly recommended__ *__Important Note:__ This can also be defined using a [secret](../methods/secrets.md) which is __strongly recommended__
especially for containerized deployments.* especially for containerized deployments.*
@ -163,6 +163,8 @@ The private key to be used with the [certificate_chain](#certificatechain) for m
The value must be one private key encoded in the DER base64 ([RFC4648]) encoded PEM format. The value must be one private key encoded in the DER base64 ([RFC4648]) encoded PEM format.
[RFC4648]: https://datatracker.ietf.org/doc/html/rfc4648
## Server Buffers ## Server Buffers
### read ### read

View File

@ -172,5 +172,5 @@ at least a minimal configuration that has the storage backend connection details
See the [CLI Documentation](../../reference/cli/authelia/authelia_storage_user_totp_export.md) for methods to perform See the [CLI Documentation](../../reference/cli/authelia/authelia_storage_user_totp_export.md) for methods to perform
exports. exports.
[RFC4226]: https://www.rfc-editor.org/rfc/rfc4226.html [RFC4226]: https://datatracker.ietf.org/doc/html/rfc4226
[RFC6238]: https://www.rfc-editor.org/rfc/rfc6238.html [RFC6238]: https://datatracker.ietf.org/doc/html/rfc6238

View File

@ -588,8 +588,8 @@ The match type `Equals` matches if the value extracted from the pattern is equal
match value is a list/slice). match value is a list/slice).
The regex groups are case-insensitive due to the fact that the regex groups are used in domain criteria and domain names The regex groups are case-insensitive due to the fact that the regex groups are used in domain criteria and domain names
should not be compared in a case-sensitive way as per the [RFC4343](https://www.rfc-editor.org/rfc/rfc4343.html) should not be compared in a case-sensitive way as per the [RFC4343](https://datatracker.ietf.org/doc/html/rfc4343)
abstract and [RFC3986 Section 3.2.2](https://www.rfc-editor.org/rfc/rfc3986#section-3.2.2). abstract and [RFC3986 Section 3.2.2](https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.2).
We do not currently apply any other normalization to usernames or groups when matching these groups. As such it's We do not currently apply any other normalization to usernames or groups when matching these groups. As such it's
generally *__not recommended__* to use these patterns with usernames or groups which contain characters that are not generally *__not recommended__* to use these patterns with usernames or groups which contain characters that are not
@ -664,6 +664,6 @@ access_control:
policy: bypass policy: bypass
``` ```
[RFC7231]: https://www.rfc-editor.org/rfc/rfc7231.html [RFC7231]: https://datatracker.ietf.org/doc/html/rfc7231
[RFC5789]: https://www.rfc-editor.org/rfc/rfc5789.html [RFC5789]: https://datatracker.ietf.org/doc/html/rfc5789
[RFC4918]: https://www.rfc-editor.org/rfc/rfc4918.html [RFC4918]: https://datatracker.ietf.org/doc/html/rfc4918

View File

@ -15,11 +15,8 @@ aliases:
- /docs/configuration/session/ - /docs/configuration/session/
--- ---
__Authelia__ relies on session cookies to authenticate users. When the user visits a website of the protected domain __Authelia__ relies on session cookies to authorize user access to various protected websites. This section configures
`example.com` for the first time, Authelia detects that there is no cookie for that user. Consequently, Authelia the session cookie behaviour and the domains which Authelia can service authorization requests for.
redirects the user to the login portal through which the user should authenticate to get a cookie which is valid for
`*.example.com`, meaning all websites of the domain. At the next request, Authelia receives the cookie associated to the
authenticated user and can then order the reverse proxy to let the request pass through to the application.
## Configuration ## Configuration
@ -34,8 +31,9 @@ session:
remember_me: 1M remember_me: 1M
cookies: cookies:
- name: authelia_session - domain: example.com
domain: example.com authelia_url: https://auth.example.com
name: authelia_session
same_site: lax same_site: lax
inactivity: 5m inactivity: 5m
expiration: 1h expiration: 1h
@ -75,10 +73,8 @@ characters.
{{< confkey type="string" required="no" >}} {{< confkey type="string" required="no" >}}
_**Deprecation Notice:** This option is deprecated. See the [cookies](#cookies) section instead._ _**Deprecation Notice:** This option is deprecated. See the [cookies](#cookies) section and specifically the
[cookies domain](#domain-1) option instead._
The domain the cookie is assigned to protect. This must be the same as the domain Authelia is served on or the root
of the domain. For example if listening on auth.example.com the cookie should be auth.example.com or example.com.
This value automatically maps to a single cookies configuration using the default values. It cannot be assigned at the This value automatically maps to a single cookies configuration using the default values. It cannot be assigned at the
same time as a `cookies` configuration. same time as a `cookies` configuration.
@ -128,28 +124,25 @@ The list of specific cookie domains that Authelia is configured to handle. Domai
automatically be denied by Authelia. The list allows administrators to define multiple session cookie domain automatically be denied by Authelia. The list allows administrators to define multiple session cookie domain
configurations with individual settings. configurations with individual settings.
#### name
{{< confkey type="string" required="no" >}}
*__Default Value:__ This option takes its default value from the [name](#name) setting above.*
The name of the session cookie. By default this is set to the `name` value in the main session configuration section.
#### domain #### domain
{{< confkey type="string" required="yes" >}} {{< confkey type="string" required="yes" >}}
The domain the cookie is assigned to protect. This must be the same as the domain Authelia is served on or the root *__Important Note:__ Browsers have rules regarding which cookie domains a website can write. In particular this.*
of the domain, and consequently if the [authelia_url](#authelia_url) is configured must be able to read and write cookies
for the domain. For example if listening on `auth.example.com` the cookie should be either `auth.example.com` or
`example.com`.
Please note most good DynamicDNS solutions fall into a specially protected group of domains and browsers do not allow The domain the session cookie is assigned to protect. This must be the same as the domain Authelia is served on or the
you to write cookies for the root domain. i.e. if you have been assigned `john.duckdns.org` you can't use `duckdns.org` root of the domain, and consequently if the [authelia_url](#authelia_url) is configured must be able to read and write
for the domain value as browsers will not allow `john.duckdns.org` to read or write cookies for `duckdns.org`. cookies for this domain.
Consequently, if you have `john.duckdns.org` and `mary.duckdns.org` you cannot share cookies between these domains. For example if Authelia is accessible via the URL `https://auth.example.com` the domain should be either
`auth.example.com` or `example.com`.
The value must not match a domain on the [Public Suffix List](https://publicsuffix.org/list/) as browsers do not allow
websites to write cookies for these domains. This includes most Dynamic DNS services such as `duckdns.org`. You should
use your domain instead of `duckdns.org` for this value, for example `example.duckdns.org`.
Consequently, if you have `example.duckdns.org` and `example-auth.duckdns.org` you cannot share cookies between these
domains.
#### authelia_url #### authelia_url
@ -160,10 +153,24 @@ that the `authelia_url` option is ineffectual for both NGINX and HAProxy, or any
implementation.* implementation.*
This is a completely optional URL which is the root URL of your Authelia installation for this cookie domain which can This is a completely optional URL which is the root URL of your Authelia installation for this cookie domain which can
be used to generate the appropriate redirection for proxies which support this. be used to generate the appropriate redirection for proxies which support this. This URL must:
1. Be able to read and write cookies for the configured [domain](#domain-1).
2. Use the `https://` scheme.
3. Include the path if relevant (i.e. `https://example.com/authelia` rather than `https://example.com` if you're using the
[server path option](../miscellaneous/server.md#path) of `authelia` and if the Authelia portal is inaccessible from
`https://example.com`).
If this option is absent you must use the appropriate query parameter or header for your relevant proxy. If this option is absent you must use the appropriate query parameter or header for your relevant proxy.
#### name
{{< confkey type="string" required="no" >}}
*__Default Value:__ This option takes its default value from the [name](#name) setting above.*
The name of the session cookie. By default this is set to the `name` value in the main session configuration section.
#### same_site #### same_site
{{< confkey type="string" required="no" >}} {{< confkey type="string" required="no" >}}

View File

@ -21,7 +21,7 @@ In order to build and contribute to __Authelia__, you need to make sure the foll
* General: * General:
* [git] * [git]
* Backend Development: * Backend Development:
* [go] *(v1.19 or greater)* * [go] *(v1.20 or greater)*
* [gcc] * [gcc]
* Frontend Development * Frontend Development
* [Node.js] *(v18 or greater)* * [Node.js] *(v18 or greater)*

View File

@ -22,14 +22,7 @@ community: true
## Before You Begin ## Before You Begin
### Common Notes {{% oidc-common %}}
1. You are *__required__* to utilize a unique client id for every client.
2. The client id on this page is merely an example and you can theoretically use any alphanumeric string.
3. You *__should not__* use the client secret in this example, We *__strongly recommend__* reading the
[Generating Client Secrets] guide instead.
[Generating Client Secrets]: ../specific-information.md#generating-client-secrets
### Assumptions ### Assumptions
@ -38,7 +31,7 @@ This example makes the following assumptions:
* __Application Root URL:__ `https://guacamole.example.com` * __Application Root URL:__ `https://guacamole.example.com`
* __Authelia Root URL:__ `https://auth.example.com` * __Authelia Root URL:__ `https://auth.example.com`
* __Client ID:__ `guacamole` * __Client ID:__ `guacamole`
* __Client Secret:__ `guacamole_client_secret` * __Client Secret:__ `insecure_secret`
## Configuration ## Configuration
@ -66,7 +59,7 @@ The following YAML configuration is an example __Authelia__
```yaml ```yaml
- id: guacamole - id: guacamole
description: Apache Guacamole description: Apache Guacamole
secret: '$plaintext$guacamole_client_secret' secret: '$pbkdf2-sha512$310000$c8p78n7pUMln0jzvd4aK4Q$JNRBzwAo0ek5qKn50cFzzvE9RXV88h1wJn5KGiHrD0YKtZaR/nCb2CJPOsKaPK0hjf.9yHxzQGZziziccp6Yng' # The digest of 'insecure_secret'.
public: false public: false
authorization_policy: two_factor authorization_policy: two_factor
redirect_uris: redirect_uris:

View File

@ -22,14 +22,7 @@ community: true
## Before You Begin ## Before You Begin
### Common Notes {{% oidc-common %}}
1. You are *__required__* to utilize a unique client id for every client.
2. The client id on this page is merely an example and you can theoretically use any alphanumeric string.
3. You *__should not__* use the client secret in this example, We *__strongly recommend__* reading the
[Generating Client Secrets] guide instead.
[Generating Client Secrets]: ../specific-information.md#generating-client-secrets
### Assumptions ### Assumptions
@ -38,7 +31,7 @@ This example makes the following assumptions:
* __Application Root URL:__ `https://argocd.example.com` * __Application Root URL:__ `https://argocd.example.com`
* __Authelia Root URL:__ `https://auth.example.com` * __Authelia Root URL:__ `https://auth.example.com`
* __Client ID:__ `argocd` * __Client ID:__ `argocd`
* __Client Secret:__ `argocd_client_secret` * __Client Secret:__ `insecure_secret`
* __CLI Client ID:__ `argocd-cli` * __CLI Client ID:__ `argocd-cli`
## Configuration ## Configuration
@ -51,7 +44,7 @@ To configure [Argo CD] to utilize Authelia as an [OpenID Connect 1.0] Provider u
name: Authelia name: Authelia
issuer: https://auth.example.com issuer: https://auth.example.com
clientID: argocd clientID: argocd
clientSecret: argocd_client_secret clientSecret: insecure_secret
cliClientID: argocd-cli cliClientID: argocd-cli
requestedScopes: requestedScopes:
- openid - openid
@ -69,7 +62,7 @@ which will operate with the above example:
```yaml ```yaml
- id: argocd - id: argocd
description: Argo CD description: Argo CD
secret: '$plaintext$argocd_client_secret' secret: '$pbkdf2-sha512$310000$c8p78n7pUMln0jzvd4aK4Q$JNRBzwAo0ek5qKn50cFzzvE9RXV88h1wJn5KGiHrD0YKtZaR/nCb2CJPOsKaPK0hjf.9yHxzQGZziziccp6Yng' # The digest of 'insecure_secret'.
public: false public: false
authorization_policy: two_factor authorization_policy: two_factor
redirect_uris: redirect_uris:

View File

@ -22,14 +22,7 @@ community: true
## Before You Begin ## Before You Begin
### Common Notes {{% oidc-common %}}
1. You are *__required__* to utilize a unique client id for every client.
2. The client id on this page is merely an example and you can theoretically use any alphanumeric string.
3. You *__should not__* use the client secret in this example, We *__strongly recommend__* reading the
[Generating Client Secrets] guide instead.
[Generating Client Secrets]: ../specific-information.md#generating-client-secrets
### Assumptions ### Assumptions
@ -38,13 +31,13 @@ This example makes the following assumptions:
* __Application Root URL:__ `https://bookstack.example.com` * __Application Root URL:__ `https://bookstack.example.com`
* __Authelia Root URL:__ `https://auth.example.com` * __Authelia Root URL:__ `https://auth.example.com`
* __Client ID:__ `bookstack` * __Client ID:__ `bookstack`
* __Client Secret:__ `bookstack_client_secret` * __Client Secret:__ `insecure_secret`
*__Important Note:__ [BookStack] does not properly URL encode the secret per [RFC6749 Appendix B] at the time this *__Important Note:__ [BookStack] does not properly URL encode the secret per [RFC6749 Appendix B] at the time this
article was last modified (noted at the bottom). This means you'll either have to use only alphanumeric characters for article was last modified (noted at the bottom). This means you'll either have to use only alphanumeric characters for
the secret or URL encode the secret yourself.* the secret or URL encode the secret yourself.*
[RFC6749 Appendix B]: https://www.rfc-editor.org/rfc/rfc6749#appendix-B [RFC6749 Appendix B]: https://datatracker.ietf.org/doc/html/rfc6749#appendix-B
## Configuration ## Configuration
@ -58,7 +51,7 @@ To configure [BookStack] to utilize Authelia as an [OpenID Connect 1.0] Provider
2. OIDC_NAME: `Authelia` 2. OIDC_NAME: `Authelia`
3. OIDC_DISPLAY_NAME_CLAIMS: `name` 3. OIDC_DISPLAY_NAME_CLAIMS: `name`
4. OIDC_CLIENT_ID: `bookstack` 4. OIDC_CLIENT_ID: `bookstack`
5. OIDC_CLIENT_SECRET: `bookstack_client_secret` 5. OIDC_CLIENT_SECRET: `insecure_secret`
6. OIDC_ISSUER: `https://auth.example.com` 6. OIDC_ISSUER: `https://auth.example.com`
7. OIDC_ISSUER_DISCOVER: `true` 7. OIDC_ISSUER_DISCOVER: `true`
@ -71,7 +64,7 @@ which will operate with the above example:
```yaml ```yaml
- id: bookstack - id: bookstack
description: BookStack description: BookStack
secret: '$plaintext$bookstack_client_secret' secret: '$pbkdf2-sha512$310000$c8p78n7pUMln0jzvd4aK4Q$JNRBzwAo0ek5qKn50cFzzvE9RXV88h1wJn5KGiHrD0YKtZaR/nCb2CJPOsKaPK0hjf.9yHxzQGZziziccp6Yng' # The digest of 'insecure_secret'.
public: false public: false
authorization_policy: two_factor authorization_policy: two_factor
redirect_uris: redirect_uris:

View File

@ -20,14 +20,7 @@ community: true
## Before You Begin ## Before You Begin
### Common Notes {{% oidc-common %}}
1. You are *__required__* to utilize a unique client id for every client.
2. The client id on this page is merely an example and you can theoretically use any alphanumeric string.
3. You *__should not__* use the client secret in this example, We *__strongly recommend__* reading the
[Generating Client Secrets] guide instead.
[Generating Client Secrets]: ../specific-information.md#generating-client-secrets
### Assumptions ### Assumptions
@ -36,13 +29,13 @@ This example makes the following assumptions:
* __Cloudflare Team Name:__ `example-team` * __Cloudflare Team Name:__ `example-team`
* __Authelia Root URL:__ `https://auth.example.com` * __Authelia Root URL:__ `https://auth.example.com`
* __Client ID:__ `cloudflare` * __Client ID:__ `cloudflare`
* __Client Secret:__ `cloudflare_client_secret` * __Client Secret:__ `insecure_secret`
*__Important Note:__ [Cloudflare Zero Trust] does not properly URL encode the secret per [RFC6749 Appendix B] at the *__Important Note:__ [Cloudflare Zero Trust] does not properly URL encode the secret per [RFC6749 Appendix B] at the
time this article was last modified (noted at the bottom). This means you'll either have to use only alphanumeric time this article was last modified (noted at the bottom). This means you'll either have to use only alphanumeric
characters for the secret or URL encode the secret yourself.* characters for the secret or URL encode the secret yourself.*
[RFC6749 Appendix B]: https://www.rfc-editor.org/rfc/rfc6749#appendix-B [RFC6749 Appendix B]: https://datatracker.ietf.org/doc/html/rfc6749#appendix-B
## Configuration ## Configuration
@ -62,7 +55,7 @@ To configure [Cloudflare Zero Trust] to utilize Authelia as an [OpenID Connect 1
6. Set the following values: 6. Set the following values:
1. Name: `Authelia` 1. Name: `Authelia`
2. App ID: `cloudflare` 2. App ID: `cloudflare`
3. Client Secret: `cloudflare_client_secret` 3. Client Secret: `insecure_secret`
4. Auth URL: `https://auth.example.com/api/oidc/authorization` 4. Auth URL: `https://auth.example.com/api/oidc/authorization`
5. Token URL: `https://auth.example.com/api/oidc/token` 5. Token URL: `https://auth.example.com/api/oidc/token`
6. Certificate URL: `https://auth.example.com/jwks.json` 6. Certificate URL: `https://auth.example.com/jwks.json`
@ -79,7 +72,7 @@ which will operate with the above example:
```yaml ```yaml
- id: cloudflare - id: cloudflare
description: Cloudflare ZeroTrust description: Cloudflare ZeroTrust
secret: '$plaintext$cloudflare_client_secret' secret: '$pbkdf2-sha512$310000$c8p78n7pUMln0jzvd4aK4Q$JNRBzwAo0ek5qKn50cFzzvE9RXV88h1wJn5KGiHrD0YKtZaR/nCb2CJPOsKaPK0hjf.9yHxzQGZziziccp6Yng' # The digest of 'insecure_secret'.
public: false public: false
authorization_policy: two_factor authorization_policy: two_factor
redirect_uris: redirect_uris:

View File

@ -22,14 +22,7 @@ community: true
## Before You Begin ## Before You Begin
### Common Notes {{% oidc-common %}}
1. You are *__required__* to utilize a unique client id for every client.
2. The client id on this page is merely an example and you can theoretically use any alphanumeric string.
3. You *__should not__* use the client secret in this example, We *__strongly recommend__* reading the
[Generating Client Secrets] guide instead.
[Generating Client Secrets]: ../specific-information.md#generating-client-secrets
### Assumptions ### Assumptions
@ -38,7 +31,7 @@ This example makes the following assumptions:
* __Application Root URL:__ `https://gitea.example.com` * __Application Root URL:__ `https://gitea.example.com`
* __Authelia Root URL:__ `https://auth.example.com` * __Authelia Root URL:__ `https://auth.example.com`
* __Client ID:__ `gitea` * __Client ID:__ `gitea`
* __Client Secret:__ `gitea_client_secret` * __Client Secret:__ `insecure_secret`
## Configuration ## Configuration
@ -54,7 +47,7 @@ To configure [Gitea] to utilize Authelia as an [OpenID Connect 1.0] Provider:
1. Authentication Name: `authelia` 1. Authentication Name: `authelia`
2. OAuth2 Provider: `OpenID Connect` 2. OAuth2 Provider: `OpenID Connect`
3. Client ID (Key): `gitea` 3. Client ID (Key): `gitea`
4. Client Secret: `gitea_client_secret` 4. Client Secret: `insecure_secret`
5. OpenID Connect Auto Discovery URL: `https://auth.example.com/.well-known/openid-configuration` 5. OpenID Connect Auto Discovery URL: `https://auth.example.com/.well-known/openid-configuration`
{{< figure src="gitea.png" alt="Gitea" width="300" >}} {{< figure src="gitea.png" alt="Gitea" width="300" >}}
@ -86,7 +79,7 @@ will operate with the above example:
```yaml ```yaml
- id: gitea - id: gitea
description: Gitea description: Gitea
secret: '$plaintext$gitea_client_secret' secret: '$pbkdf2-sha512$310000$c8p78n7pUMln0jzvd4aK4Q$JNRBzwAo0ek5qKn50cFzzvE9RXV88h1wJn5KGiHrD0YKtZaR/nCb2CJPOsKaPK0hjf.9yHxzQGZziziccp6Yng' # The digest of 'insecure_secret'.
public: false public: false
authorization_policy: two_factor authorization_policy: two_factor
redirect_uris: redirect_uris:

View File

@ -22,14 +22,7 @@ community: true
## Before You Begin ## Before You Begin
### Common Notes {{% oidc-common %}}
1. You are *__required__* to utilize a unique client id for every client.
2. The client id on this page is merely an example and you can theoretically use any alphanumeric string.
3. You *__should not__* use the client secret in this example, We *__strongly recommend__* reading the
[Generating Client Secrets] guide instead.
[Generating Client Secrets]: ../specific-information.md#generating-client-secrets
### Assumptions ### Assumptions
@ -38,7 +31,7 @@ This example makes the following assumptions:
* __Application Root URL:__ `https://gitlab.example.com` * __Application Root URL:__ `https://gitlab.example.com`
* __Authelia Root URL:__ `https://auth.example.com` * __Authelia Root URL:__ `https://auth.example.com`
* __Client ID:__ `gitlab` * __Client ID:__ `gitlab`
* __Client Secret:__ `gitlab_client_secret` * __Client Secret:__ `insecure_secret`
## Configuration ## Configuration
@ -65,7 +58,7 @@ gitlab_rails['omniauth_providers'] = [
send_scope_to_token_endpoint: "false", send_scope_to_token_endpoint: "false",
client_options: { client_options: {
identifier: "gitlab", identifier: "gitlab",
secret: "gitlab_client_secret", secret: "insecure_secret",
redirect_uri: "https://gitlab.example.com/users/auth/openid_connect/callback" redirect_uri: "https://gitlab.example.com/users/auth/openid_connect/callback"
} }
} }
@ -82,7 +75,7 @@ which will operate with the above example:
```yaml ```yaml
- id: gitlab - id: gitlab
description: GitLab description: GitLab
secret: '$plaintext$gitlab_client_secret' secret: '$pbkdf2-sha512$310000$c8p78n7pUMln0jzvd4aK4Q$JNRBzwAo0ek5qKn50cFzzvE9RXV88h1wJn5KGiHrD0YKtZaR/nCb2CJPOsKaPK0hjf.9yHxzQGZziziccp6Yng' # The digest of 'insecure_secret'.
public: false public: false
authorization_policy: two_factor authorization_policy: two_factor
redirect_uris: redirect_uris:

View File

@ -22,14 +22,7 @@ community: true
## Before You Begin ## Before You Begin
### Common Notes {{% oidc-common %}}
1. You are *__required__* to utilize a unique client id for every client.
2. The client id on this page is merely an example and you can theoretically use any alphanumeric string.
3. You *__should not__* use the client secret in this example, We *__strongly recommend__* reading the
[Generating Client Secrets] guide instead.
[Generating Client Secrets]: ../specific-information.md#generating-client-secrets
### Assumptions ### Assumptions
@ -38,7 +31,7 @@ This example makes the following assumptions:
* __Application Root URL:__ `https://grafana.example.com` * __Application Root URL:__ `https://grafana.example.com`
* __Authelia Root URL:__ `https://auth.example.com` * __Authelia Root URL:__ `https://auth.example.com`
* __Client ID:__ `grafana` * __Client ID:__ `grafana`
* __Client Secret:__ `grafana_client_secret` * __Client Secret:__ `insecure_secret`
## Configuration ## Configuration
@ -58,7 +51,7 @@ enabled = true
name = Authelia name = Authelia
icon = signin icon = signin
client_id = grafana client_id = grafana
client_secret = grafana_client_secret client_secret = insecure_secret
scopes = openid profile email groups scopes = openid profile email groups
empty_scopes = false empty_scopes = false
auth_url = https://auth.example.com/api/oidc/authorization auth_url = https://auth.example.com/api/oidc/authorization
@ -80,7 +73,7 @@ Configure the following environment variables:
| GF_AUTH_GENERIC_OAUTH_ENABLED | true | | GF_AUTH_GENERIC_OAUTH_ENABLED | true |
| GF_AUTH_GENERIC_OAUTH_NAME | Authelia | | GF_AUTH_GENERIC_OAUTH_NAME | Authelia |
| GF_AUTH_GENERIC_OAUTH_CLIENT_ID | grafana | | GF_AUTH_GENERIC_OAUTH_CLIENT_ID | grafana |
| GF_AUTH_GENERIC_OAUTH_CLIENT_SECRET | grafana_client_secret | | GF_AUTH_GENERIC_OAUTH_CLIENT_SECRET | insecure_secret |
| GF_AUTH_GENERIC_OAUTH_SCOPES | openid profile email groups | | GF_AUTH_GENERIC_OAUTH_SCOPES | openid profile email groups |
| GF_AUTH_GENERIC_OAUTH_EMPTY_SCOPES | false | | GF_AUTH_GENERIC_OAUTH_EMPTY_SCOPES | false |
| GF_AUTH_GENERIC_OAUTH_AUTH_URL | https://auth.example.com/api/oidc/authorization | | GF_AUTH_GENERIC_OAUTH_AUTH_URL | https://auth.example.com/api/oidc/authorization |
@ -100,7 +93,7 @@ which will operate with the above example:
```yaml ```yaml
- id: grafana - id: grafana
description: Grafana description: Grafana
secret: '$plaintext$grafana_client_secret' secret: '$pbkdf2-sha512$310000$c8p78n7pUMln0jzvd4aK4Q$JNRBzwAo0ek5qKn50cFzzvE9RXV88h1wJn5KGiHrD0YKtZaR/nCb2CJPOsKaPK0hjf.9yHxzQGZziziccp6Yng' # The digest of 'insecure_secret'.
public: false public: false
authorization_policy: two_factor authorization_policy: two_factor
redirect_uris: redirect_uris:

View File

@ -22,14 +22,7 @@ community: true
## Before You Begin ## Before You Begin
### Common Notes {{% oidc-common %}}
1. You are *__required__* to utilize a unique client id for every client.
2. The client id on this page is merely an example and you can theoretically use any alphanumeric string.
3. You *__should not__* use the client secret in this example, We *__strongly recommend__* reading the
[Generating Client Secrets] guide instead.
[Generating Client Secrets]: ../specific-information.md#generating-client-secrets
### Assumptions ### Assumptions
@ -38,7 +31,7 @@ This example makes the following assumptions:
* __Application Root URL:__ `https://harbor.example.com` * __Application Root URL:__ `https://harbor.example.com`
* __Authelia Root URL:__ `https://auth.example.com` * __Authelia Root URL:__ `https://auth.example.com`
* __Client ID:__ `harbor` * __Client ID:__ `harbor`
* __Client Secret:__ `harbor_client_secret` * __Client Secret:__ `insecure_secret`
## Configuration ## Configuration
@ -54,7 +47,7 @@ To configure [Harbor] to utilize Authelia as an [OpenID Connect 1.0] Provider:
1. OIDC Provider Name: `Authelia` 1. OIDC Provider Name: `Authelia`
2. OIDC Provider Endpoint: `https://auth.example.com` 2. OIDC Provider Endpoint: `https://auth.example.com`
3. OIDC Client ID: `harbor` 3. OIDC Client ID: `harbor`
4. OIDC Client Secret: `harbor_client_secret` 4. OIDC Client Secret: `insecure_secret`
5. Group Claim Name: `groups` 5. Group Claim Name: `groups`
6. OIDC Scope: `openid,profile,email,groups` 6. OIDC Scope: `openid,profile,email,groups`
7. For OIDC Admin Group you can specify a group name that matches your authentication backend. 7. For OIDC Admin Group you can specify a group name that matches your authentication backend.
@ -73,7 +66,7 @@ which will operate with the above example:
```yaml ```yaml
- id: harbor - id: harbor
description: Harbor description: Harbor
secret: '$plaintext$harbor_client_secret' secret: '$pbkdf2-sha512$310000$c8p78n7pUMln0jzvd4aK4Q$JNRBzwAo0ek5qKn50cFzzvE9RXV88h1wJn5KGiHrD0YKtZaR/nCb2CJPOsKaPK0hjf.9yHxzQGZziziccp6Yng' # The digest of 'insecure_secret'.
public: false public: false
authorization_policy: two_factor authorization_policy: two_factor
redirect_uris: redirect_uris:

View File

@ -22,14 +22,7 @@ community: true
## Before You Begin ## Before You Begin
### Common Notes {{% oidc-common %}}
1. You are *__required__* to utilize a unique client id for every client.
2. The client id on this page is merely an example and you can theoretically use any alphanumeric string.
3. You *__should not__* use the client secret in this example, We *__strongly recommend__* reading the
[Generating Client Secrets] guide instead.
[Generating Client Secrets]: ../specific-information.md#generating-client-secrets
### Assumptions ### Assumptions
@ -38,7 +31,7 @@ This example makes the following assumptions:
* __Application Root URL:__ `https://vault.example.com` * __Application Root URL:__ `https://vault.example.com`
* __Authelia Root URL:__ `https://auth.example.com` * __Authelia Root URL:__ `https://auth.example.com`
* __Client ID:__ `vault` * __Client ID:__ `vault`
* __Client Secret:__ `vault_client_secret` * __Client Secret:__ `insecure_secret`
## Configuration ## Configuration
@ -56,7 +49,7 @@ which will operate with the above example:
```yaml ```yaml
- id: vault - id: vault
description: HashiCorp Vault description: HashiCorp Vault
secret: '$plaintext$vault_client_secret' secret: '$pbkdf2-sha512$310000$c8p78n7pUMln0jzvd4aK4Q$JNRBzwAo0ek5qKn50cFzzvE9RXV88h1wJn5KGiHrD0YKtZaR/nCb2CJPOsKaPK0hjf.9yHxzQGZziziccp6Yng' # The digest of 'insecure_secret'.
public: false public: false
authorization_policy: two_factor authorization_policy: two_factor
redirect_uris: redirect_uris:

View File

@ -166,16 +166,16 @@ These endpoints implement OpenID Connect elements.
[OpenID Connect 1.0]: https://openid.net/connect/ [OpenID Connect 1.0]: https://openid.net/connect/
[OpenID Connect Discovery]: https://openid.net/specs/openid-connect-discovery-1_0.html [OpenID Connect Discovery]: https://openid.net/specs/openid-connect-discovery-1_0.html
[OAuth 2.0 Authorization Server Metadata]: https://www.rfc-editor.org/rfc/rfc8414.html [OAuth 2.0 Authorization Server Metadata]: https://datatracker.ietf.org/doc/html/rfc8414
[JSON Web Key Sets]: https://www.rfc-editor.org/rfc/rfc7517.html#section-5 [JSON Web Key Sets]: https://datatracker.ietf.org/doc/html/rfc7517#section-5
[Authorization]: https://openid.net/specs/openid-connect-core-1_0.html#AuthorizationEndpoint [Authorization]: https://openid.net/specs/openid-connect-core-1_0.html#AuthorizationEndpoint
[Token]: https://openid.net/specs/openid-connect-core-1_0.html#TokenEndpoint [Token]: https://openid.net/specs/openid-connect-core-1_0.html#TokenEndpoint
[UserInfo]: https://openid.net/specs/openid-connect-core-1_0.html#UserInfo [UserInfo]: https://openid.net/specs/openid-connect-core-1_0.html#UserInfo
[Introspection]: https://www.rfc-editor.org/rfc/rfc7662.html [Introspection]: https://datatracker.ietf.org/doc/html/rfc7662
[Revocation]: https://www.rfc-editor.org/rfc/rfc7009.html [Revocation]: https://datatracker.ietf.org/doc/html/rfc7009
[RFC8176]: https://www.rfc-editor.org/rfc/rfc8176.html [RFC8176]: https://datatracker.ietf.org/doc/html/rfc8176
[RFC4122]: https://www.rfc-editor.org/rfc/rfc4122.html [RFC4122]: https://datatracker.ietf.org/doc/html/rfc4122
[Subject Identifier Types]: https://openid.net/specs/openid-connect-core-1_0.html#SubjectIDTypes [Subject Identifier Types]: https://openid.net/specs/openid-connect-core-1_0.html#SubjectIDTypes

View File

@ -22,14 +22,7 @@ community: true
## Before You Begin ## Before You Begin
### Common Notes {{% oidc-common %}}
1. You are *__required__* to utilize a unique client id for every client.
2. The client id on this page is merely an example and you can theoretically use any alphanumeric string.
3. You *__should not__* use the client secret in this example, We *__strongly recommend__* reading the
[Generating Client Secrets] guide instead.
[Generating Client Secrets]: ../specific-information.md#generating-client-secrets
### Assumptions ### Assumptions
@ -38,7 +31,7 @@ This example makes the following assumptions:
* __Application Root URL:__ `https://komga.example.com` * __Application Root URL:__ `https://komga.example.com`
* __Authelia Root URL:__ `https://auth.example.com` * __Authelia Root URL:__ `https://auth.example.com`
* __Client ID:__ `komga` * __Client ID:__ `komga`
* __Client Secret:__ `komga_client_secret` * __Client Secret:__ `insecure_secret`
## Configuration ## Configuration
@ -58,7 +51,7 @@ spring:
registration: registration:
authelia: authelia:
client-id: `komga` client-id: `komga`
client-secret: `komga_client_secret` client-secret: `insecure_secret`
client-name: Authelia client-name: Authelia
scope: openid,profile,email scope: openid,profile,email
authorization-grant-type: authorization_code authorization-grant-type: authorization_code
@ -78,7 +71,7 @@ which will operate with the above example:
```yaml ```yaml
- id: komga - id: komga
description: Komga description: Komga
secret: '$plaintext$komga_client_secret' secret: '$pbkdf2-sha512$310000$c8p78n7pUMln0jzvd4aK4Q$JNRBzwAo0ek5qKn50cFzzvE9RXV88h1wJn5KGiHrD0YKtZaR/nCb2CJPOsKaPK0hjf.9yHxzQGZziziccp6Yng' # The digest of 'insecure_secret'.
public: false public: false
authorization_policy: two_factor authorization_policy: two_factor
redirect_uris: redirect_uris:

View File

@ -22,14 +22,7 @@ community: true
## Before You Begin ## Before You Begin
### Common Notes {{% oidc-common %}}
1. You are *__required__* to utilize a unique client id for every client.
2. The client id on this page is merely an example and you can theoretically use any alphanumeric string.
3. You *__should not__* use the client secret in this example, We *__strongly recommend__* reading the
[Generating Client Secrets] guide instead.
[Generating Client Secrets]: ../specific-information.md#generating-client-secrets
### Assumptions ### Assumptions
@ -38,7 +31,7 @@ This example makes the following assumptions:
* __Application Root URL:__ `https://nextcloud.example.com` * __Application Root URL:__ `https://nextcloud.example.com`
* __Authelia Root URL:__ `https://auth.example.com` * __Authelia Root URL:__ `https://auth.example.com`
* __Client ID:__ `nextcloud` * __Client ID:__ `nextcloud`
* __Client Secret:__ `nextcloud_client_secret` * __Client Secret:__ `insecure_secret`
## Configuration ## Configuration
@ -55,7 +48,7 @@ $CONFIG = array (
'lost_password_link' => 'disabled', 'lost_password_link' => 'disabled',
'oidc_login_provider_url' => 'https://auth.example.com', 'oidc_login_provider_url' => 'https://auth.example.com',
'oidc_login_client_id' => 'nextcloud', 'oidc_login_client_id' => 'nextcloud',
'oidc_login_client_secret' => 'nextcloud_client_secret', 'oidc_login_client_secret' => 'insecure_secret',
'oidc_login_auto_redirect' => false, 'oidc_login_auto_redirect' => false,
'oidc_login_end_session_redirect' => false, 'oidc_login_end_session_redirect' => false,
'oidc_login_button_text' => 'Log in with Authelia', 'oidc_login_button_text' => 'Log in with Authelia',
@ -94,7 +87,7 @@ which will operate with the above example:
```yaml ```yaml
- id: nextcloud - id: nextcloud
description: NextCloud description: NextCloud
secret: '$plaintext$nextcloud_client_secret' secret: '$pbkdf2-sha512$310000$c8p78n7pUMln0jzvd4aK4Q$JNRBzwAo0ek5qKn50cFzzvE9RXV88h1wJn5KGiHrD0YKtZaR/nCb2CJPOsKaPK0hjf.9yHxzQGZziziccp6Yng' # The digest of 'insecure_secret'.
public: false public: false
authorization_policy: two_factor authorization_policy: two_factor
redirect_uris: redirect_uris:

View File

@ -22,14 +22,7 @@ community: true
## Before You Begin ## Before You Begin
### Common Notes {{% oidc-common %}}
1. You are *__required__* to utilize a unique client id for every client.
2. The client id on this page is merely an example and you can theoretically use any alphanumeric string.
3. You *__should not__* use the client secret in this example, We *__strongly recommend__* reading the
[Generating Client Secrets] guide instead.
[Generating Client Secrets]: ../specific-information.md#generating-client-secrets
### Assumptions ### Assumptions
@ -38,7 +31,7 @@ This example makes the following assumptions:
* __Application Root URL:__ `https://outline.example.com` * __Application Root URL:__ `https://outline.example.com`
* __Authelia Root URL:__ `https://auth.example.com` * __Authelia Root URL:__ `https://auth.example.com`
* __Client ID:__ `outline` * __Client ID:__ `outline`
* __Client Secret:__ `outline_client_secret` * __Client Secret:__ `insecure_secret`
*__Important Note:__ At the time of this writing [Outline] requires the `offline_access` scope by default. Failure to include this scope will result *__Important Note:__ At the time of this writing [Outline] requires the `offline_access` scope by default. Failure to include this scope will result
in an error as [Outline] will attempt to use a refresh token that is never issued.* in an error as [Outline] will attempt to use a refresh token that is never issued.*
@ -55,7 +48,7 @@ URL=https://outline.example.com
FORCE_HTTPS=true FORCE_HTTPS=true
OIDC_CLIENT_ID=outline OIDC_CLIENT_ID=outline
OIDC_CLIENT_SECRET=outline_client_secret OIDC_CLIENT_SECRET=insecure_secret
OIDC_AUTH_URI=https://auth.example.com/api/oidc/authorization OIDC_AUTH_URI=https://auth.example.com/api/oidc/authorization
OIDC_TOKEN_URI=https://auth.example.com/api/oidc/token OIDC_TOKEN_URI=https://auth.example.com/api/oidc/token
OIDC_USERINFO_URI=https://auth.example.com/api/oidc/userinfo OIDC_USERINFO_URI=https://auth.example.com/api/oidc/userinfo
@ -73,7 +66,7 @@ which will operate with the above example:
```yaml ```yaml
- id: outline - id: outline
description: Outline description: Outline
secret: '$plaintext$outline_client_secret' secret: '$pbkdf2-sha512$310000$c8p78n7pUMln0jzvd4aK4Q$JNRBzwAo0ek5qKn50cFzzvE9RXV88h1wJn5KGiHrD0YKtZaR/nCb2CJPOsKaPK0hjf.9yHxzQGZziziccp6Yng' # The digest of 'insecure_secret'.
public: false public: false
authorization_policy: two_factor authorization_policy: two_factor
redirect_uris: redirect_uris:

View File

@ -24,14 +24,7 @@ aliases:
## Before You Begin ## Before You Begin
### Common Notes {{% oidc-common %}}
1. You are *__required__* to utilize a unique client id for every client.
2. The client id on this page is merely an example and you can theoretically use any alphanumeric string.
3. You *__should not__* use the client secret in this example, We *__strongly recommend__* reading the
[Generating Client Secrets] guide instead.
[Generating Client Secrets]: ../specific-information.md#generating-client-secrets
### Assumptions ### Assumptions
@ -40,7 +33,7 @@ This example makes the following assumptions:
* __Application Root URL:__ `https://portainer.example.com` * __Application Root URL:__ `https://portainer.example.com`
* __Authelia Root URL:__ `https://auth.example.com` * __Authelia Root URL:__ `https://auth.example.com`
* __Client ID:__ `portainer` * __Client ID:__ `portainer`
* __Client Secret:__ `portainer_client_secret` * __Client Secret:__ `insecure_secret`
## Configuration ## Configuration
@ -55,7 +48,7 @@ To configure [Portainer] to utilize Authelia as an [OpenID Connect 1.0] Provider
2. Provider: Custom 2. Provider: Custom
3. Enable *Automatic User Provision* if you want users to automatically be created in [Portainer]. 3. Enable *Automatic User Provision* if you want users to automatically be created in [Portainer].
4. Client ID: `portainer` 4. Client ID: `portainer`
5. Client Secret: `portainer_client_secret` 5. Client Secret: `insecure_secret`
6. Authorization URL: `https://auth.example.com/api/oidc/authorization` 6. Authorization URL: `https://auth.example.com/api/oidc/authorization`
7. Access Token URL: `https://auth.example.com/api/oidc/token` 7. Access Token URL: `https://auth.example.com/api/oidc/token`
8. Resource URL: `https://auth.example.com/api/oidc/userinfo` 8. Resource URL: `https://auth.example.com/api/oidc/userinfo`
@ -74,7 +67,7 @@ which will operate with the above example:
```yaml ```yaml
- id: portainer - id: portainer
description: Portainer description: Portainer
secret: '$plaintext$portainer_client_secret' secret: '$pbkdf2-sha512$310000$c8p78n7pUMln0jzvd4aK4Q$JNRBzwAo0ek5qKn50cFzzvE9RXV88h1wJn5KGiHrD0YKtZaR/nCb2CJPOsKaPK0hjf.9yHxzQGZziziccp6Yng' # The digest of 'insecure_secret'.
public: false public: false
authorization_policy: two_factor authorization_policy: two_factor
redirect_uris: redirect_uris:

View File

@ -43,7 +43,7 @@ This example makes the following assumptions:
* __Application Root URL:__ `https://proxmox.example.com` * __Application Root URL:__ `https://proxmox.example.com`
* __Authelia Root URL:__ `https://auth.example.com` * __Authelia Root URL:__ `https://auth.example.com`
* __Client ID:__ `proxmox` * __Client ID:__ `proxmox`
* __Client Secret:__ `proxmox_client_secret` * __Client Secret:__ `insecure_secret`
* __Realm__ `authelia` * __Realm__ `authelia`
## Configuration ## Configuration
@ -60,7 +60,7 @@ To configure [Proxmox] to utilize Authelia as an [OpenID Connect 1.0] Provider:
1. Issuer URL: `https://auth.example.com` 1. Issuer URL: `https://auth.example.com`
2. Realm: `authelia` 2. Realm: `authelia`
3. Client ID: `proxmox` 3. Client ID: `proxmox`
4. Client Key: `proxmox_client_secret` 4. Client Key: `insecure_secret`
5. Username Claim `preferred_username` 5. Username Claim `preferred_username`
6. Scopes: `openid profile email` 6. Scopes: `openid profile email`
7. Enable *Autocreate Users* if you want users to automatically be created in [Proxmox]. 7. Enable *Autocreate Users* if you want users to automatically be created in [Proxmox].
@ -76,7 +76,7 @@ which will operate with the above example:
```yaml ```yaml
- id: proxmox - id: proxmox
description: Proxmox description: Proxmox
secret: '$plaintext$proxmox_client_secret' secret: '$pbkdf2-sha512$310000$c8p78n7pUMln0jzvd4aK4Q$JNRBzwAo0ek5qKn50cFzzvE9RXV88h1wJn5KGiHrD0YKtZaR/nCb2CJPOsKaPK0hjf.9yHxzQGZziziccp6Yng' # The digest of 'insecure_secret'.
public: false public: false
authorization_policy: two_factor authorization_policy: two_factor
redirect_uris: redirect_uris:

View File

@ -22,14 +22,7 @@ community: true
## Before You Begin ## Before You Begin
### Common Notes {{% oidc-common %}}
1. You are *__required__* to utilize a unique client id for every client.
2. The client id on this page is merely an example and you can theoretically use any alphanumeric string.
3. You *__should not__* use the client secret in this example, We *__strongly recommend__* reading the
[Generating Client Secrets] guide instead.
[Generating Client Secrets]: ../specific-information.md#generating-client-secrets
### Assumptions ### Assumptions
@ -38,7 +31,7 @@ This example makes the following assumptions:
* __Application Root URL:__ `https://seafile.example.com` * __Application Root URL:__ `https://seafile.example.com`
* __Authelia Root URL:__ `https://auth.example.com` * __Authelia Root URL:__ `https://auth.example.com`
* __Client ID:__ `seafile` * __Client ID:__ `seafile`
* __Client Secret:__ `seafile_client_secret` * __Client Secret:__ `insecure_secret`
## Configuration ## Configuration
@ -55,7 +48,7 @@ To configure [Seafile] to utilize Authelia as an [OpenID Connect 1.0] Provider:
ENABLE_OAUTH = True ENABLE_OAUTH = True
OAUTH_ENABLE_INSECURE_TRANSPORT = False OAUTH_ENABLE_INSECURE_TRANSPORT = False
OAUTH_CLIENT_ID = "seafile" OAUTH_CLIENT_ID = "seafile"
OAUTH_CLIENT_SECRET = "seafile_client_secret" OAUTH_CLIENT_SECRET = "insecure_secret"
OAUTH_REDIRECT_URL = 'https://seafile.example.com/oauth/callback/' OAUTH_REDIRECT_URL = 'https://seafile.example.com/oauth/callback/'
OAUTH_PROVIDER_DOMAIN = 'auth.example.com' OAUTH_PROVIDER_DOMAIN = 'auth.example.com'
OAUTH_AUTHORIZATION_URL = 'https://auth.example.com/api/oidc/authorization' OAUTH_AUTHORIZATION_URL = 'https://auth.example.com/api/oidc/authorization'
@ -82,7 +75,7 @@ which will operate with the above example:
```yaml ```yaml
- id: seafile - id: seafile
description: Seafile description: Seafile
secret: '$plaintext$seafile_client_secret' secret: '$pbkdf2-sha512$310000$c8p78n7pUMln0jzvd4aK4Q$JNRBzwAo0ek5qKn50cFzzvE9RXV88h1wJn5KGiHrD0YKtZaR/nCb2CJPOsKaPK0hjf.9yHxzQGZziziccp6Yng' # The digest of 'insecure_secret'.
public: false public: false
authorization_policy: two_factor authorization_policy: two_factor
redirect_uris: redirect_uris:

View File

@ -34,6 +34,22 @@ using PBKDF2 which can be stored in the Authelia configuration.
### Plaintext ### Plaintext
Authelia supports storing the plaintext secret in the configuration. This may be discontinued in the future. Plaintext Authelia *technically* supports storing the plaintext secret in the configuration. This will likely be completely
is either denoted by the `$plaintext$` prefix where everything after the prefix is the secret. In addition if the secret unavailable in the future as it was a mistake to implement it like this in the first place. While some other OpenID
does not start with the `$` character it's considered as a plaintext secret for the time being but is deprecated. Connect 1.0 providers operate in this way, it's more often than not that they operating in this way in error. The
current *technical support* for this is only to prevent massive upheaval to users and give them time to migrate.
As per [RFC6819 Section 5.1.4.1.3](https://datatracker.ietf.org/doc/html/rfc6819#section-5.1.4.1.3) the secret should
only be stored by the authorization server as hashes / digests unless there is a very specific specification or protocol
that is implemented by the authorization server which requires access to the secret in the clear to operate properly in
which case the secret should be encrypted and not be stored in plaintext. The most likely long term outcome is that the
client configurations will be stored in the database with the secret both salted and peppered.
Authelia currently does not implement any of the specifications or protocols which require secrets being accessible in
the clear and currently has no plans to implement any of these. As such it's *__strongly discouraged and heavily
deprecated__* and we instead recommended that users remove this from their configuration entirely and use the
[Generating Client Secrets](#generating-client-secrets) guide.
Plaintext is either denoted by the `$plaintext$` prefix where everything after the prefix is the secret. In addition if
the secret does not start with the `$` character it's considered as a plaintext secret for the time being but is
deprecated as is the `$plaintext$` prefix.

View File

@ -22,14 +22,7 @@ community: true
## Before You Begin ## Before You Begin
### Common Notes {{% oidc-common %}}
1. You are *__required__* to utilize a unique client id for every client.
2. The client id on this page is merely an example and you can theoretically use any alphanumeric string.
3. You *__should not__* use the client secret in this example, We *__strongly recommend__* reading the
[Generating Client Secrets] guide instead.
[Generating Client Secrets]: ../specific-information.md#generating-client-secrets
### Assumptions ### Assumptions
@ -38,7 +31,7 @@ This example makes the following assumptions:
* __Application Root URL:__ `https://matrix.example.com/` * __Application Root URL:__ `https://matrix.example.com/`
* __Authelia Root URL:__ `https://auth.example.com` * __Authelia Root URL:__ `https://auth.example.com`
* __Client ID:__ `synapse` * __Client ID:__ `synapse`
* __Client Secret:__ `synapse_client_secret` * __Client Secret:__ `insecure_secret`
## Configuration ## Configuration
@ -56,7 +49,7 @@ oidc_providers:
discover: true discover: true
issuer: "https://auth.example.com" issuer: "https://auth.example.com"
client_id: "synapse" client_id: "synapse"
client_secret: "synapse_client_secret" client_secret: "insecure_secret"
scopes: ["openid", "profile", "email"] scopes: ["openid", "profile", "email"]
allow_existing_users: true allow_existing_users: true
user_mapping_provider: user_mapping_provider:
@ -76,7 +69,7 @@ which will operate with the above example:
```yaml ```yaml
- id: synapse - id: synapse
description: Synapse description: Synapse
secret: '$plaintext$synapse_client_secret' secret: '$pbkdf2-sha512$310000$c8p78n7pUMln0jzvd4aK4Q$JNRBzwAo0ek5qKn50cFzzvE9RXV88h1wJn5KGiHrD0YKtZaR/nCb2CJPOsKaPK0hjf.9yHxzQGZziziccp6Yng' # The digest of 'insecure_secret'.
public: false public: false
authorization_policy: two_factor authorization_policy: two_factor
redirect_uris: redirect_uris:

View File

@ -22,14 +22,7 @@ community: true
## Before You Begin ## Before You Begin
### Common Notes {{% oidc-common %}}
1. You are *__required__* to utilize a unique client id for every client.
2. The client id on this page is merely an example and you can theoretically use any alphanumeric string.
3. You *__should not__* use the client secret in this example, We *__strongly recommend__* reading the
[Generating Client Secrets] guide instead.
[Generating Client Secrets]: ../specific-information.md#generating-client-secrets
### Specific Notes ### Specific Notes
@ -43,7 +36,7 @@ This example makes the following assumptions:
* __Application Root URL:__ `https://dsm.example.com/` * __Application Root URL:__ `https://dsm.example.com/`
* __Authelia Root URL:__ `https://auth.example.com` * __Authelia Root URL:__ `https://auth.example.com`
* __Client ID:__ `synology-dsm` * __Client ID:__ `synology-dsm`
* __Client Secret:__ `synology-dsm_client_secret` * __Client Secret:__ `insecure_secret`
## Configuration ## Configuration
@ -61,7 +54,7 @@ To configure [Synology DSM] to utilize Authelia as an [OpenID Connect 1.0] Provi
* Name: `Authelia` * Name: `Authelia`
* Well Known URL: `https://auth.example.com/.well-known/openid-configuration` * Well Known URL: `https://auth.example.com/.well-known/openid-configuration`
* Application ID: `synology-dsm` * Application ID: `synology-dsm`
* Application Key: `synology-dsm_client_secret` * Application Key: `insecure_secret`
* Redirect URL: `https://dsm.example.com` * Redirect URL: `https://dsm.example.com`
* Authorisation Scope: `openid profile groups email` * Authorisation Scope: `openid profile groups email`
* Username Claim: `preferred_username` * Username Claim: `preferred_username`
@ -78,7 +71,7 @@ which will operate with the above example:
```yaml ```yaml
- id: synology-dsm - id: synology-dsm
description: Synology DSM description: Synology DSM
secret: '$plaintext$synology-dsm_client_secret' secret: '$pbkdf2-sha512$310000$c8p78n7pUMln0jzvd4aK4Q$JNRBzwAo0ek5qKn50cFzzvE9RXV88h1wJn5KGiHrD0YKtZaR/nCb2CJPOsKaPK0hjf.9yHxzQGZziziccp6Yng' # The digest of 'insecure_secret'.
public: false public: false
authorization_policy: two_factor authorization_policy: two_factor
redirect_uris: redirect_uris:

View File

@ -102,7 +102,7 @@ nextcloud.example.com {
## The following commented line is for configuring the Authelia URL in the proxy. We strongly suggest ## The following commented line is for configuring the Authelia URL in the proxy. We strongly suggest
## this is configured in the Session Cookies section of the Authelia configuration. ## this is configured in the Session Cookies section of the Authelia configuration.
# uri /api/authz/forward-auth?authelia_url=https://auth.example.com/ # uri /api/authz/forward-auth?authelia_url=https://auth.example.com/
copy_headers Remote-User Remote-Groups Remote-Name Remote-Email copy_headers Authorization Proxy-Authorization Remote-User Remote-Groups Remote-Email Remote-Name
## This import needs to be included if you're relying on a trusted proxies configuration. ## This import needs to be included if you're relying on a trusted proxies configuration.
import trusted_proxy_list import trusted_proxy_list
@ -141,7 +141,7 @@ example.com {
handle @nextcloud { handle @nextcloud {
forward_auth authelia:9091 { forward_auth authelia:9091 {
uri /api/authz/forward-auth?authelia_url=https://example.com/authelia/ uri /api/authz/forward-auth?authelia_url=https://example.com/authelia/
copy_headers Remote-User Remote-Groups Remote-Name Remote-Email copy_headers Authorization Proxy-Authorization Remote-User Remote-Groups Remote-Email Remote-Name
## This import needs to be included if you're relying on a trusted proxies configuration. ## This import needs to be included if you're relying on a trusted proxies configuration.
import trusted_proxy_list import trusted_proxy_list
@ -198,10 +198,12 @@ nextcloud.example.com {
## 2. Copy the relevant headers from the auth request and provide them to the backend. ## 2. Copy the relevant headers from the auth request and provide them to the backend.
@good status 2xx @good status 2xx
handle_response @good { handle_response @good {
request_header Authorization {http.reverse_proxy.header.Authorization}
request_header Proxy-Authorization {http.reverse_proxy.header.Proxy-Authorization}
request_header Remote-User {http.reverse_proxy.header.Remote-User} request_header Remote-User {http.reverse_proxy.header.Remote-User}
request_header Remote-Groups {http.reverse_proxy.header.Remote-Groups} request_header Remote-Groups {http.reverse_proxy.header.Remote-Groups}
request_header Remote-Name {http.reverse_proxy.header.Remote-Name}
request_header Remote-Email {http.reverse_proxy.header.Remote-Email} request_header Remote-Email {http.reverse_proxy.header.Remote-Email}
request_header Remote-Name {http.reverse_proxy.header.Remote-Name}
} }
} }

View File

@ -177,9 +177,10 @@ static_resources:
authorization_request: authorization_request:
allowed_headers: allowed_headers:
patterns: patterns:
- exact: authorization
- exact: proxy-authorization
- exact: accept - exact: accept
- exact: cookie - exact: cookie
- exact: proxy-authorization
headers_to_add: headers_to_add:
- key: X-Forwarded-Proto - key: X-Forwarded-Proto
value: '%REQ(:SCHEME)%' value: '%REQ(:SCHEME)%'

View File

@ -218,29 +218,53 @@ backend be_authelia
server authelia authelia:9091 server authelia authelia:9091
backend be_nextcloud backend be_nextcloud
# Pass Remote-User, Remote-Name, Remote-Email and Remote-Groups headers ## Pass the special authorization response headers to the protected application.
acl authorization_exist var(req.auth_response_header.authorization) -m found
acl proxy_authorization_exist var(req.auth_response_header.proxy_authorization) -m found
http-request set-header Authorization %[var(req.auth_response_header.authorization)] if authorization_exist
http-request set-header Proxy-Authorization %[var(req.auth_response_header.proxy_authorization)] if proxy_authorization_exist
## Pass the special metadata response headers to the protected application.
acl remote_user_exist var(req.auth_response_header.remote_user) -m found acl remote_user_exist var(req.auth_response_header.remote_user) -m found
acl remote_groups_exist var(req.auth_response_header.remote_groups) -m found acl remote_groups_exist var(req.auth_response_header.remote_groups) -m found
acl remote_name_exist var(req.auth_response_header.remote_name) -m found acl remote_name_exist var(req.auth_response_header.remote_name) -m found
acl remote_email_exist var(req.auth_response_header.remote_email) -m found acl remote_email_exist var(req.auth_response_header.remote_email) -m found
http-request set-header Remote-User %[var(req.auth_response_header.remote_user)] if remote_user_exist http-request set-header Remote-User %[var(req.auth_response_header.remote_user)] if remote_user_exist
http-request set-header Remote-Groups %[var(req.auth_response_header.remote_groups)] if remote_groups_exist http-request set-header Remote-Groups %[var(req.auth_response_header.remote_groups)] if remote_groups_exist
http-request set-header Remote-Name %[var(req.auth_response_header.remote_name)] if remote_name_exist http-request set-header Remote-Name %[var(req.auth_response_header.remote_name)] if remote_name_exist
http-request set-header Remote-Email %[var(req.auth_response_header.remote_email)] if remote_email_exist http-request set-header Remote-Email %[var(req.auth_response_header.remote_email)] if remote_email_exist
## Pass the Set-Cookie response headers to the user.
acl set_cookie_exist var(req.auth_response_header.set_cookie) -m found
http-response set-header Set-Cookie %[var(req.auth_response_header.set_cookie)] if set_cookie_exist
server nextcloud nextcloud:443 ssl verify none server nextcloud nextcloud:443 ssl verify none
backend be_heimdall backend be_heimdall
# Pass Remote-User, Remote-Name, Remote-Email and Remote-Groups headers ## Pass the special authorization response headers to the protected application.
acl authorization_exist var(req.auth_response_header.authorization) -m found
acl proxy_authorization_exist var(req.auth_response_header.proxy_authorization) -m found
http-request set-header Authorization %[var(req.auth_response_header.authorization)] if authorization_exist
http-request set-header Proxy-Authorization %[var(req.auth_response_header.proxy_authorization)] if proxy_authorization_exist
## Pass the special metadata response headers to the protected application.
acl remote_user_exist var(req.auth_response_header.remote_user) -m found acl remote_user_exist var(req.auth_response_header.remote_user) -m found
acl remote_groups_exist var(req.auth_response_header.remote_groups) -m found acl remote_groups_exist var(req.auth_response_header.remote_groups) -m found
acl remote_name_exist var(req.auth_response_header.remote_name) -m found acl remote_name_exist var(req.auth_response_header.remote_name) -m found
acl remote_email_exist var(req.auth_response_header.remote_email) -m found acl remote_email_exist var(req.auth_response_header.remote_email) -m found
http-request set-header Remote-User %[var(req.auth_response_header.remote_user)] if remote_user_exist http-request set-header Remote-User %[var(req.auth_response_header.remote_user)] if remote_user_exist
http-request set-header Remote-Groups %[var(req.auth_response_header.remote_groups)] if remote_groups_exist http-request set-header Remote-Groups %[var(req.auth_response_header.remote_groups)] if remote_groups_exist
http-request set-header Remote-Name %[var(req.auth_response_header.remote_name)] if remote_name_exist http-request set-header Remote-Name %[var(req.auth_response_header.remote_name)] if remote_name_exist
http-request set-header Remote-Email %[var(req.auth_response_header.remote_email)] if remote_email_exist http-request set-header Remote-Email %[var(req.auth_response_header.remote_email)] if remote_email_exist
## Pass the Set-Cookie response headers to the user.
acl set_cookie_exist var(req.auth_response_header.set_cookie) -m found
http-response set-header Set-Cookie %[var(req.auth_response_header.set_cookie)] if set_cookie_exist
server heimdall heimdall:443 ssl verify none server heimdall heimdall:443 ssl verify none
``` ```
@ -325,29 +349,53 @@ listen authelia_proxy
server authelia authelia:9091 ssl verify none server authelia authelia:9091 ssl verify none
backend be_nextcloud backend be_nextcloud
# Pass Remote-User, Remote-Name, Remote-Email and Remote-Groups headers ## Pass the special authorization response headers to the protected application.
acl authorization_exist var(req.auth_response_header.authorization) -m found
acl proxy_authorization_exist var(req.auth_response_header.proxy_authorization) -m found
http-request set-header Authorization %[var(req.auth_response_header.authorization)] if authorization_exist
http-request set-header Proxy-Authorization %[var(req.auth_response_header.proxy_authorization)] if proxy_authorization_exist
## Pass the special metadata response headers to the protected application.
acl remote_user_exist var(req.auth_response_header.remote_user) -m found acl remote_user_exist var(req.auth_response_header.remote_user) -m found
acl remote_groups_exist var(req.auth_response_header.remote_groups) -m found acl remote_groups_exist var(req.auth_response_header.remote_groups) -m found
acl remote_name_exist var(req.auth_response_header.remote_name) -m found acl remote_name_exist var(req.auth_response_header.remote_name) -m found
acl remote_email_exist var(req.auth_response_header.remote_email) -m found acl remote_email_exist var(req.auth_response_header.remote_email) -m found
http-request set-header Remote-User %[var(req.auth_response_header.remote_user)] if remote_user_exist http-request set-header Remote-User %[var(req.auth_response_header.remote_user)] if remote_user_exist
http-request set-header Remote-Groups %[var(req.auth_response_header.remote_groups)] if remote_groups_exist http-request set-header Remote-Groups %[var(req.auth_response_header.remote_groups)] if remote_groups_exist
http-request set-header Remote-Name %[var(req.auth_response_header.remote_name)] if remote_name_exist http-request set-header Remote-Name %[var(req.auth_response_header.remote_name)] if remote_name_exist
http-request set-header Remote-Email %[var(req.auth_response_header.remote_email)] if remote_email_exist http-request set-header Remote-Email %[var(req.auth_response_header.remote_email)] if remote_email_exist
## Pass the Set-Cookie response headers to the user.
acl set_cookie_exist var(req.auth_response_header.set_cookie) -m found
http-response set-header Set-Cookie %[var(req.auth_response_header.set_cookie)] if set_cookie_exist
server nextcloud nextcloud:443 ssl verify none server nextcloud nextcloud:443 ssl verify none
backend be_heimdall backend be_heimdall
# Pass Remote-User, Remote-Name, Remote-Email and Remote-Groups headers ## Pass the special authorization response headers to the protected application.
acl authorization_exist var(req.auth_response_header.authorization) -m found
acl proxy_authorization_exist var(req.auth_response_header.proxy_authorization) -m found
http-request set-header Authorization %[var(req.auth_response_header.authorization)] if authorization_exist
http-request set-header Proxy-Authorization %[var(req.auth_response_header.proxy_authorization)] if proxy_authorization_exist
## Pass the special metadata response headers to the protected application.
acl remote_user_exist var(req.auth_response_header.remote_user) -m found acl remote_user_exist var(req.auth_response_header.remote_user) -m found
acl remote_groups_exist var(req.auth_response_header.remote_groups) -m found acl remote_groups_exist var(req.auth_response_header.remote_groups) -m found
acl remote_name_exist var(req.auth_response_header.remote_name) -m found acl remote_name_exist var(req.auth_response_header.remote_name) -m found
acl remote_email_exist var(req.auth_response_header.remote_email) -m found acl remote_email_exist var(req.auth_response_header.remote_email) -m found
http-request set-header Remote-User %[var(req.auth_response_header.remote_user)] if remote_user_exist http-request set-header Remote-User %[var(req.auth_response_header.remote_user)] if remote_user_exist
http-request set-header Remote-Groups %[var(req.auth_response_header.remote_groups)] if remote_groups_exist http-request set-header Remote-Groups %[var(req.auth_response_header.remote_groups)] if remote_groups_exist
http-request set-header Remote-Name %[var(req.auth_response_header.remote_name)] if remote_name_exist http-request set-header Remote-Name %[var(req.auth_response_header.remote_name)] if remote_name_exist
http-request set-header Remote-Email %[var(req.auth_response_header.remote_email)] if remote_email_exist http-request set-header Remote-Email %[var(req.auth_response_header.remote_email)] if remote_email_exist
## Pass the Set-Cookie response headers to the user.
acl set_cookie_exist var(req.auth_response_header.set_cookie) -m found
http-response set-header Set-Cookie %[var(req.auth_response_header.set_cookie)] if set_cookie_exist
server heimdall heimdall:443 ssl verify none server heimdall heimdall:443 ssl verify none
``` ```

View File

@ -433,17 +433,29 @@ set_escape_uri $target_url $scheme://$http_host$request_uri;
## Uncomment this line if you're using NGINX without the http_set_misc module. ## Uncomment this line if you're using NGINX without the http_set_misc module.
# set $target_url $scheme://$http_host$request_uri; # set $target_url $scheme://$http_host$request_uri;
## Save the upstream response headers from Authelia to variables. ## Save the upstream authorization response headers from Authelia to variables.
auth_request_set $authorization $upstream_http_authorization;
auth_request_set $proxy_authorization $upstream_http_proxy_authorization;
## Inject the authorization response headers from the variables into the request made to the backend.
proxy_set_header Authorization $authorization;
proxy_set_header Proxy-Authorization $proxy_authorization;
## Save the upstream metadata response headers from Authelia to variables.
auth_request_set $user $upstream_http_remote_user; auth_request_set $user $upstream_http_remote_user;
auth_request_set $groups $upstream_http_remote_groups; auth_request_set $groups $upstream_http_remote_groups;
auth_request_set $name $upstream_http_remote_name; auth_request_set $name $upstream_http_remote_name;
auth_request_set $email $upstream_http_remote_email; auth_request_set $email $upstream_http_remote_email;
## Inject the response headers from the variables into the request made to the backend. ## Inject the metadata response headers from the variables into the request made to the backend.
proxy_set_header Remote-User $user; proxy_set_header Remote-User $user;
proxy_set_header Remote-Groups $groups; proxy_set_header Remote-Groups $groups;
proxy_set_header Remote-Name $name;
proxy_set_header Remote-Email $email; proxy_set_header Remote-Email $email;
proxy_set_header Remote-Name $name;
## Include the Set-Cookie header if present.
auth_request_set $cookie $upstream_http_set_cookie;
add_header Set-Cookie $cookie;
## If the subreqest returns 200 pass to the backend, if the subrequest returns 401 redirect to the portal. ## If the subreqest returns 200 pass to the backend, if the subrequest returns 401 redirect to the portal.
error_page 401 =302 https://auth.example.com/?rd=$target_url; error_page 401 =302 https://auth.example.com/?rd=$target_url;

View File

@ -157,7 +157,7 @@ services:
## configured in the Session Cookies section of the Authelia configuration. ## configured in the Session Cookies section of the Authelia configuration.
# - 'traefik.http.middlewares.authelia.forwardAuth.address=http://authelia:9091/api/authz/forward-auth?authelia_url=https%3A%2F%2Fauth.example.com%2F' # - 'traefik.http.middlewares.authelia.forwardAuth.address=http://authelia:9091/api/authz/forward-auth?authelia_url=https%3A%2F%2Fauth.example.com%2F'
- 'traefik.http.middlewares.authelia.forwardAuth.trustForwardHeader=true' - 'traefik.http.middlewares.authelia.forwardAuth.trustForwardHeader=true'
- 'traefik.http.middlewares.authelia.forwardAuth.authResponseHeaders=Authorization,Proxy-Authorization,Remote-User,Remote-Groups,Remote-Name,Remote-Email' - 'traefik.http.middlewares.authelia.forwardAuth.authResponseHeaders=Authorization,Proxy-Authorization,Remote-User,Remote-Groups,Remote-Email,Remote-Name'
nextcloud: nextcloud:
container_name: nextcloud container_name: nextcloud
image: linuxserver/nextcloud image: linuxserver/nextcloud
@ -503,7 +503,7 @@ This can be avoided a couple different ways:
## configured in the Session Cookies section of the Authelia configuration. ## configured in the Session Cookies section of the Authelia configuration.
# - 'traefik.http.middlewares.authelia.forwardAuth.address=http://authelia:9091/api/authz/forward-auth?authelia_url=https%3A%2F%2Fauth.example.com%2F' # - 'traefik.http.middlewares.authelia.forwardAuth.address=http://authelia:9091/api/authz/forward-auth?authelia_url=https%3A%2F%2Fauth.example.com%2F'
- 'traefik.http.middlewares.authelia.forwardAuth.trustForwardHeader=true' - 'traefik.http.middlewares.authelia.forwardAuth.trustForwardHeader=true'
- 'traefik.http.middlewares.authelia.forwardAuth.authResponseHeaders=Authorization,Proxy-Authorization,Remote-User,Remote-Groups,Remote-Name,Remote-Email' - 'traefik.http.middlewares.authelia.forwardAuth.authResponseHeaders=Authorization,Proxy-Authorization,Remote-User,Remote-Groups,Remote-Email,Remote-Name'
``` ```
## See Also ## See Also

View File

@ -137,7 +137,7 @@ services:
## configured in the Session Cookies section of the Authelia configuration. ## configured in the Session Cookies section of the Authelia configuration.
# - 'traefik.frontend.auth.forward.address=http://authelia:9091/api/authz/forward-auth?authelia_url=https%3A%2F%2Fauth.example.com%2F' # - 'traefik.frontend.auth.forward.address=http://authelia:9091/api/authz/forward-auth?authelia_url=https%3A%2F%2Fauth.example.com%2F'
- 'traefik.frontend.auth.forward.trustForwardHeader=true' - 'traefik.frontend.auth.forward.trustForwardHeader=true'
- 'traefik.frontend.auth.forward.authResponseHeaders=Authorization,Proxy-Authorization,Remote-User,Remote-Groups,Remote-Name,Remote-Email' - 'traefik.frontend.auth.forward.authResponseHeaders=Authorization,Proxy-Authorization,Remote-User,Remote-Groups,Remote-Email,Remote-Name'
expose: expose:
- 443 - 443
restart: unless-stopped restart: unless-stopped
@ -156,7 +156,7 @@ services:
- 'traefik.frontend.rule=Host:heimdall.example.com' - 'traefik.frontend.rule=Host:heimdall.example.com'
- 'traefik.frontend.auth.forward.address=http://authelia:9091/api/authz/forward-auth/basic' - 'traefik.frontend.auth.forward.address=http://authelia:9091/api/authz/forward-auth/basic'
- 'traefik.frontend.auth.forward.trustForwardHeader=true' - 'traefik.frontend.auth.forward.trustForwardHeader=true'
- 'traefik.frontend.auth.forward.authResponseHeaders=Authorization,Proxy-Authorization,Remote-User,Remote-Groups,Remote-Name,Remote-Email' - 'traefik.frontend.auth.forward.authResponseHeaders=Authorization,Proxy-Authorization,Remote-User,Remote-Groups,Remote-Email,Remote-Name'
expose: expose:
- 443 - 443
restart: unless-stopped restart: unless-stopped

View File

@ -216,9 +216,9 @@ to port 587 (_the `submission` port, a common alternative that uses STARTTLS ins
[docs-config-smtp-port]: ../../configuration/notifications/smtp.md#port [docs-config-smtp-port]: ../../configuration/notifications/smtp.md#port
[cleartext]: https://cwe.mitre.org/data/definitions/312.html [cleartext]: https://cwe.mitre.org/data/definitions/312.html
[service-submissions]: https://www.rfc-editor.org/rfc/rfc8314#section-7.3 [service-submissions]: https://datatracker.ietf.org/doc/html/rfc8314#section-7.3
[port-465]: https://www.rfc-editor.org/rfc/rfc8314#section-3.3 [port-465]: https://datatracker.ietf.org/doc/html/rfc8314#section-3.3
[smtp-auth]: https://www.rfc-editor.org/rfc/rfc6409#section-4.3 [smtp-auth]: https://datatracker.ietf.org/doc/html/rfc6409#section-4.3
## Protection against open redirects ## Protection against open redirects

View File

@ -193,14 +193,14 @@ This table suggests the parameters for the [SHA2 Crypt] algorithm:
| Standard CPU | sha512 | 50000 | 16 | | Standard CPU | sha512 | 50000 | 16 |
| High End CPU | sha512 | 150000 | 16 | | High End CPU | sha512 | 150000 | 16 |
[Argon2]: https://www.rfc-editor.org/rfc/rfc9106.html [Argon2]: https://datatracker.ietf.org/doc/html/rfc9106
[Scrypt]: https://en.wikipedia.org/wiki/Scrypt [Scrypt]: https://en.wikipedia.org/wiki/Scrypt
[PBKDF2]: https://www.ietf.org/rfc/rfc2898.html [PBKDF2]: https://datatracker.ietf.org/doc/html/rfc2898
[SHA2 Crypt]: https://www.akkadia.org/drepper/SHA-crypt.txt [SHA2 Crypt]: https://www.akkadia.org/drepper/SHA-crypt.txt
[Bcrypt]: https://en.wikipedia.org/wiki/Bcrypt [Bcrypt]: https://en.wikipedia.org/wiki/Bcrypt
[FIPS-140 compliance]: https://csrc.nist.gov/publications/detail/fips/140/2/final [FIPS-140 compliance]: https://csrc.nist.gov/publications/detail/fips/140/2/final
[RFC9106 Parameter Choice]: https://www.rfc-editor.org/rfc/rfc9106.html#section-4 [RFC9106 Parameter Choice]: https://datatracker.ietf.org/doc/html/rfc9106#section-4
[YAML]: https://yaml.org/ [YAML]: https://yaml.org/
[crypt hash generate]: ../cli/authelia/authelia_crypto_hash_generate.md [crypt hash generate]: ../cli/authelia/authelia_crypto_hash_generate.md
[Password Hashing Competition]: https://en.wikipedia.org/wiki/Password_Hashing_Competition [Password Hashing Competition]: https://en.wikipedia.org/wiki/Password_Hashing_Competition

View File

@ -46,7 +46,7 @@ utilize these overrides should either check for changes to the files in the
The locales directory holds folders of internationalization locales. This directory can be utilized to override these The locales directory holds folders of internationalization locales. This directory can be utilized to override these
locales. They are the names of locales that are returned by the `navigator.langauge` ECMAScript command. These are locales. They are the names of locales that are returned by the `navigator.langauge` ECMAScript command. These are
generally those in the [RFC5646 / BCP47 Format](https://www.rfc-editor.org/rfc/rfc5646.html) specifically the language generally those in the [RFC5646 / BCP47 Format](https://datatracker.ietf.org/doc/html/rfc5646) specifically the language
codes from [Crowdin](https://support.crowdin.com/api/language-codes/). codes from [Crowdin](https://support.crowdin.com/api/language-codes/).
Each directory has JSON files which you can explore the format of in the Each directory has JSON files which you can explore the format of in the

View File

@ -39,11 +39,11 @@ Feature List:
* [User Consent](https://openid.net/specs/openid-connect-core-1_0.html#Consent) * [User Consent](https://openid.net/specs/openid-connect-core-1_0.html#Consent)
* [Authorization Code Flow](https://openid.net/specs/openid-connect-core-1_0.html#CodeFlowSteps) * [Authorization Code Flow](https://openid.net/specs/openid-connect-core-1_0.html#CodeFlowSteps)
* [OpenID Connect Discovery](https://openid.net/specs/openid-connect-discovery-1_0.html) * [OpenID Connect Discovery](https://openid.net/specs/openid-connect-discovery-1_0.html)
* [RS256 Signature Strategy](https://www.rfc-editor.org/rfc/rfc7518.html#section-3.1) * [RS256 Signature Strategy](https://datatracker.ietf.org/doc/html/rfc7518#section-3.1)
* Per Client Scope/Grant Type/Response Type Restriction * Per Client Scope/Grant Type/Response Type Restriction
* Per Client Authorization Policy (1FA/2FA) * Per Client Authorization Policy (1FA/2FA)
* Per Client List of Valid Redirection URI's * Per Client List of Valid Redirection URI's
* [Confidential Client Type](https://www.rfc-editor.org/rfc/rfc6749.html#section-2.1) * [Confidential Client Type](https://datatracker.ietf.org/doc/html/rfc6749#section-2.1)
### Beta 2 ### Beta 2
@ -56,7 +56,7 @@ Feature List:
* Token/Code Lifespan * Token/Code Lifespan
* Client Debug Messages * Client Debug Messages
* Client Audience * Client Audience
* [Public Client Type](https://www.rfc-editor.org/rfc/rfc6749.html#section-2.1) * [Public Client Type](https://datatracker.ietf.org/doc/html/rfc6749#section-2.1)
### Beta 3 ### Beta 3
@ -97,7 +97,7 @@ Feature List:
Feature List: Feature List:
* [JWK's backed by X509 Certificate Chains](https://www.rfc-editor.org/rfc/rfc7517#section-4.7) * [JWK's backed by X509 Certificate Chains](https://datatracker.ietf.org/doc/html/rfc7517#section-4.7)
* Hashed Client Secrets * Hashed Client Secrets
* Per-Client [Consent](https://openid.net/specs/openid-connect-core-1_0.html#Consent) Mode: * Per-Client [Consent](https://openid.net/specs/openid-connect-core-1_0.html#Consent) Mode:
* Explicit: * Explicit:
@ -115,7 +115,7 @@ Feature List:
{{< roadmap-status stage="in-progress" version="v4.38.0" >}} {{< roadmap-status stage="in-progress" version="v4.38.0" >}}
* [OAuth 2.0 Pushed Authorization Requests](https://www.rfc-editor.org/rfc/rfc9126.html) * [OAuth 2.0 Pushed Authorization Requests](https://datatracker.ietf.org/doc/html/rfc9126)
* Per-Client [Proof Key Code Exchange (PKCE)] Policy * Per-Client [Proof Key Code Exchange (PKCE)] Policy
### Beta 7 ### Beta 7
@ -177,7 +177,7 @@ Should be implemented alongside [Dynamic Client Registration](#openid-connect-dy
{{< roadmap-status stage="complete" version="v4.34.0" >}} {{< roadmap-status stage="complete" version="v4.34.0" >}}
See the [IETF Specification RFC8414](https://www.rfc-editor.org/rfc/rfc8414.html) for more information. See the [IETF Specification RFC8414](https://datatracker.ietf.org/doc/html/rfc8414) for more information.
#### OpenID Connect Session Management #### OpenID Connect Session Management
@ -205,9 +205,9 @@ The `preferred_username` claim was missing and was fixed.
[Cross Origin Resource Sharing]: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS [Cross Origin Resource Sharing]: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
[RFC8176]: https://www.rfc-editor.org/rfc/rfc8176.html [RFC8176]: https://datatracker.ietf.org/doc/html/rfc8176
[RFC8693 Section 4.3]: https://www.rfc-editor.org/rfc/rfc8693.html/#section-4.3 [RFC8693 Section 4.3]: https://datatracker.ietf.org/doc/html/rfc8693/#section-4.3
[RFC4122]: https://www.rfc-editor.org/rfc/rfc4122.html [RFC4122]: https://datatracker.ietf.org/doc/html/rfc4122
[OpenID Connect]: https://openid.net/connect/ [OpenID Connect]: https://openid.net/connect/
[OpenID Connect Front-Channel Logout]: https://openid.net/specs/openid-connect-frontchannel-1_0.html [OpenID Connect Front-Channel Logout]: https://openid.net/specs/openid-connect-frontchannel-1_0.html
@ -219,4 +219,4 @@ The `preferred_username` claim was missing and was fixed.
[OpenID Connect Core (Subject Identifier Types)]: https://openid.net/specs/openid-connect-core-1_0.html#SubjectIDTypes [OpenID Connect Core (Subject Identifier Types)]: https://openid.net/specs/openid-connect-core-1_0.html#SubjectIDTypes
[OpenID Connect Core (Pairwise Identifier Algorithm)]: https://openid.net/specs/openid-connect-core-1_0.html#PairwiseAlg [OpenID Connect Core (Pairwise Identifier Algorithm)]: https://openid.net/specs/openid-connect-core-1_0.html#PairwiseAlg
[OpenID Connect Core (Mandatory to Implement Features for All OpenID Providers)]: https://openid.net/specs/openid-connect-core-1_0.html#ServerMTI [OpenID Connect Core (Mandatory to Implement Features for All OpenID Providers)]: https://openid.net/specs/openid-connect-core-1_0.html#ServerMTI
[Proof Key Code Exchange (PKCE)]: https://www.rfc-editor.org/rfc/rfc7636.html [Proof Key Code Exchange (PKCE)]: https://datatracker.ietf.org/doc/html/rfc7636

View File

@ -0,0 +1,18 @@
{{ $specificinfo := "../specific-information/" }}{{ $config := "../../../configuration/identity-providers/open-id-connect.md" }}
{{- with .Get "specificinfo" }}{{ $specificinfo = . }}{{ end }}
{{- with .Get "config" }}{{ $config = . }}{{ end }}
### Common Notes
1. The [OpenID Connect 1.0](https://openid.net/specs/openid-connect-core-1_0.html) `client_id` parameter:
1. This *__must__* be a unique value for every client.
2. The value used in this guide is merely for demonstration purposes and you can theoretically use nearly any
alphanumeric string.
2. The [OpenID Connect 1.0](https://openid.net/specs/openid-connect-core-1_0.html) `secret` parameter:
1. The value used in this guide is merely for demonstration purposes and you *__should absolutely not__* use this in
production and should instead utilize the
[Generating Client Secrets]({{ $specificinfo }}#generating-client-secrets) guide.
2. This string may be stored as plaintext in the Authelia configuration but this behaviour is deprecated and is not
guaranteed to be supported in the future. See the [Plaintext]({{ $specificinfo }}#plaintext) guide for more
information.
3. The Configuration example for Authelia is only a portion of the required configuration and it should be used as a
guide in conjunction with the standard [OpenID Connect 1.0 Configuration]({{ $config }}) guide.

View File

@ -5,7 +5,7 @@
[build.environment] [build.environment]
NODE_VERSION = "16.18.1" NODE_VERSION = "16.18.1"
NPM_VERSION = "8.19.2" NPM_VERSION = "8.19.2"
GO_VERSION = "1.19.4" GO_VERSION = "1.19.5"
[context.production] [context.production]
command = "pnpm run build" command = "pnpm run build"

14
go.mod
View File

@ -1,19 +1,19 @@
module github.com/authelia/authelia/v4 module github.com/authelia/authelia/v4
go 1.19 go 1.20
require ( require (
github.com/Gurpartap/logrus-stack v0.0.0-20170710170904-89c00d8a28f4 github.com/Gurpartap/logrus-stack v0.0.0-20170710170904-89c00d8a28f4
github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d
github.com/deckarep/golang-set/v2 v2.1.0 github.com/deckarep/golang-set/v2 v2.1.0
github.com/duosecurity/duo_api_golang v0.0.0-20221117185402-091daa09e19d github.com/duosecurity/duo_api_golang v0.0.0-20230203160531-b221c950c2b0
github.com/fasthttp/router v1.4.15 github.com/fasthttp/router v1.4.16
github.com/fasthttp/session/v2 v2.4.16 github.com/fasthttp/session/v2 v2.4.16
github.com/fsnotify/fsnotify v1.6.0 github.com/fsnotify/fsnotify v1.6.0
github.com/go-asn1-ber/asn1-ber v1.5.4 github.com/go-asn1-ber/asn1-ber v1.5.4
github.com/go-crypt/crypt v0.2.3 github.com/go-crypt/crypt v0.2.5
github.com/go-ldap/ldap/v3 v3.4.4 github.com/go-ldap/ldap/v3 v3.4.4
github.com/go-rod/rod v0.112.3 github.com/go-rod/rod v0.112.4
github.com/go-sql-driver/mysql v1.7.0 github.com/go-sql-driver/mysql v1.7.0
github.com/go-webauthn/webauthn v0.7.0 github.com/go-webauthn/webauthn v0.7.0
github.com/golang-jwt/jwt/v4 v4.4.3 github.com/golang-jwt/jwt/v4 v4.4.3
@ -40,6 +40,7 @@ require (
github.com/trustelem/zxcvbn v1.0.1 github.com/trustelem/zxcvbn v1.0.1
github.com/valyala/fasthttp v1.44.0 github.com/valyala/fasthttp v1.44.0
github.com/wneessen/go-mail v0.3.8 github.com/wneessen/go-mail v0.3.8
golang.org/x/net v0.5.0
golang.org/x/sync v0.1.0 golang.org/x/sync v0.1.0
golang.org/x/term v0.4.0 golang.org/x/term v0.4.0
golang.org/x/text v0.6.0 golang.org/x/text v0.6.0
@ -64,7 +65,7 @@ require (
github.com/ecordell/optgen v0.0.6 // indirect github.com/ecordell/optgen v0.0.6 // indirect
github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 // indirect github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 // indirect
github.com/fxamacker/cbor/v2 v2.4.0 // indirect github.com/fxamacker/cbor/v2 v2.4.0 // indirect
github.com/go-crypt/x v0.1.10 // indirect github.com/go-crypt/x v0.1.12 // indirect
github.com/go-redis/redis/v8 v8.11.5 // indirect github.com/go-redis/redis/v8 v8.11.5 // indirect
github.com/go-webauthn/revoke v0.1.6 // indirect github.com/go-webauthn/revoke v0.1.6 // indirect
github.com/golang/glog v1.0.0 // indirect github.com/golang/glog v1.0.0 // indirect
@ -109,7 +110,6 @@ require (
github.com/ysmood/leakless v0.8.0 // indirect github.com/ysmood/leakless v0.8.0 // indirect
golang.org/x/crypto v0.5.0 // indirect golang.org/x/crypto v0.5.0 // indirect
golang.org/x/mod v0.7.0 // indirect golang.org/x/mod v0.7.0 // indirect
golang.org/x/net v0.5.0 // indirect
golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783 // indirect golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783 // indirect
golang.org/x/sys v0.4.0 // indirect golang.org/x/sys v0.4.0 // indirect
golang.org/x/tools v0.4.0 // indirect golang.org/x/tools v0.4.0 // indirect

20
go.sum
View File

@ -127,8 +127,8 @@ github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cu
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
github.com/dlclark/regexp2 v1.4.0 h1:F1rxgk7p4uKjwIQxBs9oAXe5CqrXlCduYEJvrF4u93E= github.com/dlclark/regexp2 v1.4.0 h1:F1rxgk7p4uKjwIQxBs9oAXe5CqrXlCduYEJvrF4u93E=
github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
github.com/duosecurity/duo_api_golang v0.0.0-20221117185402-091daa09e19d h1:DdF2JKufY7l8IBJuGeanPFR5gVpWJfEh1LWJFM/zDas= github.com/duosecurity/duo_api_golang v0.0.0-20230203160531-b221c950c2b0 h1:+0VqbFomxHYZLIsuLJ7FjAdjhJTQ4P3/o6paTMx5kAY=
github.com/duosecurity/duo_api_golang v0.0.0-20221117185402-091daa09e19d/go.mod h1:jI+QUTOK3wqIOrUl0Cwnwlgc/P6vs6pZOuQY3aKggwg= github.com/duosecurity/duo_api_golang v0.0.0-20230203160531-b221c950c2b0/go.mod h1:jI+QUTOK3wqIOrUl0Cwnwlgc/P6vs6pZOuQY3aKggwg=
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/ecordell/optgen v0.0.6 h1:aSknPe6ZUBrjwHGp2+6XfmfCGYGD6W0ZDfCmmsrS7s4= github.com/ecordell/optgen v0.0.6 h1:aSknPe6ZUBrjwHGp2+6XfmfCGYGD6W0ZDfCmmsrS7s4=
@ -144,8 +144,8 @@ github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 h1:JWuenKqqX8nojtoVVWjGfOF9635RETekkoH6Cc9SX0A= github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 h1:JWuenKqqX8nojtoVVWjGfOF9635RETekkoH6Cc9SX0A=
github.com/facebookgo/stack v0.0.0-20160209184415-751773369052/go.mod h1:UbMTZqLaRiH3MsBH8va0n7s1pQYcu3uTb8G4tygF4Zg= github.com/facebookgo/stack v0.0.0-20160209184415-751773369052/go.mod h1:UbMTZqLaRiH3MsBH8va0n7s1pQYcu3uTb8G4tygF4Zg=
github.com/fasthttp/router v1.4.15 h1:ERaILezYX6ks1I+Z2v5qY4vqiQKnujauo9nV6M+HIOg= github.com/fasthttp/router v1.4.16 h1:faWJ9OtaHvAtodreyQLps58M80YFNzphMJtOJzeESXs=
github.com/fasthttp/router v1.4.15/go.mod h1:NFNlTCilbRVkeLc+E5JDkcxUdkpiJGKDL8Zy7Ey2JTI= github.com/fasthttp/router v1.4.16/go.mod h1:NFNlTCilbRVkeLc+E5JDkcxUdkpiJGKDL8Zy7Ey2JTI=
github.com/fasthttp/session/v2 v2.4.16 h1:JRvuEqr/+/cNMBkhGZN118FurLh6paUGscwJr26TxAQ= github.com/fasthttp/session/v2 v2.4.16 h1:JRvuEqr/+/cNMBkhGZN118FurLh6paUGscwJr26TxAQ=
github.com/fasthttp/session/v2 v2.4.16/go.mod h1:nv8SD6pAx3n3KjJsEt4k1p0vstqclbNcrCwjc1OjuCI= github.com/fasthttp/session/v2 v2.4.16/go.mod h1:nv8SD6pAx3n3KjJsEt4k1p0vstqclbNcrCwjc1OjuCI=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
@ -162,10 +162,10 @@ github.com/fxamacker/cbor/v2 v2.4.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrt
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-asn1-ber/asn1-ber v1.5.4 h1:vXT6d/FNDiELJnLb6hGNa309LMsrCoYFvpwHDF0+Y1A= github.com/go-asn1-ber/asn1-ber v1.5.4 h1:vXT6d/FNDiELJnLb6hGNa309LMsrCoYFvpwHDF0+Y1A=
github.com/go-asn1-ber/asn1-ber v1.5.4/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0= github.com/go-asn1-ber/asn1-ber v1.5.4/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
github.com/go-crypt/crypt v0.2.3 h1:g9OPe39VmqonsTXP/zo4byEoxrxAAUG+DzBvjzGWvuw= github.com/go-crypt/crypt v0.2.5 h1:QYGV/OkamPz69fME+JbD0wVmPnAL3C1Ooypqb1FHnHk=
github.com/go-crypt/crypt v0.2.3/go.mod h1:mbhOIjybuVuh0Vxveb//7UbGV8OCugJC7UPzqs1awYw= github.com/go-crypt/crypt v0.2.5/go.mod h1:VtajXhpCQlYwf4ekvp1I/6bSFi1YKobq0QInA1AFCQQ=
github.com/go-crypt/x v0.1.10 h1:HN8oQGrWcg5xPtIIGwPDWs9MvdYEUJrP7JeNkC46dvM= github.com/go-crypt/x v0.1.12 h1:UQvK75MBYGdeY7PdP/YbkUqiGxNzJq3BlO/lTVT6yuU=
github.com/go-crypt/x v0.1.10/go.mod h1:OI04rm/Ojti3mrUFZAJnx66nFbnZ0CVPF7qG49mBZgI= github.com/go-crypt/x v0.1.12/go.mod h1:037K8Cyl2IJUzO297LjhDIeYZYxg7K8yzbCco6ZNtV0=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
@ -182,8 +182,8 @@ github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG
github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI= github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI=
github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo= github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo=
github.com/go-rod/rod v0.112.3 h1:xbSaA9trZ8v/+eJRGOM6exK1RCsLPwwnzA78vpES0gk= github.com/go-rod/rod v0.112.4 h1:Ck002nM6rCORdVFtD778WxiadS5oJsmqytjXTG5bqiQ=
github.com/go-rod/rod v0.112.3/go.mod h1:ElViL9ABbcshNQw93+11FrYRH92RRhMKleuILo6+5V0= github.com/go-rod/rod v0.112.4/go.mod h1:ElViL9ABbcshNQw93+11FrYRH92RRhMKleuILo6+5V0=
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc= github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc=
github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=

View File

@ -426,7 +426,7 @@ authentication_backend:
## changed once attributed to a user otherwise it would break the configuration for that user. Technically, ## changed once attributed to a user otherwise it would break the configuration for that user. Technically,
## non-unique attributes like 'mail' can also be used but we don't recommend using them, we instead advise to use ## non-unique attributes like 'mail' can also be used but we don't recommend using them, we instead advise to use
## a filter to perform alternative lookups and the attributes mentioned above (sAMAccountName and uid) to ## a filter to perform alternative lookups and the attributes mentioned above (sAMAccountName and uid) to
## follow https://www.ietf.org/rfc/rfc2307.txt. ## follow https://datatracker.ietf.org/doc/html/rfc2307.
# username_attribute: uid # username_attribute: uid
## The additional_users_dn is prefixed to base_dn and delimited by a comma when searching for users. ## The additional_users_dn is prefixed to base_dn and delimited by a comma when searching for users.

View File

@ -105,6 +105,9 @@ func TestShouldValidateConfigurationWithFilters(t *testing.T) {
testSetEnv(t, "JWT_SECRET", "abc") testSetEnv(t, "JWT_SECRET", "abc")
testSetEnv(t, "AUTHENTICATION_BACKEND_LDAP_PASSWORD", "abc") testSetEnv(t, "AUTHENTICATION_BACKEND_LDAP_PASSWORD", "abc")
t.Setenv("ABC_CLIENT_SECRET", "$plaintext$example-abc")
t.Setenv("XYZ_CLIENT_SECRET", "$plaintext$example-xyz")
t.Setenv("ANOTHER_CLIENT_SECRET", "$plaintext$example-123")
t.Setenv("SERVICES_SERVER", "10.10.10.10") t.Setenv("SERVICES_SERVER", "10.10.10.10")
t.Setenv("ROOT_DOMAIN", "example.org") t.Setenv("ROOT_DOMAIN", "example.org")
@ -118,6 +121,11 @@ func TestShouldValidateConfigurationWithFilters(t *testing.T) {
assert.Equal(t, "api-123456789.example.org", config.DuoAPI.Hostname) assert.Equal(t, "api-123456789.example.org", config.DuoAPI.Hostname)
assert.Equal(t, "10.10.10.10", config.Notifier.SMTP.Host) assert.Equal(t, "10.10.10.10", config.Notifier.SMTP.Host)
assert.Equal(t, "10.10.10.10", config.Session.Redis.Host) assert.Equal(t, "10.10.10.10", config.Session.Redis.Host)
require.Len(t, config.IdentityProviders.OIDC.Clients, 3)
assert.Equal(t, "$plaintext$example-abc", config.IdentityProviders.OIDC.Clients[0].Secret.String())
assert.Equal(t, "$plaintext$example-xyz", config.IdentityProviders.OIDC.Clients[1].Secret.String())
assert.Equal(t, "$plaintext$example-123", config.IdentityProviders.OIDC.Clients[2].Secret.String())
} }
func TestShouldNotIgnoreInvalidEnvs(t *testing.T) { func TestShouldNotIgnoreInvalidEnvs(t *testing.T) {

View File

@ -174,4 +174,21 @@ notifier:
port: 1025 port: 1025
sender: 'admin@{{ env "ROOT_DOMAIN" }}' sender: 'admin@{{ env "ROOT_DOMAIN" }}'
disable_require_tls: true disable_require_tls: true
identity_providers:
oidc:
cors:
allowed_origins:
- https://google.com
- https://example.com
clients:
- id: abc
secret: '${ABC_CLIENT_SECRET}'
consent_mode: explicit
- id: xyz
secret: '$XYZ_CLIENT_SECRET'
consent_mode: explicit
- id: '123'
secret: $ANOTHER_CLIENT_SECRET
consent_mode: explicit
... ...

View File

@ -267,7 +267,9 @@ const (
errFmtSessionDomainDuplicateCookieScope = "session: domain config %s: option 'domain' shares the same cookie domain scope as another configured session domain" errFmtSessionDomainDuplicateCookieScope = "session: domain config %s: option 'domain' shares the same cookie domain scope as another configured session domain"
errFmtSessionDomainPortalURLInsecure = "session: domain config %s: option 'authelia_url' does not have a secure scheme with a value of '%s'" errFmtSessionDomainPortalURLInsecure = "session: domain config %s: option 'authelia_url' does not have a secure scheme with a value of '%s'"
errFmtSessionDomainPortalURLNotInCookieScope = "session: domain config %s: option 'authelia_url' does not share a cookie scope with domain '%s' with a value of '%s'" errFmtSessionDomainPortalURLNotInCookieScope = "session: domain config %s: option 'authelia_url' does not share a cookie scope with domain '%s' with a value of '%s'"
errFmtSessionDomainInvalidDomain = "session: domain config %s: option 'domain' is not a valid domain" errFmtSessionDomainInvalidDomain = "session: domain config %s: option 'domain' is not a valid cookie domain"
errFmtSessionDomainInvalidDomainNoDots = "session: domain config %s: option 'domain' is not a valid cookie domain: must have at least a single period"
errFmtSessionDomainInvalidDomainPublic = "session: domain config %s: option 'domain' is not a valid cookie domain: the domain is part of the special public suffix list"
) )
// Regulation Error Consts. // Regulation Error Consts.

View File

@ -104,12 +104,22 @@ func validateSessionDomainName(i int, config *schema.SessionConfiguration, valid
switch { switch {
case d.Domain == "": case d.Domain == "":
validator.Push(fmt.Errorf(errFmtSessionDomainRequired, sessionDomainDescriptor(i, d))) validator.Push(fmt.Errorf(errFmtSessionDomainRequired, sessionDomainDescriptor(i, d)))
return
case strings.HasPrefix(d.Domain, "*."): case strings.HasPrefix(d.Domain, "*."):
validator.Push(fmt.Errorf(errFmtSessionDomainMustBeRoot, sessionDomainDescriptor(i, d), d.Domain)) validator.Push(fmt.Errorf(errFmtSessionDomainMustBeRoot, sessionDomainDescriptor(i, d), d.Domain))
return
case strings.HasPrefix(d.Domain, "."): case strings.HasPrefix(d.Domain, "."):
validator.PushWarning(fmt.Errorf(errFmtSessionDomainHasPeriodPrefix, sessionDomainDescriptor(i, d))) validator.PushWarning(fmt.Errorf(errFmtSessionDomainHasPeriodPrefix, sessionDomainDescriptor(i, d)))
case !strings.Contains(d.Domain, "."):
validator.Push(fmt.Errorf(errFmtSessionDomainInvalidDomainNoDots, sessionDomainDescriptor(i, d)))
return
case !reDomainCharacters.MatchString(d.Domain): case !reDomainCharacters.MatchString(d.Domain):
validator.Push(fmt.Errorf(errFmtSessionDomainInvalidDomain, sessionDomainDescriptor(i, d))) validator.Push(fmt.Errorf(errFmtSessionDomainInvalidDomain, sessionDomainDescriptor(i, d)))
return
}
if isCookieDomainAPublicSuffix(d.Domain) {
validator.Push(fmt.Errorf(errFmtSessionDomainInvalidDomainPublic, sessionDomainDescriptor(i, d)))
} }
} }

View File

@ -586,45 +586,6 @@ func TestShouldRaiseErrorOnBadRedisTLSOptionsMinVerGreaterThanMax(t *testing.T)
assert.EqualError(t, validator.Errors()[0], "session: redis: tls: option combination of 'minimum_version' and 'maximum_version' is invalid: minimum version TLS1.3 is greater than the maximum version TLS1.0") assert.EqualError(t, validator.Errors()[0], "session: redis: tls: option combination of 'minimum_version' and 'maximum_version' is invalid: minimum version TLS1.3 is greater than the maximum version TLS1.0")
} }
func TestShouldRaiseErrorWhenDomainNotSet(t *testing.T) {
validator := schema.NewStructValidator()
config := newDefaultSessionConfig()
config.Domain = ""
config.Cookies = []schema.SessionCookieConfiguration{}
ValidateSession(&config, validator)
assert.False(t, validator.HasWarnings())
assert.Len(t, validator.Errors(), 1)
assert.EqualError(t, validator.Errors()[0], "session: option 'domain' is required")
}
func TestShouldRaiseErrorWhenDomainIsWildcard(t *testing.T) {
validator := schema.NewStructValidator()
config := newDefaultSessionConfig()
config.Domain = "*.example.com"
ValidateSession(&config, validator)
assert.Len(t, validator.Warnings(), 0)
require.Len(t, validator.Errors(), 1)
assert.EqualError(t, validator.Errors()[0], "session: domain config #1 (domain '*.example.com'): option 'domain' must be the domain you wish to protect not a wildcard domain but it is configured as '*.example.com'")
}
func TestShouldRaiseErrorWhenDomainNameIsInvalid(t *testing.T) {
validator := schema.NewStructValidator()
config := newDefaultSessionConfig()
config.Domain = "example!.com"
ValidateSession(&config, validator)
assert.Len(t, validator.Warnings(), 0)
require.Len(t, validator.Errors(), 1)
assert.EqualError(t, validator.Errors()[0], "session: domain config #1 (domain 'example!.com'): option 'domain' is not a valid domain")
}
func TestShouldRaiseErrorWhenHaveDuplicatedDomainName(t *testing.T) { func TestShouldRaiseErrorWhenHaveDuplicatedDomainName(t *testing.T) {
validator := schema.NewStructValidator() validator := schema.NewStructValidator()
config := newDefaultSessionConfig() config := newDefaultSessionConfig()
@ -675,10 +636,18 @@ func TestShouldRaiseErrorWhenDomainIsInvalid(t *testing.T) {
testCases := []struct { testCases := []struct {
name string name string
have string have string
warnings []string
expected []string expected []string
}{ }{
{"ShouldRaiseErrorOnMissingDomain", "", []string{"session: domain config #1 (domain ''): option 'domain' is required"}}, {"ShouldNotRaiseErrorOnValidDomain", exampleDotCom, nil, nil},
{"ShouldNotRaiseErrorOnValidDomain", exampleDotCom, nil}, {"ShouldRaiseErrorOnMissingDomain", "", nil, []string{"session: domain config #1 (domain ''): option 'domain' is required"}},
{"ShouldRaiseErrorOnDomainWithInvalidChars", "example!.com", nil, []string{"session: domain config #1 (domain 'example!.com'): option 'domain' is not a valid cookie domain"}},
{"ShouldRaiseErrorOnDomainWithoutDots", "localhost", nil, []string{"session: domain config #1 (domain 'localhost'): option 'domain' is not a valid cookie domain: must have at least a single period"}},
{"ShouldRaiseErrorOnPublicDomainDuckDNS", "duckdns.org", nil, []string{"session: domain config #1 (domain 'duckdns.org'): option 'domain' is not a valid cookie domain: the domain is part of the special public suffix list"}},
{"ShouldNotRaiseErrorOnSuffixOfPublicDomainDuckDNS", "example.duckdns.org", nil, nil},
{"ShouldRaiseWarningOnDomainWithLeadingDot", ".example.com", []string{"session: domain config #1 (domain '.example.com'): option 'domain' has a prefix of '.' which is not supported or intended behaviour: you can use this at your own risk but we recommend removing it"}, nil},
{"ShouldRaiseErrorOnDomainWithLeadingStarDot", "*.example.com", nil, []string{"session: domain config #1 (domain '*.example.com'): option 'domain' must be the domain you wish to protect not a wildcard domain but it is configured as '*.example.com'"}},
{"ShouldRaiseErrorOnDomainNotSet", "", nil, []string{"session: domain config #1 (domain ''): option 'domain' is required"}},
} }
for _, tc := range testCases { for _, tc := range testCases {
@ -692,14 +661,18 @@ func TestShouldRaiseErrorWhenDomainIsInvalid(t *testing.T) {
SessionCookieCommonConfiguration: schema.SessionCookieCommonConfiguration{ SessionCookieCommonConfiguration: schema.SessionCookieCommonConfiguration{
Domain: tc.have, Domain: tc.have,
}, },
AutheliaURL: MustParseURL("https://auth.example.com")}, },
} }
ValidateSession(&config, validator) ValidateSession(&config, validator)
assert.Len(t, validator.Warnings(), 0) require.Len(t, validator.Warnings(), len(tc.warnings))
require.Len(t, validator.Errors(), len(tc.expected)) require.Len(t, validator.Errors(), len(tc.expected))
for i, expected := range tc.warnings {
assert.EqualError(t, validator.Warnings()[i], expected)
}
for i, expected := range tc.expected { for i, expected := range tc.expected {
assert.EqualError(t, validator.Errors()[i], expected) assert.EqualError(t, validator.Errors()[i], expected)
} }

View File

@ -0,0 +1,15 @@
package validator
import (
"strings"
"golang.org/x/net/publicsuffix"
)
func isCookieDomainAPublicSuffix(domain string) (valid bool) {
var suffix string
suffix, _ = publicsuffix.PublicSuffix(domain)
return len(strings.TrimLeft(domain, ".")) == len(suffix)
}

View File

@ -0,0 +1,40 @@
package validator
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestIsCookieDomainValid(t *testing.T) {
testCases := []struct {
domain string
expected bool
}{
{"example.com", false},
{".example.com", false},
{"*.example.com", false},
{"authelia.com", false},
{"duckdns.org", true},
{".duckdns.org", true},
{"example.duckdns.org", false},
{"192.168.2.1", false},
{"localhost", true},
{"com", true},
{"randomnada", true},
}
for _, tc := range testCases {
name := "ShouldFail"
if tc.expected {
name = "ShouldPass"
}
t.Run(tc.domain, func(t *testing.T) {
t.Run(name, func(t *testing.T) {
assert.Equal(t, tc.expected, isCookieDomainAPublicSuffix(tc.domain))
})
})
}
}

View File

@ -234,11 +234,11 @@ func (p *CORSPolicy) handleOPTIONS(ctx *fasthttp.RequestCtx) {
/* The OPTIONS method should not return a 204 as per the following specifications when read together: /* The OPTIONS method should not return a 204 as per the following specifications when read together:
RFC7231 (https://www.rfc-editor.org/rfc/rfc7231#section-4.3.7): RFC7231 (https://datatracker.ietf.org/doc/html/rfc7231#section-4.3.7):
A server MUST generate a Content-Length field with a value of "0" if no payload body is to be sent in A server MUST generate a Content-Length field with a value of "0" if no payload body is to be sent in
the response. the response.
RFC7230 (https://www.rfc-editor.org/rfc/rfc7230#section-3.3.2): RFC7230 (https://datatracker.ietf.org/doc/html/rfc7230#section-3.3.2):
A server MUST NOT send a Content-Length header field in any response with a status code of 1xx (Informational) A server MUST NOT send a Content-Length header field in any response with a status code of 1xx (Informational)
or 204 (No Content). or 204 (No Content).
*/ */

View File

@ -121,33 +121,48 @@ func (mr *MockRandomMockRecorder) IntErr(arg0 interface{}) *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IntErr", reflect.TypeOf((*MockRandom)(nil).IntErr), arg0) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IntErr", reflect.TypeOf((*MockRandom)(nil).IntErr), arg0)
} }
// Integer mocks base method. // Intn mocks base method.
func (m *MockRandom) Integer(arg0 int) int { func (m *MockRandom) Intn(arg0 int) int {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Integer", arg0) ret := m.ctrl.Call(m, "Intn", arg0)
ret0, _ := ret[0].(int) ret0, _ := ret[0].(int)
return ret0 return ret0
} }
// Integer indicates an expected call of Integer. // Intn indicates an expected call of Intn.
func (mr *MockRandomMockRecorder) Integer(arg0 interface{}) *gomock.Call { func (mr *MockRandomMockRecorder) Intn(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper() mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Integer", reflect.TypeOf((*MockRandom)(nil).Integer), arg0) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Intn", reflect.TypeOf((*MockRandom)(nil).Intn), arg0)
} }
// IntegerErr mocks base method. // IntnErr mocks base method.
func (m *MockRandom) IntegerErr(arg0 int) (int, error) { func (m *MockRandom) IntnErr(arg0 int) (int, error) {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "IntegerErr", arg0) ret := m.ctrl.Call(m, "IntnErr", arg0)
ret0, _ := ret[0].(int) ret0, _ := ret[0].(int)
ret1, _ := ret[1].(error) ret1, _ := ret[1].(error)
return ret0, ret1 return ret0, ret1
} }
// IntegerErr indicates an expected call of IntegerErr. // IntnErr indicates an expected call of IntnErr.
func (mr *MockRandomMockRecorder) IntegerErr(arg0 interface{}) *gomock.Call { func (mr *MockRandomMockRecorder) IntnErr(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper() mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IntegerErr", reflect.TypeOf((*MockRandom)(nil).IntegerErr), arg0) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IntnErr", reflect.TypeOf((*MockRandom)(nil).IntnErr), arg0)
}
// Prime mocks base method.
func (m *MockRandom) Prime(arg0 int) (*big.Int, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Prime", arg0)
ret0, _ := ret[0].(*big.Int)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Prime indicates an expected call of Prime.
func (mr *MockRandomMockRecorder) Prime(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Prime", reflect.TypeOf((*MockRandom)(nil).Prime), arg0)
} }
// Read mocks base method. // Read mocks base method.

View File

@ -163,8 +163,8 @@ func (n *SMTPNotifier) Send(ctx context.Context, recipient mail.Address, subject
} }
func (n *SMTPNotifier) setMessageID(msg *gomail.Msg, domain string) { func (n *SMTPNotifier) setMessageID(msg *gomail.Msg, domain string) {
rn := n.random.Integer(100000000) rn := n.random.Intn(100000000)
rm := n.random.Integer(10000) rm := n.random.Intn(10000)
rs := n.random.StringCustom(17, random.CharSetAlphaNumeric) rs := n.random.StringCustom(17, random.CharSetAlphaNumeric)
pid := os.Getpid() + rm pid := os.Getpid() + rm

View File

@ -180,7 +180,7 @@ func (s *Store) DeleteAccessTokenSession(ctx context.Context, signature string)
return s.revokeSessionBySignature(ctx, storage.OAuth2SessionTypeAccessToken, signature) return s.revokeSessionBySignature(ctx, storage.OAuth2SessionTypeAccessToken, signature)
} }
// RevokeAccessToken revokes an access token as specified in: https://tools.ietf.org/html/rfc7009#section-2.1 // RevokeAccessToken revokes an access token as specified in: https://datatracker.ietf.org/doc/html/rfc7009#section-2.1
// If the token passed to the request is an access token, the server MAY revoke the respective refresh token as well. // If the token passed to the request is an access token, the server MAY revoke the respective refresh token as well.
// This implements a portion of oauth2.TokenRevocationStorage. // This implements a portion of oauth2.TokenRevocationStorage.
func (s *Store) RevokeAccessToken(ctx context.Context, requestID string) (err error) { func (s *Store) RevokeAccessToken(ctx context.Context, requestID string) (err error) {
@ -205,7 +205,7 @@ func (s *Store) DeleteRefreshTokenSession(ctx context.Context, signature string)
return s.revokeSessionBySignature(ctx, storage.OAuth2SessionTypeRefreshToken, signature) return s.revokeSessionBySignature(ctx, storage.OAuth2SessionTypeRefreshToken, signature)
} }
// RevokeRefreshToken revokes a refresh token as specified in: https://tools.ietf.org/html/rfc7009#section-2.1 // RevokeRefreshToken revokes a refresh token as specified in: https://datatracker.ietf.org/doc/html/rfc7009#section-2.1
// If the particular token is a refresh token and the authorization server supports the revocation of access tokens, // If the particular token is a refresh token and the authorization server supports the revocation of access tokens,
// then the authorization server SHOULD also invalidate all access tokens based on the same authorization grant (see Implementation Note). // then the authorization server SHOULD also invalidate all access tokens based on the same authorization grant (see Implementation Note).
// This implements a portion of oauth2.TokenRevocationStorage. // This implements a portion of oauth2.TokenRevocationStorage.
@ -213,7 +213,7 @@ func (s *Store) RevokeRefreshToken(ctx context.Context, requestID string) (err e
return s.provider.DeactivateOAuth2SessionByRequestID(ctx, storage.OAuth2SessionTypeRefreshToken, requestID) return s.provider.DeactivateOAuth2SessionByRequestID(ctx, storage.OAuth2SessionTypeRefreshToken, requestID)
} }
// RevokeRefreshTokenMaybeGracePeriod revokes an access token as specified in: https://tools.ietf.org/html/rfc7009#section-2.1 // RevokeRefreshTokenMaybeGracePeriod revokes an access token as specified in: https://datatracker.ietf.org/doc/html/rfc7009#section-2.1
// If the token passed to the request is an access token, the server MAY revoke the respective refresh token as well. // If the token passed to the request is an access token, the server MAY revoke the respective refresh token as well.
// This implements a portion of oauth2.TokenRevocationStorage. // This implements a portion of oauth2.TokenRevocationStorage.
func (s *Store) RevokeRefreshTokenMaybeGracePeriod(ctx context.Context, requestID string, signature string) (err error) { func (s *Store) RevokeRefreshTokenMaybeGracePeriod(ctx context.Context, requestID string, signature string) (err error) {

View File

@ -25,7 +25,7 @@ const (
CharSetSymbolic = "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~" CharSetSymbolic = "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~"
// CharSetSymbolicRFC3986Unreserved are RFC3986 unreserved symbol characters. // CharSetSymbolicRFC3986Unreserved are RFC3986 unreserved symbol characters.
// See https://www.rfc-editor.org/rfc/rfc3986#section-2.3. // See https://datatracker.ietf.org/doc/html/rfc3986#section-2.3.
CharSetSymbolicRFC3986Unreserved = "-._~" CharSetSymbolicRFC3986Unreserved = "-._~"
// CharSetAlphaNumeric are literally just valid alphanumeric printable ASCII chars. // CharSetAlphaNumeric are literally just valid alphanumeric printable ASCII chars.
@ -35,7 +35,7 @@ const (
CharSetASCII = CharSetAlphabetic + CharSetNumeric + CharSetSymbolic CharSetASCII = CharSetAlphabetic + CharSetNumeric + CharSetSymbolic
// CharSetRFC3986Unreserved are RFC3986 unreserved characters. // CharSetRFC3986Unreserved are RFC3986 unreserved characters.
// See https://www.rfc-editor.org/rfc/rfc3986#section-2.3. // See https://datatracker.ietf.org/doc/html/rfc3986#section-2.3.
CharSetRFC3986Unreserved = CharSetAlphabetic + CharSetNumeric + CharSetSymbolicRFC3986Unreserved CharSetRFC3986Unreserved = CharSetAlphabetic + CharSetNumeric + CharSetSymbolicRFC3986Unreserved
// CharSetUnambiguousUpper are a set of unambiguous uppercase characters. // CharSetUnambiguousUpper are a set of unambiguous uppercase characters.

View File

@ -18,11 +18,7 @@ func (r *Cryptographical) Read(p []byte) (n int, err error) {
// BytesErr returns random data as bytes with the standard random.DefaultN length and can contain any byte values // BytesErr returns random data as bytes with the standard random.DefaultN length and can contain any byte values
// (including unreadable byte values). If an error is returned from the random read this function returns it. // (including unreadable byte values). If an error is returned from the random read this function returns it.
func (r *Cryptographical) BytesErr() (data []byte, err error) { func (r *Cryptographical) BytesErr() (data []byte, err error) {
data = make([]byte, DefaultN) return r.BytesCustomErr(0, nil)
_, err = rand.Read(data)
return data, err
} }
// Bytes returns random data as bytes with the standard random.DefaultN length and can contain any byte values // Bytes returns random data as bytes with the standard random.DefaultN length and can contain any byte values
@ -49,8 +45,10 @@ func (r *Cryptographical) BytesCustomErr(n int, charset []byte) (data []byte, er
t := len(charset) t := len(charset)
for i := 0; i < n; i++ { if t > 0 {
data[i] = charset[data[i]%byte(t)] for i := 0; i < n; i++ {
data[i] = charset[data[i]%byte(t)]
}
} }
return data, nil return data, nil
@ -81,6 +79,36 @@ func (r *Cryptographical) StringCustom(n int, characters string) (data string) {
return string(r.BytesCustom(n, []byte(characters))) return string(r.BytesCustom(n, []byte(characters)))
} }
// IntnErr returns a random int error combination with a maximum of n.
func (r *Cryptographical) IntnErr(n int) (value int, err error) {
if n <= 0 {
return 0, fmt.Errorf("n must be more than 0")
}
max := big.NewInt(int64(n))
var result *big.Int
if result, err = r.IntErr(max); err != nil {
return 0, err
}
value = int(result.Int64())
if value < 0 {
return 0, fmt.Errorf("generated number is too big for int")
}
return value, nil
}
// Intn returns a random int with a maximum of n.
func (r *Cryptographical) Intn(n int) (value int) {
value, _ = r.IntnErr(n)
return value
}
// IntErr returns a random *big.Int error combination with a maximum of max. // IntErr returns a random *big.Int error combination with a maximum of max.
func (r *Cryptographical) IntErr(max *big.Int) (value *big.Int, err error) { func (r *Cryptographical) IntErr(max *big.Int) (value *big.Int, err error) {
if max == nil { if max == nil {
@ -105,32 +133,8 @@ func (r *Cryptographical) Int(max *big.Int) (value *big.Int) {
return value return value
} }
// IntegerErr returns a random int error combination with a maximum of n. // Prime returns a number of the given bit length that is prime with high probability. Prime will return error for any
func (r *Cryptographical) IntegerErr(n int) (value int, err error) { // error returned by rand.Read or if bits < 2.
if n <= 0 { func (r *Cryptographical) Prime(bits int) (prime *big.Int, err error) {
return 0, fmt.Errorf("n must be more than 0") return rand.Prime(rand.Reader, bits)
}
max := big.NewInt(int64(n))
var result *big.Int
if result, err = r.IntErr(max); err != nil {
return 0, err
}
value = int(result.Int64())
if value < 0 {
return 0, fmt.Errorf("generated number is too big for int")
}
return value, nil
}
// Integer returns a random int with a maximum of n.
func (r *Cryptographical) Integer(n int) (value int) {
value, _ = r.IntegerErr(n)
return value
} }

View File

@ -1,26 +1,36 @@
package random package random
import ( import (
crand "crypto/rand"
"fmt" "fmt"
"math/big" "math/big"
"math/rand" "math/rand"
"sync"
"time" "time"
) )
// NewMathematical runs rand.Seed with the current time and returns a random.Provider, specifically *random.Mathematical. // NewMathematical runs rand.Seed with the current time and returns a random.Provider, specifically *random.Mathematical.
func NewMathematical() *Mathematical { func NewMathematical() *Mathematical {
rand.Seed(time.Now().UnixNano()) return &Mathematical{
rand: rand.New(rand.NewSource(time.Now().UnixNano())), //nolint:gosec
return &Mathematical{} lock: &sync.Mutex{},
}
} }
// Mathematical is the random.Provider which uses math/rand and is COMPLETELY UNSAFE FOR PRODUCTION IN MOST SITUATIONS. // Mathematical is the random.Provider which uses math/rand and is COMPLETELY UNSAFE FOR PRODUCTION IN MOST SITUATIONS.
// Use random.Cryptographical instead. // Use random.Cryptographical instead.
type Mathematical struct{} type Mathematical struct {
rand *rand.Rand
lock *sync.Mutex
}
// Read implements the io.Reader interface. // Read implements the io.Reader interface.
func (r *Mathematical) Read(p []byte) (n int, err error) { func (r *Mathematical) Read(p []byte) (n int, err error) {
return rand.Read(p) //nolint:gosec r.lock.Lock()
defer r.lock.Unlock()
return r.rand.Read(p)
} }
// BytesErr returns random data as bytes with the standard random.DefaultN length and can contain any byte values // BytesErr returns random data as bytes with the standard random.DefaultN length and can contain any byte values
@ -28,7 +38,7 @@ func (r *Mathematical) Read(p []byte) (n int, err error) {
func (r *Mathematical) BytesErr() (data []byte, err error) { func (r *Mathematical) BytesErr() (data []byte, err error) {
data = make([]byte, DefaultN) data = make([]byte, DefaultN)
if _, err = rand.Read(data); err != nil { //nolint:gosec if _, err = r.Read(data); err != nil {
return nil, err return nil, err
} }
@ -53,7 +63,7 @@ func (r *Mathematical) BytesCustomErr(n int, charset []byte) (data []byte, err e
data = make([]byte, n) data = make([]byte, n)
if _, err = rand.Read(data); err != nil { //nolint:gosec if _, err = r.Read(data); err != nil {
return nil, err return nil, err
} }
@ -91,17 +101,18 @@ func (r *Mathematical) StringCustom(n int, characters string) (data string) {
return string(r.BytesCustom(n, []byte(characters))) return string(r.BytesCustom(n, []byte(characters)))
} }
// IntErr returns a random *big.Int error combination with a maximum of max. // Intn returns a random int with a maximum of n.
func (r *Mathematical) IntErr(max *big.Int) (value *big.Int, err error) { func (r *Mathematical) Intn(n int) int {
if max == nil { r.lock.Lock()
return nil, fmt.Errorf("max is required")
}
if max.Sign() <= 0 { defer r.lock.Unlock()
return nil, fmt.Errorf("max must be 1 or more")
}
return big.NewInt(int64(rand.Intn(max.Sign()))), nil //nolint:gosec return r.rand.Intn(n)
}
// IntnErr returns a random int error combination with a maximum of n.
func (r *Mathematical) IntnErr(n int) (output int, err error) {
return r.Intn(n), nil
} }
// Int returns a random *big.Int with a maximum of max. // Int returns a random *big.Int with a maximum of max.
@ -115,12 +126,25 @@ func (r *Mathematical) Int(max *big.Int) (value *big.Int) {
return value return value
} }
// IntegerErr returns a random int error combination with a maximum of n. // IntErr returns a random *big.Int error combination with a maximum of max.
func (r *Mathematical) IntegerErr(n int) (output int, err error) { func (r *Mathematical) IntErr(max *big.Int) (value *big.Int, err error) {
return r.Integer(n), nil if max == nil {
return nil, fmt.Errorf("max is required")
}
if max.Sign() <= 0 {
return nil, fmt.Errorf("max must be 1 or more")
}
r.lock.Lock()
defer r.lock.Unlock()
return big.NewInt(int64(r.Intn(max.Sign()))), nil
} }
// Integer returns a random int with a maximum of n. // Prime returns a number of the given bit length that is prime with high probability. Prime will return error for any
func (r *Mathematical) Integer(n int) int { // error returned by rand.Read or if bits < 2.
return rand.Intn(n) //nolint:gosec func (r *Mathematical) Prime(bits int) (prime *big.Int, err error) {
return crand.Prime(r, bits)
} }

View File

@ -32,15 +32,19 @@ type Provider interface {
// StringCustom is an overload of GenerateCustom which takes a characters string and returns a string. // StringCustom is an overload of GenerateCustom which takes a characters string and returns a string.
StringCustom(n int, characters string) (data string) StringCustom(n int, characters string) (data string)
// Intn returns a random integer with a maximum of n.
Intn(n int) (value int)
// IntnErr returns a random int error combination with a maximum of n.
IntnErr(n int) (value int, err error)
// IntErr returns a random *big.Int error combination with a maximum of max. // IntErr returns a random *big.Int error combination with a maximum of max.
IntErr(max *big.Int) (value *big.Int, err error) IntErr(max *big.Int) (value *big.Int, err error)
// Int returns a random *big.Int with a maximum of max. // Int returns a random *big.Int with a maximum of max.
Int(max *big.Int) (value *big.Int) Int(max *big.Int) (value *big.Int)
// IntegerErr returns a random int error combination with a maximum of n. // Prime returns a number of the given bit length that is prime with high probability. Prime will return error for any
IntegerErr(n int) (value int, err error) // error returned by rand.Read or if bits < 2.
Prime(bits int) (prime *big.Int, err error)
// Integer returns a random integer with a maximum of n.
Integer(n int) (value int)
} }

View File

@ -4,11 +4,11 @@
"Access your group membership": "Tilgang til ditt gruppemedlemskap", "Access your group membership": "Tilgang til ditt gruppemedlemskap",
"Access your profile information": "Få tilgang til profilinformasjonen din", "Access your profile information": "Få tilgang til profilinformasjonen din",
"An email has been sent to your address to complete the process": "En e-post har blitt sendt til din adresse for å fullføre prosessen.", "An email has been sent to your address to complete the process": "En e-post har blitt sendt til din adresse for å fullføre prosessen.",
"Authenticated": "Verifisert", "Authenticated": "Autentisert",
"Automatically refresh these permissions without user interaction": "Oppdater disse tillatelsene automatisk uten brukerinteraksjon", "Automatically refresh these permissions without user interaction": "Oppdater disse tillatelsene automatisk uten brukerinteraksjon",
"Cancel": "Avbryt", "Cancel": "Avbryt",
"Client ID": "Klient-ID: {{client_id}}", "Client ID": "Klient-ID: {{client_id}}",
"Consent Request": "Samtaleforespørsel", "Consent Request": "Samtykkeforespørsel",
"Contact your administrator to register a device": "Kontakt systemansvarlig for å registrere en enhet.", "Contact your administrator to register a device": "Kontakt systemansvarlig for å registrere en enhet.",
"Could not obtain user settings": "Kan ikke hente brukerinnstillinger", "Could not obtain user settings": "Kan ikke hente brukerinnstillinger",
"Deny": "Avslå", "Deny": "Avslå",
@ -16,15 +16,15 @@
"Enter new password": "Skriv inn nytt passord", "Enter new password": "Skriv inn nytt passord",
"Enter one-time password": "Angi engangspassord", "Enter one-time password": "Angi engangspassord",
"Failed to register device, the provided link is expired or has already been used": "Kan ikke registrere enheten, den angitte lenken er utløpt eller allerede er brukt", "Failed to register device, the provided link is expired or has already been used": "Kan ikke registrere enheten, den angitte lenken er utløpt eller allerede er brukt",
"Hi": "Hi", "Hi": "Hei",
"Incorrect username or password": "Ugyldig brukernavn eller passord.", "Incorrect username or password": "Ugyldig brukernavn eller passord.",
"Loading": "Laster", "Loading": "Laster",
"Login": "Innlogging", "Login": "Innlogging",
"Logout": "Logg", "Logout": "Logg ut",
"Lost your device?": "Har du mistet enheten?", "Lost your device?": "Har du mistet enheten?",
"Methods": "Metoder", "Methods": "Metoder",
"Must be at least {{len}} characters in length": "Må være minst {{len}} tegn i lengde", "Must be at least {{len}} characters in length": "Må være minst {{len}} tegn i lengde",
"Must have at least one UPPERCASE letter": "Må ha minst én STORE bokstav", "Must have at least one UPPERCASE letter": "Må ha minst én STOR bokstav",
"Must have at least one lowercase letter": "Må ha minst én liten bokstav", "Must have at least one lowercase letter": "Må ha minst én liten bokstav",
"Must have at least one number": "Må ha minst ett tall", "Must have at least one number": "Må ha minst ett tall",
"Must have at least one special character": "Må ha minst ett spesialtegn", "Must have at least one special character": "Må ha minst ett spesialtegn",
@ -39,6 +39,7 @@
"Password": "Passord", "Password": "Passord",
"Passwords do not match": "Passordene samsvarer ikke.", "Passwords do not match": "Passordene samsvarer ikke.",
"Powered by": "Drives av", "Powered by": "Drives av",
"Privacy Policy": "Personvernerklæring",
"Push Notification": "Push varsling", "Push Notification": "Push varsling",
"Register device": "Registrer enheten", "Register device": "Registrer enheten",
"Register your first device by clicking on the link below": "Registrer din første enhet ved å klikke på lenken nedenfor.", "Register your first device by clicking on the link below": "Registrer din første enhet ved å klikke på lenken nedenfor.",
@ -47,8 +48,8 @@
"Repeat new password": "Gjenta nytt passord", "Repeat new password": "Gjenta nytt passord",
"Reset password": "Tilbakestill passord", "Reset password": "Tilbakestill passord",
"Reset password?": "Tilbakestill passord?", "Reset password?": "Tilbakestill passord?",
"Reset": "Reset", "Reset": "Tilbakestill",
"Scan QR Code": "Scan QR Code", "Scan QR Code": "Skann QR Kode",
"Secret": "Hemmelig", "Secret": "Hemmelig",
"Security Key - WebAuthN": "Sikkerhetsnøkkel - WebAuthN", "Security Key - WebAuthN": "Sikkerhetsnøkkel - WebAuthN",
"Select a Device": "Velg en enhet", "Select a Device": "Velg en enhet",
@ -67,6 +68,7 @@
"Use OpenID to verify your identity": "Bruk OpenID for å bekrefte identiteten din", "Use OpenID to verify your identity": "Bruk OpenID for å bekrefte identiteten din",
"Username": "Brukernavn", "Username": "Brukernavn",
"You must open the link from the same device and browser that initiated the registration process": "Du må åpne linken fra samme enhet og nettleser som startet registreringsprosessen", "You must open the link from the same device and browser that initiated the registration process": "Du må åpne linken fra samme enhet og nettleser som startet registreringsprosessen",
"You must view and accept the Privacy Policy before using": "Du må lese og akseptere <0>Personvernerklæringen</0> før du bruker",
"You're being signed out and redirected": "Du blir logget ut og omdirigert", "You're being signed out and redirected": "Du blir logget ut og omdirigert",
"Your supplied password does not meet the password policy requirements": "Ditt angitte passord oppfyller ikke kravene for passord." "Your supplied password does not meet the password policy requirements": "Ditt angitte passord oppfyller ikke kravene for passord."
} }

View File

@ -4,11 +4,11 @@
"Access your group membership": "Tilgang til ditt gruppemedlemskap", "Access your group membership": "Tilgang til ditt gruppemedlemskap",
"Access your profile information": "Få tilgang til profilinformasjonen din", "Access your profile information": "Få tilgang til profilinformasjonen din",
"An email has been sent to your address to complete the process": "En e-post har blitt sendt til din adresse for å fullføre prosessen.", "An email has been sent to your address to complete the process": "En e-post har blitt sendt til din adresse for å fullføre prosessen.",
"Authenticated": "Verifisert", "Authenticated": "Autentisert",
"Automatically refresh these permissions without user interaction": "Oppdater disse tillatelsene automatisk uten brukerinteraksjon", "Automatically refresh these permissions without user interaction": "Oppdater disse tillatelsene automatisk uten brukerinteraksjon",
"Cancel": "Avbryt", "Cancel": "Avbryt",
"Client ID": "Klient-ID: {{client_id}}", "Client ID": "Klient-ID: {{client_id}}",
"Consent Request": "Samtaleforespørsel", "Consent Request": "Samtykkeforespørsel",
"Contact your administrator to register a device": "Kontakt systemansvarlig for å registrere en enhet.", "Contact your administrator to register a device": "Kontakt systemansvarlig for å registrere en enhet.",
"Could not obtain user settings": "Kan ikke hente brukerinnstillinger", "Could not obtain user settings": "Kan ikke hente brukerinnstillinger",
"Deny": "Avslå", "Deny": "Avslå",
@ -16,15 +16,15 @@
"Enter new password": "Skriv inn nytt passord", "Enter new password": "Skriv inn nytt passord",
"Enter one-time password": "Angi engangspassord", "Enter one-time password": "Angi engangspassord",
"Failed to register device, the provided link is expired or has already been used": "Kan ikke registrere enheten, den angitte lenken er utløpt eller allerede er brukt", "Failed to register device, the provided link is expired or has already been used": "Kan ikke registrere enheten, den angitte lenken er utløpt eller allerede er brukt",
"Hi": "Hi", "Hi": "Hei",
"Incorrect username or password": "Ugyldig brukernavn eller passord.", "Incorrect username or password": "Ugyldig brukernavn eller passord.",
"Loading": "Laster", "Loading": "Laster",
"Login": "Innlogging", "Login": "Innlogging",
"Logout": "Logg", "Logout": "Logg ut",
"Lost your device?": "Har du mistet enheten?", "Lost your device?": "Har du mistet enheten?",
"Methods": "Metoder", "Methods": "Metoder",
"Must be at least {{len}} characters in length": "Må være minst {{len}} tegn i lengde", "Must be at least {{len}} characters in length": "Må være minst {{len}} tegn i lengde",
"Must have at least one UPPERCASE letter": "Må ha minst én STORE bokstav", "Must have at least one UPPERCASE letter": "Må ha minst én STOR bokstav",
"Must have at least one lowercase letter": "Må ha minst én liten bokstav", "Must have at least one lowercase letter": "Må ha minst én liten bokstav",
"Must have at least one number": "Må ha minst ett tall", "Must have at least one number": "Må ha minst ett tall",
"Must have at least one special character": "Må ha minst ett spesialtegn", "Must have at least one special character": "Må ha minst ett spesialtegn",
@ -39,6 +39,7 @@
"Password": "Passord", "Password": "Passord",
"Passwords do not match": "Passordene samsvarer ikke.", "Passwords do not match": "Passordene samsvarer ikke.",
"Powered by": "Drives av", "Powered by": "Drives av",
"Privacy Policy": "Personvernerklæring",
"Push Notification": "Push varsling", "Push Notification": "Push varsling",
"Register device": "Registrer enheten", "Register device": "Registrer enheten",
"Register your first device by clicking on the link below": "Registrer din første enhet ved å klikke på lenken nedenfor.", "Register your first device by clicking on the link below": "Registrer din første enhet ved å klikke på lenken nedenfor.",
@ -47,8 +48,8 @@
"Repeat new password": "Gjenta nytt passord", "Repeat new password": "Gjenta nytt passord",
"Reset password": "Tilbakestill passord", "Reset password": "Tilbakestill passord",
"Reset password?": "Tilbakestill passord?", "Reset password?": "Tilbakestill passord?",
"Reset": "Reset", "Reset": "Tilbakestill",
"Scan QR Code": "Scan QR Code", "Scan QR Code": "Skann QR Kode",
"Secret": "Hemmelig", "Secret": "Hemmelig",
"Security Key - WebAuthN": "Sikkerhetsnøkkel - WebAuthN", "Security Key - WebAuthN": "Sikkerhetsnøkkel - WebAuthN",
"Select a Device": "Velg en enhet", "Select a Device": "Velg en enhet",
@ -67,6 +68,7 @@
"Use OpenID to verify your identity": "Bruk OpenID for å bekrefte identiteten din", "Use OpenID to verify your identity": "Bruk OpenID for å bekrefte identiteten din",
"Username": "Brukernavn", "Username": "Brukernavn",
"You must open the link from the same device and browser that initiated the registration process": "Du må åpne linken fra samme enhet og nettleser som startet registreringsprosessen", "You must open the link from the same device and browser that initiated the registration process": "Du må åpne linken fra samme enhet og nettleser som startet registreringsprosessen",
"You must view and accept the Privacy Policy before using": "Du må lese og akseptere <0>Personvernerklæringen</0> før du bruker",
"You're being signed out and redirected": "Du blir logget ut og omdirigert", "You're being signed out and redirected": "Du blir logget ut og omdirigert",
"Your supplied password does not meet the password policy requirements": "Ditt angitte passord oppfyller ikke kravene for passord." "Your supplied password does not meet the password policy requirements": "Ditt angitte passord oppfyller ikke kravene for passord."
} }

View File

@ -1,4 +1,4 @@
FROM golang:1.19.5-alpine FROM golang:1.20.0-alpine
ARG USER_ID ARG USER_ID
ARG GROUP_ID ARG GROUP_ID

View File

@ -87,16 +87,20 @@ static_resources:
authorization_request: authorization_request:
allowed_headers: allowed_headers:
patterns: patterns:
- exact: authorization
- exact: proxy-authorization
- exact: accept - exact: accept
- exact: cookie - exact: cookie
- exact: proxy-authorization
headers_to_add: headers_to_add:
- key: X-Forwarded-Proto - key: X-Forwarded-Proto
value: '%REQ(:SCHEME)%' value: '%REQ(:SCHEME)%'
authorization_response: authorization_response:
allowed_upstream_headers: allowed_upstream_headers:
patterns: patterns:
- exact: authorization
- exact: proxy-authorization
- prefix: remote- - prefix: remote-
- prefix: authelia-
allowed_client_headers: allowed_client_headers:
patterns: patterns:
- exact: set-cookie - exact: set-cookie

View File

@ -82,15 +82,28 @@ backend fe_authelia
server authelia-backend authelia-backend:9091 check backup resolvers docker ssl verify none server authelia-backend authelia-backend:9091 check backup resolvers docker ssl verify none
backend be_httpbin backend be_httpbin
## Pass the special authorization response headers to the protected application.
acl authorization_exist var(req.auth_response_header.authorization) -m found
acl proxy_authorization_exist var(req.auth_response_header.proxy_authorization) -m found
http-request set-header Authorization %[var(req.auth_response_header.authorization)] if authorization_exist
http-request set-header Proxy-Authorization %[var(req.auth_response_header.proxy_authorization)] if proxy_authorization_exist
## Pass the special metadata response headers to the protected application.
acl remote_user_exist var(req.auth_response_header.remote_user) -m found acl remote_user_exist var(req.auth_response_header.remote_user) -m found
acl remote_groups_exist var(req.auth_response_header.remote_groups) -m found acl remote_groups_exist var(req.auth_response_header.remote_groups) -m found
acl remote_name_exist var(req.auth_response_header.remote_name) -m found acl remote_name_exist var(req.auth_response_header.remote_name) -m found
acl remote_email_exist var(req.auth_response_header.remote_email) -m found acl remote_email_exist var(req.auth_response_header.remote_email) -m found
http-request set-header Remote-User %[var(req.auth_response_header.remote_user)] if remote_user_exist http-request set-header Remote-User %[var(req.auth_response_header.remote_user)] if remote_user_exist
http-request set-header Remote-Groups %[var(req.auth_response_header.remote_groups)] if remote_groups_exist http-request set-header Remote-Groups %[var(req.auth_response_header.remote_groups)] if remote_groups_exist
http-request set-header Remote-Name %[var(req.auth_response_header.remote_name)] if remote_name_exist http-request set-header Remote-Name %[var(req.auth_response_header.remote_name)] if remote_name_exist
http-request set-header Remote-Email %[var(req.auth_response_header.remote_email)] if remote_email_exist http-request set-header Remote-Email %[var(req.auth_response_header.remote_email)] if remote_email_exist
## Pass the Set-Cookie response headers to the user.
acl set_cookie_exist var(req.auth_response_header.set_cookie) -m found
http-response set-header Set-Cookie %[var(req.auth_response_header.set_cookie)] if set_cookie_exist
server httpbin-backend httpbin:8000 resolvers docker server httpbin-backend httpbin:8000 resolvers docker
backend be_mail backend be_mail

View File

@ -752,9 +752,9 @@ M.base64 = {}
--- URL safe base64 encoder --- URL safe base64 encoder
-- --
-- Padding ('=') is omited, as permited per RFC -- Padding ('=') is omited, as permited per RFC
-- https://tools.ietf.org/html/rfc4648 -- https://datatracker.ietf.org/doc/html/rfc4648
-- in order to follow JSON Web Signature RFC -- in order to follow JSON Web Signature RFC
-- https://tools.ietf.org/html/rfc7515 -- https://datatracker.ietf.org/doc/html/rfc7515
-- --
-- @param s String (can be binary data) to encode -- @param s String (can be binary data) to encode
-- @param enc Function which implements base64 encoder (e.g. HAProxy base64 fetch) -- @param enc Function which implements base64 encoder (e.g. HAProxy base64 fetch)

View File

@ -12,7 +12,7 @@ services:
- 'traefik.frontend.auth.forward.address=https://authelia-backend:9091/api/authz/forward-auth' - 'traefik.frontend.auth.forward.address=https://authelia-backend:9091/api/authz/forward-auth'
- 'traefik.frontend.auth.forward.tls.insecureSkipVerify=true' - 'traefik.frontend.auth.forward.tls.insecureSkipVerify=true'
- 'traefik.frontend.auth.forward.trustForwardHeader=true' - 'traefik.frontend.auth.forward.trustForwardHeader=true'
- 'traefik.frontend.auth.forward.authResponseHeaders=Remote-User,Remote-Groups,Remote-Name,Remote-Email' - 'traefik.frontend.auth.forward.authResponseHeaders=Authorization,Proxy-Authorization,Remote-User,Remote-Groups,Remote-Email,Remote-Name'
# Traefik 2.x # Traefik 2.x
- 'traefik.enable=true' - 'traefik.enable=true'
- 'traefik.http.routers.httpbin.rule=Host(`public.example.com`) && Path(`/headers`)' - 'traefik.http.routers.httpbin.rule=Host(`public.example.com`) && Path(`/headers`)'

View File

@ -2,7 +2,7 @@
version: '3' version: '3'
services: services:
k3d: k3d:
image: ghcr.io/k3d-io/k3d:5.4.6-dind image: ghcr.io/k3d-io/k3d:5.4.7-dind
volumes: volumes:
- './example/kube:/authelia' - './example/kube:/authelia'
- './example/kube/authelia/configs/configuration.yml:/configmaps/authelia/configuration.yml' - './example/kube/authelia/configs/configuration.yml:/configmaps/authelia/configuration.yml'

View File

@ -9,7 +9,7 @@ services:
- 'traefik.frontend.auth.forward.address=https://authelia-backend:9091/api/authz/forward-auth' # yamllint disable-line rule:line-length - 'traefik.frontend.auth.forward.address=https://authelia-backend:9091/api/authz/forward-auth' # yamllint disable-line rule:line-length
- 'traefik.frontend.auth.forward.tls.insecureSkipVerify=true' - 'traefik.frontend.auth.forward.tls.insecureSkipVerify=true'
- 'traefik.frontend.auth.forward.trustForwardHeader=true' - 'traefik.frontend.auth.forward.trustForwardHeader=true'
- 'traefik.frontend.auth.forward.authResponseHeaders=Remote-User,Remote-Groups,Remote-Name,Remote-Email' - 'traefik.frontend.auth.forward.authResponseHeaders=Authorization,Proxy-Authorization,Remote-User,Remote-Groups,Remote-Email,Remote-Name'
# Traefik 2.x # Traefik 2.x
- 'traefik.enable=true' - 'traefik.enable=true'
- 'traefik.http.routers.protectedapps.rule=Host(`home.example.com`,`public.example.com`,`secure.example.com`,`admin.example.com`,`singlefactor.example.com`)' # yamllint disable-line rule:line-length - 'traefik.http.routers.protectedapps.rule=Host(`home.example.com`,`public.example.com`,`secure.example.com`,`admin.example.com`,`singlefactor.example.com`)' # yamllint disable-line rule:line-length

View File

@ -148,7 +148,7 @@ http {
server_name ~^(public|admin|secure|dev|singlefactor|mx[1-2])(\.mail)?\.(?<basedomain>example([0-9])*\.com)$; server_name ~^(public|admin|secure|dev|singlefactor|mx[1-2])(\.mail)?\.(?<basedomain>example([0-9])*\.com)$;
resolver 127.0.0.11 ipv6=off; resolver 127.0.0.11 ipv6=off;
set $upstream_verify https://authelia-backend:9091/api/authz/auth-request; set $upstream_authelia https://authelia-backend:9091/api/authz/auth-request;
set $upstream_endpoint http://nginx-backend; set $upstream_endpoint http://nginx-backend;
set $upstream_headers http://httpbin:8000/headers; set $upstream_headers http://httpbin:8000/headers;
@ -163,22 +163,38 @@ http {
# Reverse proxy to the backend. It is protected by Authelia by forwarding authorization checks # Reverse proxy to the backend. It is protected by Authelia by forwarding authorization checks
# to the virtual endpoint introduced by nginx and declared in the next block. # to the virtual endpoint introduced by nginx and declared in the next block.
location / { location / {
auth_request /auth_verify; ## Send a subrequest to Authelia to verify if the user is authenticated and has permission to access the resource.
auth_request /authelia;
auth_request_set $user $upstream_http_remote_user; ## Set the $target_url variable based on the original request.
proxy_set_header Remote-User $user; set $target_url $scheme://$http_host$request_uri;
auth_request_set $groups $upstream_http_remote_groups; ## Save the upstream authorization response headers from Authelia to variables.
proxy_set_header Remote-Groups $groups; auth_request_set $authorization $upstream_http_authorization;
auth_request_set $proxy_authorization $upstream_http_proxy_authorization;
auth_request_set $name $upstream_http_remote_name; ## Inject the authorization response headers from the variables into the request made to the backend.
proxy_set_header Remote-Name $name; proxy_set_header Authorization $authorization;
proxy_set_header Proxy-Authorization $proxy_authorization;
auth_request_set $email $upstream_http_remote_email; ## Save the upstream metadata response headers from Authelia to variables.
proxy_set_header Remote-Email $email; auth_request_set $user $upstream_http_remote_user;
auth_request_set $groups $upstream_http_remote_groups;
auth_request_set $name $upstream_http_remote_name;
auth_request_set $email $upstream_http_remote_email;
# Route the request to the correct virtual host in the backend. ## Inject the metadata response headers from the variables into the request made to the backend.
proxy_set_header Host $http_host; proxy_set_header Remote-User $user;
proxy_set_header Remote-Groups $groups;
proxy_set_header Remote-Email $email;
proxy_set_header Remote-Name $name;
## Include the Set-Cookie header if present.
auth_request_set $cookie $upstream_http_set_cookie;
add_header Set-Cookie $cookie;
## If the subreqest returns 200 pass to the backend, if the subrequest returns 401 redirect to the portal.
error_page 401 =302 https://login.$basedomain:8080/?rd=$target_url;
# Authelia relies on Proxy-Authorization header to authenticate in basic auth. # Authelia relies on Proxy-Authorization header to authenticate in basic auth.
# but for the sake of simplicity (because Authorization in supported in most # but for the sake of simplicity (because Authorization in supported in most
@ -186,22 +202,17 @@ http {
# Proxy-Authorization before sending it to Authelia. # Proxy-Authorization before sending it to Authelia.
proxy_set_header Proxy-Authorization $http_authorization; proxy_set_header Proxy-Authorization $http_authorization;
# mitigate HTTPoxy Vulnerability # Route the request to the correct virtual host in the backend.
# https://www.nginx.com/blog/mitigating-the-httpoxy-vulnerability-with-nginx/ proxy_set_header Host $http_host;
proxy_set_header Proxy "";
# Set the `target_url` variable based on the request. It will be used to build the portal
# URL with the correct redirection parameter.
set $target_url $scheme://$http_host$request_uri;
error_page 401 =302 https://login.$basedomain:8080/?rd=$target_url;
proxy_pass $upstream_endpoint; proxy_pass $upstream_endpoint;
} }
# Virtual endpoint forwarding requests to Authelia server. # Virtual endpoint forwarding requests to Authelia server.
location /auth_verify { location /authelia {
internal; ## Essential Proxy Configuration
proxy_set_header X-Real-IP $remote_addr; internal;
proxy_pass $upstream_authelia;
# Provide either X-Original-URL and X-Forwarded-Proto or # Provide either X-Original-URL and X-Forwarded-Proto or
# X-Forwarded-Proto, X-Forwarded-Host and X-Forwarded-URI or both. # X-Forwarded-Proto, X-Forwarded-Host and X-Forwarded-URI or both.
@ -209,39 +220,67 @@ http {
# #
# X-Forwarded-Proto is mandatory since Authelia uses the "trust proxy" option. # X-Forwarded-Proto is mandatory since Authelia uses the "trust proxy" option.
# See https://expressjs.com/en/guide/behind-proxies.html # See https://expressjs.com/en/guide/behind-proxies.html
proxy_set_header X-Original-Method $request_method; proxy_set_header X-Original-Method $request_method;
proxy_set_header X-Original-URL $scheme://$http_host$request_uri; proxy_set_header X-Original-URL $scheme://$http_host$request_uri;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Content-Length "";
proxy_set_header Connection "";
# Authelia can receive Proxy-Authorization to authenticate however most of the clients # Authelia can receive Proxy-Authorization to authenticate however most of the clients
# support Authorization instead. Therefore we rewrite Authorization into Proxy-Authorization. # support Authorization instead. Therefore we rewrite Authorization into Proxy-Authorization.
proxy_set_header Proxy-Authorization $http_authorization; proxy_set_header Proxy-Authorization $http_authorization;
proxy_pass_request_body off; ## Basic Proxy Configuration
proxy_set_header Content-Length ""; proxy_pass_request_body off;
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503; # Timeout if the real server is dead
proxy_redirect http:// $scheme://;
proxy_http_version 1.1;
proxy_cache_bypass $cookie_session;
proxy_no_cache $cookie_session;
proxy_buffers 4 32k;
client_body_buffer_size 128k;
proxy_pass $upstream_verify; ## Advanced Proxy Configuration
send_timeout 5m;
proxy_read_timeout 240;
proxy_send_timeout 240;
proxy_connect_timeout 240;
} }
# Used by suites to test the forwarded users and groups headers produced by Authelia. # Used by suites to test the forwarded users and groups headers produced by Authelia.
location /headers { location /headers {
auth_request /auth_verify; ## Send a subrequest to Authelia to verify if the user is authenticated and has permission to access the resource.
auth_request /authelia;
auth_request_set $user $upstream_http_remote_user; ## Set the $target_url variable based on the original request.
proxy_set_header Remote-User $user; set $target_url $scheme://$http_host$request_uri;
auth_request_set $groups $upstream_http_remote_groups; ## Save the upstream authorization response headers from Authelia to variables.
proxy_set_header Remote-Groups $groups; auth_request_set $authorization $upstream_http_authorization;
auth_request_set $proxy_authorization $upstream_http_proxy_authorization;
auth_request_set $name $upstream_http_remote_name; ## Inject the authorization response headers from the variables into the request made to the backend.
proxy_set_header Remote-Name $name; proxy_set_header Authorization $authorization;
proxy_set_header Proxy-Authorization $proxy_authorization;
auth_request_set $email $upstream_http_remote_email; ## Save the upstream metadata response headers from Authelia to variables.
proxy_set_header Remote-Email $email; auth_request_set $user $upstream_http_remote_user;
auth_request_set $groups $upstream_http_remote_groups;
auth_request_set $name $upstream_http_remote_name;
auth_request_set $email $upstream_http_remote_email;
set $target_url $scheme://$http_host$request_uri; ## Inject the metadata response headers from the variables into the request made to the backend.
error_page 401 =302 https://login.$basedomain:8080/?rd=$target_url; proxy_set_header Remote-User $user;
proxy_set_header Remote-Groups $groups;
proxy_set_header Remote-Email $email;
proxy_set_header Remote-Name $name;
## Include the Set-Cookie header if present.
auth_request_set $cookie $upstream_http_set_cookie;
add_header Set-Cookie $cookie;
## If the subreqest returns 200 pass to the backend, if the subrequest returns 401 redirect to the portal.
error_page 401 =302 https://login.$basedomain:8080/?rd=$target_url;
proxy_pass $upstream_headers; proxy_pass $upstream_headers;
} }
@ -253,7 +292,7 @@ http {
server_name ~^oidc(-public)?\.(?<basedomain>example([0-9])*\.com)$; server_name ~^oidc(-public)?\.(?<basedomain>example([0-9])*\.com)$;
resolver 127.0.0.11 ipv6=off; resolver 127.0.0.11 ipv6=off;
set $upstream_verify https://authelia-backend:9091/api/authz/auth-request; set $upstream_authelia https://authelia-backend:9091/api/authz/auth-request;
set $upstream_endpoint http://oidc-client:8080; set $upstream_endpoint http://oidc-client:8080;
ssl_certificate /etc/ssl/server.cert; ssl_certificate /etc/ssl/server.cert;
@ -267,27 +306,50 @@ http {
# Reverse proxy to the backend. It is protected by Authelia by forwarding authorization checks # Reverse proxy to the backend. It is protected by Authelia by forwarding authorization checks
# to the virtual endpoint introduced by nginx and declared in the next block. # to the virtual endpoint introduced by nginx and declared in the next block.
location / { location / {
auth_request /auth_verify; ## Send a subrequest to Authelia to verify if the user is authenticated and has permission to access the resource.
auth_request /authelia;
## Set the $target_url variable based on the original request.
set $target_url $scheme://$http_host$request_uri;
## Save the upstream authorization response headers from Authelia to variables.
auth_request_set $authorization $upstream_http_authorization;
auth_request_set $proxy_authorization $upstream_http_proxy_authorization;
## Inject the authorization response headers from the variables into the request made to the backend.
proxy_set_header Authorization $authorization;
proxy_set_header Proxy-Authorization $proxy_authorization;
## Save the upstream metadata response headers from Authelia to variables.
auth_request_set $user $upstream_http_remote_user;
auth_request_set $groups $upstream_http_remote_groups;
auth_request_set $name $upstream_http_remote_name;
auth_request_set $email $upstream_http_remote_email;
## Inject the metadata response headers from the variables into the request made to the backend.
proxy_set_header Remote-User $user;
proxy_set_header Remote-Groups $groups;
proxy_set_header Remote-Email $email;
proxy_set_header Remote-Name $name;
## Include the Set-Cookie header if present.
auth_request_set $cookie $upstream_http_set_cookie;
add_header Set-Cookie $cookie;
## If the subreqest returns 200 pass to the backend, if the subrequest returns 401 redirect to the portal.
error_page 401 =302 https://login.$basedomain:8080/?rd=$target_url;
# Route the request to the correct virtual host in the backend. # Route the request to the correct virtual host in the backend.
proxy_set_header Host $http_host; proxy_set_header Host $http_host;
# mitigate HTTPoxy Vulnerability
# https://www.nginx.com/blog/mitigating-the-httpoxy-vulnerability-with-nginx/
proxy_set_header Proxy "";
# Set the `target_url` variable based on the request. It will be used to build the portal
# URL with the correct redirection parameter.
set $target_url $scheme://$http_host$request_uri;
error_page 401 =302 https://login.$basedomain:8080/?rd=$target_url;
proxy_pass $upstream_endpoint; proxy_pass $upstream_endpoint;
} }
# Virtual endpoint forwarding requests to Authelia server. # Virtual endpoint forwarding requests to Authelia server.
location /auth_verify { location /authelia {
internal; ## Essential Proxy Configuration
proxy_set_header X-Real-IP $remote_addr; internal;
proxy_pass $upstream_authelia;
# Provide either X-Original-URL and X-Forwarded-Proto or # Provide either X-Original-URL and X-Forwarded-Proto or
# X-Forwarded-Proto, X-Forwarded-Host and X-Forwarded-URI or both. # X-Forwarded-Proto, X-Forwarded-Host and X-Forwarded-URI or both.
@ -295,19 +357,31 @@ http {
# #
# X-Forwarded-Proto is mandatory since Authelia uses the "trust proxy" option. # X-Forwarded-Proto is mandatory since Authelia uses the "trust proxy" option.
# See https://expressjs.com/en/guide/behind-proxies.html # See https://expressjs.com/en/guide/behind-proxies.html
proxy_set_header X-Original-Method $request_method; proxy_set_header X-Original-Method $request_method;
proxy_set_header X-Original-URL $scheme://$http_host$request_uri; proxy_set_header X-Original-URL $scheme://$http_host$request_uri;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Content-Length "";
proxy_set_header Connection "";
# Authelia can receive Proxy-Authorization to authenticate however most of the clients # Authelia can receive Proxy-Authorization to authenticate however most of the clients
# support Authorization instead. Therefore we rewrite Authorization into Proxy-Authorization. # support Authorization instead. Therefore we rewrite Authorization into Proxy-Authorization.
proxy_set_header Proxy-Authorization $http_authorization; proxy_set_header Proxy-Authorization $http_authorization;
proxy_pass_request_body off; ## Basic Proxy Configuration
proxy_set_header Content-Length ""; proxy_pass_request_body off;
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503; # Timeout if the real server is dead
proxy_redirect http:// $scheme://;
proxy_http_version 1.1;
proxy_cache_bypass $cookie_session;
proxy_no_cache $cookie_session;
proxy_buffers 4 32k;
client_body_buffer_size 128k;
proxy_pass $upstream_verify; ## Advanced Proxy Configuration
send_timeout 5m;
proxy_read_timeout 240;
proxy_send_timeout 240;
proxy_connect_timeout 240;
} }
} }

View File

@ -1617,7 +1617,7 @@ notify-keyspace-events ""
############################### GOPHER SERVER ################################# ############################### GOPHER SERVER #################################
# Redis contains an implementation of the Gopher protocol, as specified in # Redis contains an implementation of the Gopher protocol, as specified in
# the RFC 1436 (https://www.ietf.org/rfc/rfc1436.txt). # the RFC 1436 (https://datatracker.ietf.org/doc/html/rfc1436).
# #
# The Gopher protocol was very popular in the late '90s. It is an alternative # The Gopher protocol was very popular in the late '90s. It is an alternative
# to the web, and the implementation both server and client side is so simple # to the web, and the implementation both server and client side is so simple

View File

@ -1617,7 +1617,7 @@ notify-keyspace-events ""
############################### GOPHER SERVER ################################# ############################### GOPHER SERVER #################################
# Redis contains an implementation of the Gopher protocol, as specified in # Redis contains an implementation of the Gopher protocol, as specified in
# the RFC 1436 (https://www.ietf.org/rfc/rfc1436.txt). # the RFC 1436 (https://datatracker.ietf.org/doc/html/rfc1436).
# #
# The Gopher protocol was very popular in the late '90s. It is an alternative # The Gopher protocol was very popular in the late '90s. It is an alternative
# to the web, and the implementation both server and client side is so simple # to the web, and the implementation both server and client side is so simple

View File

@ -15,7 +15,7 @@ services:
- 'traefik.http.middlewares.authelia.forwardauth.address=https://authelia-backend:9091${PathPrefix}/api/authz/forward-auth' # yamllint disable-line rule:line-length - 'traefik.http.middlewares.authelia.forwardauth.address=https://authelia-backend:9091${PathPrefix}/api/authz/forward-auth' # yamllint disable-line rule:line-length
- 'traefik.http.middlewares.authelia.forwardauth.tls.insecureSkipVerify=true' - 'traefik.http.middlewares.authelia.forwardauth.tls.insecureSkipVerify=true'
- 'traefik.http.middlewares.authelia.forwardauth.trustForwardHeader=true' - 'traefik.http.middlewares.authelia.forwardauth.trustForwardHeader=true'
- 'traefik.http.middlewares.authelia.forwardauth.authResponseHeaders=Remote-User, Remote-Groups, Remote-Name, Remote-Email' # yamllint disable-line rule:line-length - 'traefik.http.middlewares.authelia.forwardauth.authResponseHeaders=Authorization,Proxy-Authorization,Remote-User,Remote-Groups,Remote-Email,Remote-Name' # yamllint disable-line rule:line-length
command: command:
- '--accesslog=true' - '--accesslog=true'
- '--api' - '--api'

View File

@ -26,11 +26,11 @@
"@fortawesome/free-solid-svg-icons": "6.2.1", "@fortawesome/free-solid-svg-icons": "6.2.1",
"@fortawesome/react-fontawesome": "0.2.0", "@fortawesome/react-fontawesome": "0.2.0",
"@mui/icons-material": "5.11.0", "@mui/icons-material": "5.11.0",
"@mui/material": "5.11.6", "@mui/material": "5.11.7",
"@mui/styles": "5.11.2", "@mui/styles": "5.11.7",
"@simplewebauthn/browser": "7.0.1", "@simplewebauthn/browser": "7.0.1",
"@simplewebauthn/typescript-types": "7.0.0", "@simplewebauthn/typescript-types": "7.0.0",
"axios": "1.2.6", "axios": "1.3.2",
"broadcast-channel": "4.20.2", "broadcast-channel": "4.20.2",
"classnames": "2.3.2", "classnames": "2.3.2",
"i18next": "22.4.9", "i18next": "22.4.9",
@ -39,7 +39,7 @@
"qrcode.react": "3.1.0", "qrcode.react": "3.1.0",
"react": "18.2.0", "react": "18.2.0",
"react-dom": "18.2.0", "react-dom": "18.2.0",
"react-i18next": "12.1.4", "react-i18next": "12.1.5",
"react-loading": "2.0.3", "react-loading": "2.0.3",
"react-router-dom": "6.8.0", "react-router-dom": "6.8.0",
"react18-input-otp": "1.1.2", "react18-input-otp": "1.1.2",
@ -82,7 +82,8 @@
"^.+\\.(css|png|svg)$": "jest-transform-stub" "^.+\\.(css|png|svg)$": "jest-transform-stub"
}, },
"transformIgnorePatterns": [ "transformIgnorePatterns": [
"[/\\\\]node_modules[/\\\\].+\\.(js|jsx|mjs|cjs|ts|tsx)$" "[/\\\\]node_modules[/\\\\].+\\.(js|jsx|mjs|cjs|ts|tsx)$",
"[/\\\\]node_modules[/\\\\](?!(@simplewebauthn)[/\\\\])"
], ],
"moduleNameMapper": { "moduleNameMapper": {
"^@root/(.*)$": [ "^@root/(.*)$": [
@ -150,14 +151,14 @@
"@testing-library/jest-dom": "5.16.5", "@testing-library/jest-dom": "5.16.5",
"@testing-library/react": "13.4.0", "@testing-library/react": "13.4.0",
"@types/jest": "29.4.0", "@types/jest": "29.4.0",
"@types/node": "18.11.18", "@types/node": "18.11.19",
"@types/qrcode.react": "1.0.2", "@types/qrcode.react": "1.0.2",
"@types/react": "18.0.27", "@types/react": "18.0.27",
"@types/react-dom": "18.0.10", "@types/react-dom": "18.0.10",
"@types/zxcvbn": "4.4.1", "@types/zxcvbn": "4.4.1",
"@typescript-eslint/eslint-plugin": "5.49.0", "@typescript-eslint/eslint-plugin": "5.50.0",
"@typescript-eslint/parser": "5.49.0", "@typescript-eslint/parser": "5.50.0",
"@vitejs/plugin-react": "3.0.1", "@vitejs/plugin-react": "3.1.0",
"esbuild": "0.17.5", "esbuild": "0.17.5",
"esbuild-jest": "0.5.0", "esbuild-jest": "0.5.0",
"eslint": "8.33.0", "eslint": "8.33.0",
@ -177,8 +178,8 @@
"jest-watch-typeahead": "2.2.2", "jest-watch-typeahead": "2.2.2",
"prettier": "2.8.3", "prettier": "2.8.3",
"react-test-renderer": "18.2.0", "react-test-renderer": "18.2.0",
"typescript": "4.9.4", "typescript": "4.9.5",
"vite": "4.0.4", "vite": "4.1.1",
"vite-plugin-eslint": "1.8.1", "vite-plugin-eslint": "1.8.1",
"vite-plugin-istanbul": "4.0.0", "vite-plugin-istanbul": "4.0.0",
"vite-plugin-svgr": "2.4.0", "vite-plugin-svgr": "2.4.0",

File diff suppressed because it is too large Load Diff