Merge remote-tracking branch 'origin/master' into feat-settings-ui
# Conflicts: # web/package.json # web/pnpm-lock.yamlfeat-otp-verification
commit
9e5aa1c1a9
|
@ -11,6 +11,10 @@ insert_final_newline = true
|
|||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
[{.github/pre-commit,.github/required-apps,.github/commit-msg}]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
[.buildkite/hooks/**]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#!/bin/sh
|
||||
|
||||
. "$(dirname "$0")/_/husky.sh"
|
||||
. "$(dirname "$0")/required-apps"
|
||||
|
||||
cd web && ${PMGR} commitlint --edit "$1"
|
||||
cd web && ${PMGR_EXEC} commitlint --edit "$1"
|
||||
|
|
|
@ -8,4 +8,4 @@ fi
|
|||
. "$(dirname "$0")/required-apps"
|
||||
|
||||
golangci-lint run -v --fix && \
|
||||
cd web && "${PMGR}" lint
|
||||
cd web && ${PMGR_RUN} lint
|
||||
|
|
|
@ -1,19 +1,20 @@
|
|||
#!/bin/sh
|
||||
|
||||
export PMGR=pnpm
|
||||
|
||||
if [ ! -x "$(command -v golangci-lint)" ]; then
|
||||
echo "You must install golangci-lint."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -x "$(command -v pnpm)" ]; then
|
||||
export PMGR=yarn
|
||||
if [ ! -x "$(command -v yarn)" ]; then
|
||||
export PMGR=npm
|
||||
if [ ! -x "$(command -v npm)" ]; then
|
||||
echo "You must install a node package manager."
|
||||
if [ -x "$(command -v pnpm)" ]; then
|
||||
export PMGR_RUN="pnpm"
|
||||
export PMGR_EXEC="pnpm"
|
||||
elif [ -x "$(command -v yarn)" ]; then
|
||||
export PMGR_RUN="yarn run"
|
||||
export PMGR_EXEC="yarn dlx"
|
||||
elif [ -x "$(command -v npm)" ]; then
|
||||
export PMGR_RUN="npm run"
|
||||
export PMGR_EXEC="npx"
|
||||
else
|
||||
echo "You must install a node package manager (pnpm, yarn, or npm)."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
|
|
@ -15,7 +15,7 @@ RUN yarn global add pnpm && \
|
|||
# =======================================
|
||||
# ===== 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
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ RUN yarn install --frozen-lockfile && yarn build
|
|||
# =======================================
|
||||
# ===== 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
|
||||
|
||||
|
|
|
@ -855,7 +855,7 @@ paths:
|
|||
summary: OAuth 2.0 Authorization Server Metadata
|
||||
description: >
|
||||
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:
|
||||
"200":
|
||||
description: OK
|
||||
|
@ -2878,8 +2878,8 @@ components:
|
|||
description: >
|
||||
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:
|
||||
JWS: https://datatracker.ietf.org/doc/html/rfc7515 JWA: https://datatracker.ietf.org/doc/html/rfc7518 JWT:
|
||||
https://datatracker.ietf.org/doc/html/rfc7519
|
||||
JWS: https://datatracker.ietf.org/doc/html/rfc7515 JWA: https://datatracker.ietf.org/doc/html/rfc7518
|
||||
JWT: https://datatracker.ietf.org/doc/html/rfc7519
|
||||
type: array
|
||||
example: ["none", "RS256"]
|
||||
items:
|
||||
|
|
|
@ -426,7 +426,7 @@ authentication_backend:
|
|||
## 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
|
||||
## 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
|
||||
|
||||
## The additional_users_dn is prefixed to base_dn and delimited by a comma when searching for users.
|
||||
|
|
|
@ -1 +1 @@
|
|||
canonifyURLs = false
|
||||
baseurl = "https://authelia-staging.netlify.app/"
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
canonifyURLs = false
|
|
@ -1,2 +1 @@
|
|||
canonifyURLs = false
|
||||
baseurl = "https://authelia-staging.netlify.app/"
|
||||
|
|
|
@ -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].
|
||||
|
||||
[Argon2]: https://www.rfc-editor.org/rfc/rfc9106.html
|
||||
[Argon2]: https://datatracker.ietf.org/doc/html/rfc9106
|
||||
[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
|
||||
[Bcrypt]: https://en.wikipedia.org/wiki/Bcrypt
|
||||
|
|
|
@ -316,4 +316,4 @@ for your users.
|
|||
|
||||
[username attribute]: #usernameattribute
|
||||
[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
|
||||
|
|
|
@ -119,7 +119,7 @@ identity_providers:
|
|||
clients:
|
||||
- id: myapp
|
||||
description: My Application
|
||||
secret: '$plaintext$this_is_a_secret'
|
||||
secret: '$pbkdf2-sha512$310000$c8p78n7pUMln0jzvd4aK4Q$JNRBzwAo0ek5qKn50cFzzvE9RXV88h1wJn5KGiHrD0YKtZaR/nCb2CJPOsKaPK0hjf.9yHxzQGZziziccp6Yng' # The digest of 'insecure_secret'.
|
||||
sector_identifier: ''
|
||||
public: false
|
||||
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)
|
||||
as per [RFC7517].
|
||||
|
||||
[RFC7517]: https://www.rfc-editor.org/rfc/rfc7517
|
||||
[x5c]: https://www.rfc-editor.org/rfc/rfc7517#section-4.7
|
||||
[x5t]: https://www.rfc-editor.org/rfc/rfc7517#section-4.8
|
||||
[RFC7517]: https://datatracker.ietf.org/doc/html/rfc7517
|
||||
[x5c]: https://datatracker.ietf.org/doc/html/rfc7517#section-4.7
|
||||
[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
|
||||
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" >}}
|
||||
|
||||
[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`.
|
||||
|
||||
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
|
||||
[OpenID Connect 1.0]: https://openid.net/connect/
|
||||
[JWT]: https://www.rfc-editor.org/rfc/rfc7519.html
|
||||
[RFC6234]: https://www.rfc-editor.org/rfc/rfc6234.html
|
||||
[RFC4648]: https://www.rfc-editor.org/rfc/rfc4648.html
|
||||
[RFC7468]: https://www.rfc-editor.org/rfc/rfc7468.html
|
||||
[RFC6749 Section 2.1]: https://www.rfc-editor.org/rfc/rfc6749.html#section-2.1
|
||||
[PKCE]: https://www.rfc-editor.org/rfc/rfc7636.html
|
||||
[JWT]: https://datatracker.ietf.org/doc/html/rfc7519
|
||||
[RFC6234]: https://datatracker.ietf.org/doc/html/rfc6234
|
||||
[RFC4648]: https://datatracker.ietf.org/doc/html/rfc4648
|
||||
[RFC7468]: https://datatracker.ietf.org/doc/html/rfc7468
|
||||
[RFC6749 Section 2.1]: https://datatracker.ietf.org/doc/html/rfc6749#section-2.1
|
||||
[PKCE]: https://datatracker.ietf.org/doc/html/rfc7636
|
||||
[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
|
||||
[Pairwise Identifier Algorithm]: https://openid.net/specs/openid-connect-core-1_0.html#PairwiseAlg
|
||||
|
|
|
@ -164,7 +164,7 @@ characters and the user password is changed to this value.
|
|||
{{< 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
|
||||
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
|
||||
* John Smith <jsmith@domain.com>
|
||||
|
|
|
@ -154,7 +154,7 @@ The value must be one or more certificates encoded in the DER base64 ([RFC4648])
|
|||
|
||||
### 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__
|
||||
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.
|
||||
|
||||
[RFC4648]: https://datatracker.ietf.org/doc/html/rfc4648
|
||||
|
||||
## Server Buffers
|
||||
|
||||
### read
|
||||
|
|
|
@ -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
|
||||
exports.
|
||||
|
||||
[RFC4226]: https://www.rfc-editor.org/rfc/rfc4226.html
|
||||
[RFC6238]: https://www.rfc-editor.org/rfc/rfc6238.html
|
||||
[RFC4226]: https://datatracker.ietf.org/doc/html/rfc4226
|
||||
[RFC6238]: https://datatracker.ietf.org/doc/html/rfc6238
|
||||
|
|
|
@ -588,8 +588,8 @@ The match type `Equals` matches if the value extracted from the pattern is equal
|
|||
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
|
||||
should not be compared in a case-sensitive way as per the [RFC4343](https://www.rfc-editor.org/rfc/rfc4343.html)
|
||||
abstract and [RFC3986 Section 3.2.2](https://www.rfc-editor.org/rfc/rfc3986#section-3.2.2).
|
||||
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://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
|
||||
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
|
||||
```
|
||||
|
||||
[RFC7231]: https://www.rfc-editor.org/rfc/rfc7231.html
|
||||
[RFC5789]: https://www.rfc-editor.org/rfc/rfc5789.html
|
||||
[RFC4918]: https://www.rfc-editor.org/rfc/rfc4918.html
|
||||
[RFC7231]: https://datatracker.ietf.org/doc/html/rfc7231
|
||||
[RFC5789]: https://datatracker.ietf.org/doc/html/rfc5789
|
||||
[RFC4918]: https://datatracker.ietf.org/doc/html/rfc4918
|
||||
|
|
|
@ -15,11 +15,8 @@ aliases:
|
|||
- /docs/configuration/session/
|
||||
---
|
||||
|
||||
__Authelia__ relies on session cookies to authenticate users. When the user visits a website of the protected domain
|
||||
`example.com` for the first time, Authelia detects that there is no cookie for that user. Consequently, Authelia
|
||||
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.
|
||||
__Authelia__ relies on session cookies to authorize user access to various protected websites. This section configures
|
||||
the session cookie behaviour and the domains which Authelia can service authorization requests for.
|
||||
|
||||
## Configuration
|
||||
|
||||
|
@ -34,8 +31,9 @@ session:
|
|||
remember_me: 1M
|
||||
|
||||
cookies:
|
||||
- name: authelia_session
|
||||
domain: example.com
|
||||
- domain: example.com
|
||||
authelia_url: https://auth.example.com
|
||||
name: authelia_session
|
||||
same_site: lax
|
||||
inactivity: 5m
|
||||
expiration: 1h
|
||||
|
@ -75,10 +73,8 @@ characters.
|
|||
|
||||
{{< confkey type="string" required="no" >}}
|
||||
|
||||
_**Deprecation Notice:** This option is deprecated. See the [cookies](#cookies) section 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.
|
||||
_**Deprecation Notice:** This option is deprecated. See the [cookies](#cookies) section and specifically the
|
||||
[cookies domain](#domain-1) option instead._
|
||||
|
||||
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.
|
||||
|
@ -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
|
||||
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
|
||||
|
||||
{{< 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
|
||||
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`.
|
||||
*__Important Note:__ Browsers have rules regarding which cookie domains a website can write. In particular this.*
|
||||
|
||||
Please note most good DynamicDNS solutions fall into a specially protected group of domains and browsers do not allow
|
||||
you to write cookies for the root domain. i.e. if you have been assigned `john.duckdns.org` you can't use `duckdns.org`
|
||||
for the domain value as browsers will not allow `john.duckdns.org` to read or write cookies for `duckdns.org`.
|
||||
The domain the session cookie is assigned to protect. This must be the same as the domain Authelia is served on or the
|
||||
root of the domain, and consequently if the [authelia_url](#authelia_url) is configured must be able to read and write
|
||||
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
|
||||
|
||||
|
@ -160,10 +153,24 @@ that the `authelia_url` option is ineffectual for both NGINX and HAProxy, or any
|
|||
implementation.*
|
||||
|
||||
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.
|
||||
|
||||
#### 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
|
||||
|
||||
{{< confkey type="string" required="no" >}}
|
||||
|
|
|
@ -21,7 +21,7 @@ In order to build and contribute to __Authelia__, you need to make sure the foll
|
|||
* General:
|
||||
* [git]
|
||||
* Backend Development:
|
||||
* [go] *(v1.19 or greater)*
|
||||
* [go] *(v1.20 or greater)*
|
||||
* [gcc]
|
||||
* Frontend Development
|
||||
* [Node.js] *(v18 or greater)*
|
||||
|
|
|
@ -22,14 +22,7 @@ community: true
|
|||
|
||||
## Before You Begin
|
||||
|
||||
### Common Notes
|
||||
|
||||
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
|
||||
{{% oidc-common %}}
|
||||
|
||||
### Assumptions
|
||||
|
||||
|
@ -38,7 +31,7 @@ This example makes the following assumptions:
|
|||
* __Application Root URL:__ `https://guacamole.example.com`
|
||||
* __Authelia Root URL:__ `https://auth.example.com`
|
||||
* __Client ID:__ `guacamole`
|
||||
* __Client Secret:__ `guacamole_client_secret`
|
||||
* __Client Secret:__ `insecure_secret`
|
||||
|
||||
## Configuration
|
||||
|
||||
|
@ -66,7 +59,7 @@ The following YAML configuration is an example __Authelia__
|
|||
```yaml
|
||||
- id: guacamole
|
||||
description: Apache Guacamole
|
||||
secret: '$plaintext$guacamole_client_secret'
|
||||
secret: '$pbkdf2-sha512$310000$c8p78n7pUMln0jzvd4aK4Q$JNRBzwAo0ek5qKn50cFzzvE9RXV88h1wJn5KGiHrD0YKtZaR/nCb2CJPOsKaPK0hjf.9yHxzQGZziziccp6Yng' # The digest of 'insecure_secret'.
|
||||
public: false
|
||||
authorization_policy: two_factor
|
||||
redirect_uris:
|
||||
|
|
|
@ -22,14 +22,7 @@ community: true
|
|||
|
||||
## Before You Begin
|
||||
|
||||
### Common Notes
|
||||
|
||||
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
|
||||
{{% oidc-common %}}
|
||||
|
||||
### Assumptions
|
||||
|
||||
|
@ -38,7 +31,7 @@ This example makes the following assumptions:
|
|||
* __Application Root URL:__ `https://argocd.example.com`
|
||||
* __Authelia Root URL:__ `https://auth.example.com`
|
||||
* __Client ID:__ `argocd`
|
||||
* __Client Secret:__ `argocd_client_secret`
|
||||
* __Client Secret:__ `insecure_secret`
|
||||
* __CLI Client ID:__ `argocd-cli`
|
||||
|
||||
## Configuration
|
||||
|
@ -51,7 +44,7 @@ To configure [Argo CD] to utilize Authelia as an [OpenID Connect 1.0] Provider u
|
|||
name: Authelia
|
||||
issuer: https://auth.example.com
|
||||
clientID: argocd
|
||||
clientSecret: argocd_client_secret
|
||||
clientSecret: insecure_secret
|
||||
cliClientID: argocd-cli
|
||||
requestedScopes:
|
||||
- openid
|
||||
|
@ -69,7 +62,7 @@ which will operate with the above example:
|
|||
```yaml
|
||||
- id: argocd
|
||||
description: Argo CD
|
||||
secret: '$plaintext$argocd_client_secret'
|
||||
secret: '$pbkdf2-sha512$310000$c8p78n7pUMln0jzvd4aK4Q$JNRBzwAo0ek5qKn50cFzzvE9RXV88h1wJn5KGiHrD0YKtZaR/nCb2CJPOsKaPK0hjf.9yHxzQGZziziccp6Yng' # The digest of 'insecure_secret'.
|
||||
public: false
|
||||
authorization_policy: two_factor
|
||||
redirect_uris:
|
||||
|
|
|
@ -22,14 +22,7 @@ community: true
|
|||
|
||||
## Before You Begin
|
||||
|
||||
### Common Notes
|
||||
|
||||
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
|
||||
{{% oidc-common %}}
|
||||
|
||||
### Assumptions
|
||||
|
||||
|
@ -38,13 +31,13 @@ This example makes the following assumptions:
|
|||
* __Application Root URL:__ `https://bookstack.example.com`
|
||||
* __Authelia Root URL:__ `https://auth.example.com`
|
||||
* __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
|
||||
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.*
|
||||
|
||||
[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
|
||||
|
||||
|
@ -58,7 +51,7 @@ To configure [BookStack] to utilize Authelia as an [OpenID Connect 1.0] Provider
|
|||
2. OIDC_NAME: `Authelia`
|
||||
3. OIDC_DISPLAY_NAME_CLAIMS: `name`
|
||||
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`
|
||||
7. OIDC_ISSUER_DISCOVER: `true`
|
||||
|
||||
|
@ -71,7 +64,7 @@ which will operate with the above example:
|
|||
```yaml
|
||||
- id: bookstack
|
||||
description: BookStack
|
||||
secret: '$plaintext$bookstack_client_secret'
|
||||
secret: '$pbkdf2-sha512$310000$c8p78n7pUMln0jzvd4aK4Q$JNRBzwAo0ek5qKn50cFzzvE9RXV88h1wJn5KGiHrD0YKtZaR/nCb2CJPOsKaPK0hjf.9yHxzQGZziziccp6Yng' # The digest of 'insecure_secret'.
|
||||
public: false
|
||||
authorization_policy: two_factor
|
||||
redirect_uris:
|
||||
|
|
|
@ -20,14 +20,7 @@ community: true
|
|||
|
||||
## Before You Begin
|
||||
|
||||
### Common Notes
|
||||
|
||||
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
|
||||
{{% oidc-common %}}
|
||||
|
||||
### Assumptions
|
||||
|
||||
|
@ -36,13 +29,13 @@ This example makes the following assumptions:
|
|||
* __Cloudflare Team Name:__ `example-team`
|
||||
* __Authelia Root URL:__ `https://auth.example.com`
|
||||
* __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
|
||||
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.*
|
||||
|
||||
[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
|
||||
|
||||
|
@ -62,7 +55,7 @@ To configure [Cloudflare Zero Trust] to utilize Authelia as an [OpenID Connect 1
|
|||
6. Set the following values:
|
||||
1. Name: `Authelia`
|
||||
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`
|
||||
5. Token URL: `https://auth.example.com/api/oidc/token`
|
||||
6. Certificate URL: `https://auth.example.com/jwks.json`
|
||||
|
@ -79,7 +72,7 @@ which will operate with the above example:
|
|||
```yaml
|
||||
- id: cloudflare
|
||||
description: Cloudflare ZeroTrust
|
||||
secret: '$plaintext$cloudflare_client_secret'
|
||||
secret: '$pbkdf2-sha512$310000$c8p78n7pUMln0jzvd4aK4Q$JNRBzwAo0ek5qKn50cFzzvE9RXV88h1wJn5KGiHrD0YKtZaR/nCb2CJPOsKaPK0hjf.9yHxzQGZziziccp6Yng' # The digest of 'insecure_secret'.
|
||||
public: false
|
||||
authorization_policy: two_factor
|
||||
redirect_uris:
|
||||
|
|
|
@ -22,14 +22,7 @@ community: true
|
|||
|
||||
## Before You Begin
|
||||
|
||||
### Common Notes
|
||||
|
||||
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
|
||||
{{% oidc-common %}}
|
||||
|
||||
### Assumptions
|
||||
|
||||
|
@ -38,7 +31,7 @@ This example makes the following assumptions:
|
|||
* __Application Root URL:__ `https://gitea.example.com`
|
||||
* __Authelia Root URL:__ `https://auth.example.com`
|
||||
* __Client ID:__ `gitea`
|
||||
* __Client Secret:__ `gitea_client_secret`
|
||||
* __Client Secret:__ `insecure_secret`
|
||||
|
||||
## Configuration
|
||||
|
||||
|
@ -54,7 +47,7 @@ To configure [Gitea] to utilize Authelia as an [OpenID Connect 1.0] Provider:
|
|||
1. Authentication Name: `authelia`
|
||||
2. OAuth2 Provider: `OpenID Connect`
|
||||
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`
|
||||
|
||||
{{< figure src="gitea.png" alt="Gitea" width="300" >}}
|
||||
|
@ -86,7 +79,7 @@ will operate with the above example:
|
|||
```yaml
|
||||
- id: gitea
|
||||
description: Gitea
|
||||
secret: '$plaintext$gitea_client_secret'
|
||||
secret: '$pbkdf2-sha512$310000$c8p78n7pUMln0jzvd4aK4Q$JNRBzwAo0ek5qKn50cFzzvE9RXV88h1wJn5KGiHrD0YKtZaR/nCb2CJPOsKaPK0hjf.9yHxzQGZziziccp6Yng' # The digest of 'insecure_secret'.
|
||||
public: false
|
||||
authorization_policy: two_factor
|
||||
redirect_uris:
|
||||
|
|
|
@ -22,14 +22,7 @@ community: true
|
|||
|
||||
## Before You Begin
|
||||
|
||||
### Common Notes
|
||||
|
||||
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
|
||||
{{% oidc-common %}}
|
||||
|
||||
### Assumptions
|
||||
|
||||
|
@ -38,7 +31,7 @@ This example makes the following assumptions:
|
|||
* __Application Root URL:__ `https://gitlab.example.com`
|
||||
* __Authelia Root URL:__ `https://auth.example.com`
|
||||
* __Client ID:__ `gitlab`
|
||||
* __Client Secret:__ `gitlab_client_secret`
|
||||
* __Client Secret:__ `insecure_secret`
|
||||
|
||||
## Configuration
|
||||
|
||||
|
@ -65,7 +58,7 @@ gitlab_rails['omniauth_providers'] = [
|
|||
send_scope_to_token_endpoint: "false",
|
||||
client_options: {
|
||||
identifier: "gitlab",
|
||||
secret: "gitlab_client_secret",
|
||||
secret: "insecure_secret",
|
||||
redirect_uri: "https://gitlab.example.com/users/auth/openid_connect/callback"
|
||||
}
|
||||
}
|
||||
|
@ -82,7 +75,7 @@ which will operate with the above example:
|
|||
```yaml
|
||||
- id: gitlab
|
||||
description: GitLab
|
||||
secret: '$plaintext$gitlab_client_secret'
|
||||
secret: '$pbkdf2-sha512$310000$c8p78n7pUMln0jzvd4aK4Q$JNRBzwAo0ek5qKn50cFzzvE9RXV88h1wJn5KGiHrD0YKtZaR/nCb2CJPOsKaPK0hjf.9yHxzQGZziziccp6Yng' # The digest of 'insecure_secret'.
|
||||
public: false
|
||||
authorization_policy: two_factor
|
||||
redirect_uris:
|
||||
|
|
|
@ -22,14 +22,7 @@ community: true
|
|||
|
||||
## Before You Begin
|
||||
|
||||
### Common Notes
|
||||
|
||||
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
|
||||
{{% oidc-common %}}
|
||||
|
||||
### Assumptions
|
||||
|
||||
|
@ -38,7 +31,7 @@ This example makes the following assumptions:
|
|||
* __Application Root URL:__ `https://grafana.example.com`
|
||||
* __Authelia Root URL:__ `https://auth.example.com`
|
||||
* __Client ID:__ `grafana`
|
||||
* __Client Secret:__ `grafana_client_secret`
|
||||
* __Client Secret:__ `insecure_secret`
|
||||
|
||||
## Configuration
|
||||
|
||||
|
@ -58,7 +51,7 @@ enabled = true
|
|||
name = Authelia
|
||||
icon = signin
|
||||
client_id = grafana
|
||||
client_secret = grafana_client_secret
|
||||
client_secret = insecure_secret
|
||||
scopes = openid profile email groups
|
||||
empty_scopes = false
|
||||
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_NAME | Authelia |
|
||||
| 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_EMPTY_SCOPES | false |
|
||||
| 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
|
||||
- id: grafana
|
||||
description: Grafana
|
||||
secret: '$plaintext$grafana_client_secret'
|
||||
secret: '$pbkdf2-sha512$310000$c8p78n7pUMln0jzvd4aK4Q$JNRBzwAo0ek5qKn50cFzzvE9RXV88h1wJn5KGiHrD0YKtZaR/nCb2CJPOsKaPK0hjf.9yHxzQGZziziccp6Yng' # The digest of 'insecure_secret'.
|
||||
public: false
|
||||
authorization_policy: two_factor
|
||||
redirect_uris:
|
||||
|
|
|
@ -22,14 +22,7 @@ community: true
|
|||
|
||||
## Before You Begin
|
||||
|
||||
### Common Notes
|
||||
|
||||
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
|
||||
{{% oidc-common %}}
|
||||
|
||||
### Assumptions
|
||||
|
||||
|
@ -38,7 +31,7 @@ This example makes the following assumptions:
|
|||
* __Application Root URL:__ `https://harbor.example.com`
|
||||
* __Authelia Root URL:__ `https://auth.example.com`
|
||||
* __Client ID:__ `harbor`
|
||||
* __Client Secret:__ `harbor_client_secret`
|
||||
* __Client Secret:__ `insecure_secret`
|
||||
|
||||
## Configuration
|
||||
|
||||
|
@ -54,7 +47,7 @@ To configure [Harbor] to utilize Authelia as an [OpenID Connect 1.0] Provider:
|
|||
1. OIDC Provider Name: `Authelia`
|
||||
2. OIDC Provider Endpoint: `https://auth.example.com`
|
||||
3. OIDC Client ID: `harbor`
|
||||
4. OIDC Client Secret: `harbor_client_secret`
|
||||
4. OIDC Client Secret: `insecure_secret`
|
||||
5. Group Claim Name: `groups`
|
||||
6. OIDC Scope: `openid,profile,email,groups`
|
||||
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
|
||||
- id: harbor
|
||||
description: Harbor
|
||||
secret: '$plaintext$harbor_client_secret'
|
||||
secret: '$pbkdf2-sha512$310000$c8p78n7pUMln0jzvd4aK4Q$JNRBzwAo0ek5qKn50cFzzvE9RXV88h1wJn5KGiHrD0YKtZaR/nCb2CJPOsKaPK0hjf.9yHxzQGZziziccp6Yng' # The digest of 'insecure_secret'.
|
||||
public: false
|
||||
authorization_policy: two_factor
|
||||
redirect_uris:
|
||||
|
|
|
@ -22,14 +22,7 @@ community: true
|
|||
|
||||
## Before You Begin
|
||||
|
||||
### Common Notes
|
||||
|
||||
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
|
||||
{{% oidc-common %}}
|
||||
|
||||
### Assumptions
|
||||
|
||||
|
@ -38,7 +31,7 @@ This example makes the following assumptions:
|
|||
* __Application Root URL:__ `https://vault.example.com`
|
||||
* __Authelia Root URL:__ `https://auth.example.com`
|
||||
* __Client ID:__ `vault`
|
||||
* __Client Secret:__ `vault_client_secret`
|
||||
* __Client Secret:__ `insecure_secret`
|
||||
|
||||
## Configuration
|
||||
|
||||
|
@ -56,7 +49,7 @@ which will operate with the above example:
|
|||
```yaml
|
||||
- id: vault
|
||||
description: HashiCorp Vault
|
||||
secret: '$plaintext$vault_client_secret'
|
||||
secret: '$pbkdf2-sha512$310000$c8p78n7pUMln0jzvd4aK4Q$JNRBzwAo0ek5qKn50cFzzvE9RXV88h1wJn5KGiHrD0YKtZaR/nCb2CJPOsKaPK0hjf.9yHxzQGZziziccp6Yng' # The digest of 'insecure_secret'.
|
||||
public: false
|
||||
authorization_policy: two_factor
|
||||
redirect_uris:
|
||||
|
|
|
@ -166,16 +166,16 @@ These endpoints implement OpenID Connect elements.
|
|||
[OpenID Connect 1.0]: https://openid.net/connect/
|
||||
|
||||
[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
|
||||
[Token]: https://openid.net/specs/openid-connect-core-1_0.html#TokenEndpoint
|
||||
[UserInfo]: https://openid.net/specs/openid-connect-core-1_0.html#UserInfo
|
||||
[Introspection]: https://www.rfc-editor.org/rfc/rfc7662.html
|
||||
[Revocation]: https://www.rfc-editor.org/rfc/rfc7009.html
|
||||
[Introspection]: https://datatracker.ietf.org/doc/html/rfc7662
|
||||
[Revocation]: https://datatracker.ietf.org/doc/html/rfc7009
|
||||
|
||||
[RFC8176]: https://www.rfc-editor.org/rfc/rfc8176.html
|
||||
[RFC4122]: https://www.rfc-editor.org/rfc/rfc4122.html
|
||||
[RFC8176]: https://datatracker.ietf.org/doc/html/rfc8176
|
||||
[RFC4122]: https://datatracker.ietf.org/doc/html/rfc4122
|
||||
[Subject Identifier Types]: https://openid.net/specs/openid-connect-core-1_0.html#SubjectIDTypes
|
||||
|
|
|
@ -22,14 +22,7 @@ community: true
|
|||
|
||||
## Before You Begin
|
||||
|
||||
### Common Notes
|
||||
|
||||
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
|
||||
{{% oidc-common %}}
|
||||
|
||||
### Assumptions
|
||||
|
||||
|
@ -38,7 +31,7 @@ This example makes the following assumptions:
|
|||
* __Application Root URL:__ `https://komga.example.com`
|
||||
* __Authelia Root URL:__ `https://auth.example.com`
|
||||
* __Client ID:__ `komga`
|
||||
* __Client Secret:__ `komga_client_secret`
|
||||
* __Client Secret:__ `insecure_secret`
|
||||
|
||||
## Configuration
|
||||
|
||||
|
@ -58,7 +51,7 @@ spring:
|
|||
registration:
|
||||
authelia:
|
||||
client-id: `komga`
|
||||
client-secret: `komga_client_secret`
|
||||
client-secret: `insecure_secret`
|
||||
client-name: Authelia
|
||||
scope: openid,profile,email
|
||||
authorization-grant-type: authorization_code
|
||||
|
@ -78,7 +71,7 @@ which will operate with the above example:
|
|||
```yaml
|
||||
- id: komga
|
||||
description: Komga
|
||||
secret: '$plaintext$komga_client_secret'
|
||||
secret: '$pbkdf2-sha512$310000$c8p78n7pUMln0jzvd4aK4Q$JNRBzwAo0ek5qKn50cFzzvE9RXV88h1wJn5KGiHrD0YKtZaR/nCb2CJPOsKaPK0hjf.9yHxzQGZziziccp6Yng' # The digest of 'insecure_secret'.
|
||||
public: false
|
||||
authorization_policy: two_factor
|
||||
redirect_uris:
|
||||
|
|
|
@ -22,14 +22,7 @@ community: true
|
|||
|
||||
## Before You Begin
|
||||
|
||||
### Common Notes
|
||||
|
||||
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
|
||||
{{% oidc-common %}}
|
||||
|
||||
### Assumptions
|
||||
|
||||
|
@ -38,7 +31,7 @@ This example makes the following assumptions:
|
|||
* __Application Root URL:__ `https://nextcloud.example.com`
|
||||
* __Authelia Root URL:__ `https://auth.example.com`
|
||||
* __Client ID:__ `nextcloud`
|
||||
* __Client Secret:__ `nextcloud_client_secret`
|
||||
* __Client Secret:__ `insecure_secret`
|
||||
|
||||
## Configuration
|
||||
|
||||
|
@ -55,7 +48,7 @@ $CONFIG = array (
|
|||
'lost_password_link' => 'disabled',
|
||||
'oidc_login_provider_url' => 'https://auth.example.com',
|
||||
'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_end_session_redirect' => false,
|
||||
'oidc_login_button_text' => 'Log in with Authelia',
|
||||
|
@ -94,7 +87,7 @@ which will operate with the above example:
|
|||
```yaml
|
||||
- id: nextcloud
|
||||
description: NextCloud
|
||||
secret: '$plaintext$nextcloud_client_secret'
|
||||
secret: '$pbkdf2-sha512$310000$c8p78n7pUMln0jzvd4aK4Q$JNRBzwAo0ek5qKn50cFzzvE9RXV88h1wJn5KGiHrD0YKtZaR/nCb2CJPOsKaPK0hjf.9yHxzQGZziziccp6Yng' # The digest of 'insecure_secret'.
|
||||
public: false
|
||||
authorization_policy: two_factor
|
||||
redirect_uris:
|
||||
|
|
|
@ -22,14 +22,7 @@ community: true
|
|||
|
||||
## Before You Begin
|
||||
|
||||
### Common Notes
|
||||
|
||||
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
|
||||
{{% oidc-common %}}
|
||||
|
||||
### Assumptions
|
||||
|
||||
|
@ -38,7 +31,7 @@ This example makes the following assumptions:
|
|||
* __Application Root URL:__ `https://outline.example.com`
|
||||
* __Authelia Root URL:__ `https://auth.example.com`
|
||||
* __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
|
||||
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
|
||||
|
||||
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_TOKEN_URI=https://auth.example.com/api/oidc/token
|
||||
OIDC_USERINFO_URI=https://auth.example.com/api/oidc/userinfo
|
||||
|
@ -73,7 +66,7 @@ which will operate with the above example:
|
|||
```yaml
|
||||
- id: outline
|
||||
description: Outline
|
||||
secret: '$plaintext$outline_client_secret'
|
||||
secret: '$pbkdf2-sha512$310000$c8p78n7pUMln0jzvd4aK4Q$JNRBzwAo0ek5qKn50cFzzvE9RXV88h1wJn5KGiHrD0YKtZaR/nCb2CJPOsKaPK0hjf.9yHxzQGZziziccp6Yng' # The digest of 'insecure_secret'.
|
||||
public: false
|
||||
authorization_policy: two_factor
|
||||
redirect_uris:
|
||||
|
|
|
@ -24,14 +24,7 @@ aliases:
|
|||
|
||||
## Before You Begin
|
||||
|
||||
### Common Notes
|
||||
|
||||
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
|
||||
{{% oidc-common %}}
|
||||
|
||||
### Assumptions
|
||||
|
||||
|
@ -40,7 +33,7 @@ This example makes the following assumptions:
|
|||
* __Application Root URL:__ `https://portainer.example.com`
|
||||
* __Authelia Root URL:__ `https://auth.example.com`
|
||||
* __Client ID:__ `portainer`
|
||||
* __Client Secret:__ `portainer_client_secret`
|
||||
* __Client Secret:__ `insecure_secret`
|
||||
|
||||
## Configuration
|
||||
|
||||
|
@ -55,7 +48,7 @@ To configure [Portainer] to utilize Authelia as an [OpenID Connect 1.0] Provider
|
|||
2. Provider: Custom
|
||||
3. Enable *Automatic User Provision* if you want users to automatically be created in [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`
|
||||
7. Access Token URL: `https://auth.example.com/api/oidc/token`
|
||||
8. Resource URL: `https://auth.example.com/api/oidc/userinfo`
|
||||
|
@ -74,7 +67,7 @@ which will operate with the above example:
|
|||
```yaml
|
||||
- id: portainer
|
||||
description: Portainer
|
||||
secret: '$plaintext$portainer_client_secret'
|
||||
secret: '$pbkdf2-sha512$310000$c8p78n7pUMln0jzvd4aK4Q$JNRBzwAo0ek5qKn50cFzzvE9RXV88h1wJn5KGiHrD0YKtZaR/nCb2CJPOsKaPK0hjf.9yHxzQGZziziccp6Yng' # The digest of 'insecure_secret'.
|
||||
public: false
|
||||
authorization_policy: two_factor
|
||||
redirect_uris:
|
||||
|
|
|
@ -43,7 +43,7 @@ This example makes the following assumptions:
|
|||
* __Application Root URL:__ `https://proxmox.example.com`
|
||||
* __Authelia Root URL:__ `https://auth.example.com`
|
||||
* __Client ID:__ `proxmox`
|
||||
* __Client Secret:__ `proxmox_client_secret`
|
||||
* __Client Secret:__ `insecure_secret`
|
||||
* __Realm__ `authelia`
|
||||
|
||||
## 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`
|
||||
2. Realm: `authelia`
|
||||
3. Client ID: `proxmox`
|
||||
4. Client Key: `proxmox_client_secret`
|
||||
4. Client Key: `insecure_secret`
|
||||
5. Username Claim `preferred_username`
|
||||
6. Scopes: `openid profile email`
|
||||
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
|
||||
- id: proxmox
|
||||
description: Proxmox
|
||||
secret: '$plaintext$proxmox_client_secret'
|
||||
secret: '$pbkdf2-sha512$310000$c8p78n7pUMln0jzvd4aK4Q$JNRBzwAo0ek5qKn50cFzzvE9RXV88h1wJn5KGiHrD0YKtZaR/nCb2CJPOsKaPK0hjf.9yHxzQGZziziccp6Yng' # The digest of 'insecure_secret'.
|
||||
public: false
|
||||
authorization_policy: two_factor
|
||||
redirect_uris:
|
||||
|
|
|
@ -22,14 +22,7 @@ community: true
|
|||
|
||||
## Before You Begin
|
||||
|
||||
### Common Notes
|
||||
|
||||
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
|
||||
{{% oidc-common %}}
|
||||
|
||||
### Assumptions
|
||||
|
||||
|
@ -38,7 +31,7 @@ This example makes the following assumptions:
|
|||
* __Application Root URL:__ `https://seafile.example.com`
|
||||
* __Authelia Root URL:__ `https://auth.example.com`
|
||||
* __Client ID:__ `seafile`
|
||||
* __Client Secret:__ `seafile_client_secret`
|
||||
* __Client Secret:__ `insecure_secret`
|
||||
|
||||
## Configuration
|
||||
|
||||
|
@ -55,7 +48,7 @@ To configure [Seafile] to utilize Authelia as an [OpenID Connect 1.0] Provider:
|
|||
ENABLE_OAUTH = True
|
||||
OAUTH_ENABLE_INSECURE_TRANSPORT = False
|
||||
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_PROVIDER_DOMAIN = 'auth.example.com'
|
||||
OAUTH_AUTHORIZATION_URL = 'https://auth.example.com/api/oidc/authorization'
|
||||
|
@ -82,7 +75,7 @@ which will operate with the above example:
|
|||
```yaml
|
||||
- id: seafile
|
||||
description: Seafile
|
||||
secret: '$plaintext$seafile_client_secret'
|
||||
secret: '$pbkdf2-sha512$310000$c8p78n7pUMln0jzvd4aK4Q$JNRBzwAo0ek5qKn50cFzzvE9RXV88h1wJn5KGiHrD0YKtZaR/nCb2CJPOsKaPK0hjf.9yHxzQGZziziccp6Yng' # The digest of 'insecure_secret'.
|
||||
public: false
|
||||
authorization_policy: two_factor
|
||||
redirect_uris:
|
||||
|
|
|
@ -34,6 +34,22 @@ using PBKDF2 which can be stored in the Authelia configuration.
|
|||
|
||||
### Plaintext
|
||||
|
||||
Authelia supports storing the plaintext secret in the configuration. This may be discontinued in the future. 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.
|
||||
Authelia *technically* supports storing the plaintext secret in the configuration. This will likely be completely
|
||||
unavailable in the future as it was a mistake to implement it like this in the first place. While some other OpenID
|
||||
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.
|
||||
|
|
|
@ -22,14 +22,7 @@ community: true
|
|||
|
||||
## Before You Begin
|
||||
|
||||
### Common Notes
|
||||
|
||||
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
|
||||
{{% oidc-common %}}
|
||||
|
||||
### Assumptions
|
||||
|
||||
|
@ -38,7 +31,7 @@ This example makes the following assumptions:
|
|||
* __Application Root URL:__ `https://matrix.example.com/`
|
||||
* __Authelia Root URL:__ `https://auth.example.com`
|
||||
* __Client ID:__ `synapse`
|
||||
* __Client Secret:__ `synapse_client_secret`
|
||||
* __Client Secret:__ `insecure_secret`
|
||||
|
||||
## Configuration
|
||||
|
||||
|
@ -56,7 +49,7 @@ oidc_providers:
|
|||
discover: true
|
||||
issuer: "https://auth.example.com"
|
||||
client_id: "synapse"
|
||||
client_secret: "synapse_client_secret"
|
||||
client_secret: "insecure_secret"
|
||||
scopes: ["openid", "profile", "email"]
|
||||
allow_existing_users: true
|
||||
user_mapping_provider:
|
||||
|
@ -76,7 +69,7 @@ which will operate with the above example:
|
|||
```yaml
|
||||
- id: synapse
|
||||
description: Synapse
|
||||
secret: '$plaintext$synapse_client_secret'
|
||||
secret: '$pbkdf2-sha512$310000$c8p78n7pUMln0jzvd4aK4Q$JNRBzwAo0ek5qKn50cFzzvE9RXV88h1wJn5KGiHrD0YKtZaR/nCb2CJPOsKaPK0hjf.9yHxzQGZziziccp6Yng' # The digest of 'insecure_secret'.
|
||||
public: false
|
||||
authorization_policy: two_factor
|
||||
redirect_uris:
|
||||
|
|
|
@ -22,14 +22,7 @@ community: true
|
|||
|
||||
## Before You Begin
|
||||
|
||||
### Common Notes
|
||||
|
||||
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
|
||||
{{% oidc-common %}}
|
||||
|
||||
### Specific Notes
|
||||
|
||||
|
@ -43,7 +36,7 @@ This example makes the following assumptions:
|
|||
* __Application Root URL:__ `https://dsm.example.com/`
|
||||
* __Authelia Root URL:__ `https://auth.example.com`
|
||||
* __Client ID:__ `synology-dsm`
|
||||
* __Client Secret:__ `synology-dsm_client_secret`
|
||||
* __Client Secret:__ `insecure_secret`
|
||||
|
||||
## Configuration
|
||||
|
||||
|
@ -61,7 +54,7 @@ To configure [Synology DSM] to utilize Authelia as an [OpenID Connect 1.0] Provi
|
|||
* Name: `Authelia`
|
||||
* Well Known URL: `https://auth.example.com/.well-known/openid-configuration`
|
||||
* Application ID: `synology-dsm`
|
||||
* Application Key: `synology-dsm_client_secret`
|
||||
* Application Key: `insecure_secret`
|
||||
* Redirect URL: `https://dsm.example.com`
|
||||
* Authorisation Scope: `openid profile groups email`
|
||||
* Username Claim: `preferred_username`
|
||||
|
@ -78,7 +71,7 @@ which will operate with the above example:
|
|||
```yaml
|
||||
- id: 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
|
||||
authorization_policy: two_factor
|
||||
redirect_uris:
|
||||
|
|
|
@ -102,7 +102,7 @@ nextcloud.example.com {
|
|||
## 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.
|
||||
# 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.
|
||||
import trusted_proxy_list
|
||||
|
@ -141,7 +141,7 @@ example.com {
|
|||
handle @nextcloud {
|
||||
forward_auth authelia:9091 {
|
||||
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.
|
||||
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.
|
||||
@good status 2xx
|
||||
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-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-Name {http.reverse_proxy.header.Remote-Name}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -177,9 +177,10 @@ static_resources:
|
|||
authorization_request:
|
||||
allowed_headers:
|
||||
patterns:
|
||||
- exact: authorization
|
||||
- exact: proxy-authorization
|
||||
- exact: accept
|
||||
- exact: cookie
|
||||
- exact: proxy-authorization
|
||||
headers_to_add:
|
||||
- key: X-Forwarded-Proto
|
||||
value: '%REQ(:SCHEME)%'
|
||||
|
|
|
@ -218,29 +218,53 @@ backend be_authelia
|
|||
server authelia authelia:9091
|
||||
|
||||
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_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_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-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-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
|
||||
|
||||
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_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_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-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-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
|
||||
```
|
||||
|
||||
|
@ -325,29 +349,53 @@ listen authelia_proxy
|
|||
server authelia authelia:9091 ssl verify none
|
||||
|
||||
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_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_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-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-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
|
||||
|
||||
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_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_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-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-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
|
||||
```
|
||||
|
||||
|
|
|
@ -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.
|
||||
# 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 $groups $upstream_http_remote_groups;
|
||||
auth_request_set $name $upstream_http_remote_name;
|
||||
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-Groups $groups;
|
||||
proxy_set_header Remote-Name $name;
|
||||
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://auth.example.com/?rd=$target_url;
|
||||
|
|
|
@ -157,7 +157,7 @@ services:
|
|||
## 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.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:
|
||||
container_name: 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.
|
||||
# - '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.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
|
||||
|
|
|
@ -137,7 +137,7 @@ services:
|
|||
## 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.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:
|
||||
- 443
|
||||
restart: unless-stopped
|
||||
|
@ -156,7 +156,7 @@ services:
|
|||
- 'traefik.frontend.rule=Host:heimdall.example.com'
|
||||
- 'traefik.frontend.auth.forward.address=http://authelia:9091/api/authz/forward-auth/basic'
|
||||
- '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:
|
||||
- 443
|
||||
restart: unless-stopped
|
||||
|
|
|
@ -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
|
||||
[cleartext]: https://cwe.mitre.org/data/definitions/312.html
|
||||
[service-submissions]: https://www.rfc-editor.org/rfc/rfc8314#section-7.3
|
||||
[port-465]: https://www.rfc-editor.org/rfc/rfc8314#section-3.3
|
||||
[smtp-auth]: https://www.rfc-editor.org/rfc/rfc6409#section-4.3
|
||||
[service-submissions]: https://datatracker.ietf.org/doc/html/rfc8314#section-7.3
|
||||
[port-465]: https://datatracker.ietf.org/doc/html/rfc8314#section-3.3
|
||||
[smtp-auth]: https://datatracker.ietf.org/doc/html/rfc6409#section-4.3
|
||||
|
||||
## Protection against open redirects
|
||||
|
||||
|
|
|
@ -193,14 +193,14 @@ This table suggests the parameters for the [SHA2 Crypt] algorithm:
|
|||
| Standard CPU | sha512 | 50000 | 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
|
||||
[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
|
||||
[Bcrypt]: https://en.wikipedia.org/wiki/Bcrypt
|
||||
[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/
|
||||
[crypt hash generate]: ../cli/authelia/authelia_crypto_hash_generate.md
|
||||
[Password Hashing Competition]: https://en.wikipedia.org/wiki/Password_Hashing_Competition
|
||||
|
|
|
@ -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
|
||||
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/).
|
||||
|
||||
Each directory has JSON files which you can explore the format of in the
|
||||
|
|
|
@ -39,11 +39,11 @@ Feature List:
|
|||
* [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)
|
||||
* [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 Authorization Policy (1FA/2FA)
|
||||
* 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
|
||||
|
||||
|
@ -56,7 +56,7 @@ Feature List:
|
|||
* Token/Code Lifespan
|
||||
* Client Debug Messages
|
||||
* 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
|
||||
|
||||
|
@ -97,7 +97,7 @@ 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
|
||||
* Per-Client [Consent](https://openid.net/specs/openid-connect-core-1_0.html#Consent) Mode:
|
||||
* Explicit:
|
||||
|
@ -115,7 +115,7 @@ Feature List:
|
|||
|
||||
{{< 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
|
||||
|
||||
### Beta 7
|
||||
|
@ -177,7 +177,7 @@ Should be implemented alongside [Dynamic Client Registration](#openid-connect-dy
|
|||
|
||||
{{< 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
|
||||
|
||||
|
@ -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
|
||||
|
||||
[RFC8176]: https://www.rfc-editor.org/rfc/rfc8176.html
|
||||
[RFC8693 Section 4.3]: https://www.rfc-editor.org/rfc/rfc8693.html/#section-4.3
|
||||
[RFC4122]: https://www.rfc-editor.org/rfc/rfc4122.html
|
||||
[RFC8176]: https://datatracker.ietf.org/doc/html/rfc8176
|
||||
[RFC8693 Section 4.3]: https://datatracker.ietf.org/doc/html/rfc8693/#section-4.3
|
||||
[RFC4122]: https://datatracker.ietf.org/doc/html/rfc4122
|
||||
|
||||
[OpenID Connect]: https://openid.net/connect/
|
||||
[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 (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
|
||||
[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
|
||||
|
|
|
@ -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.
|
|
@ -5,7 +5,7 @@
|
|||
[build.environment]
|
||||
NODE_VERSION = "16.18.1"
|
||||
NPM_VERSION = "8.19.2"
|
||||
GO_VERSION = "1.19.4"
|
||||
GO_VERSION = "1.19.5"
|
||||
|
||||
[context.production]
|
||||
command = "pnpm run build"
|
||||
|
|
14
go.mod
14
go.mod
|
@ -1,19 +1,19 @@
|
|||
module github.com/authelia/authelia/v4
|
||||
|
||||
go 1.19
|
||||
go 1.20
|
||||
|
||||
require (
|
||||
github.com/Gurpartap/logrus-stack v0.0.0-20170710170904-89c00d8a28f4
|
||||
github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d
|
||||
github.com/deckarep/golang-set/v2 v2.1.0
|
||||
github.com/duosecurity/duo_api_golang v0.0.0-20221117185402-091daa09e19d
|
||||
github.com/fasthttp/router v1.4.15
|
||||
github.com/duosecurity/duo_api_golang v0.0.0-20230203160531-b221c950c2b0
|
||||
github.com/fasthttp/router v1.4.16
|
||||
github.com/fasthttp/session/v2 v2.4.16
|
||||
github.com/fsnotify/fsnotify v1.6.0
|
||||
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-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-webauthn/webauthn v0.7.0
|
||||
github.com/golang-jwt/jwt/v4 v4.4.3
|
||||
|
@ -40,6 +40,7 @@ require (
|
|||
github.com/trustelem/zxcvbn v1.0.1
|
||||
github.com/valyala/fasthttp v1.44.0
|
||||
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/term v0.4.0
|
||||
golang.org/x/text v0.6.0
|
||||
|
@ -64,7 +65,7 @@ require (
|
|||
github.com/ecordell/optgen v0.0.6 // indirect
|
||||
github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 // 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-webauthn/revoke v0.1.6 // indirect
|
||||
github.com/golang/glog v1.0.0 // indirect
|
||||
|
@ -109,7 +110,6 @@ require (
|
|||
github.com/ysmood/leakless v0.8.0 // indirect
|
||||
golang.org/x/crypto v0.5.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/sys v0.4.0 // indirect
|
||||
golang.org/x/tools v0.4.0 // indirect
|
||||
|
|
20
go.sum
20
go.sum
|
@ -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/dlclark/regexp2 v1.4.0 h1:F1rxgk7p4uKjwIQxBs9oAXe5CqrXlCduYEJvrF4u93E=
|
||||
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-20221117185402-091daa09e19d/go.mod h1:jI+QUTOK3wqIOrUl0Cwnwlgc/P6vs6pZOuQY3aKggwg=
|
||||
github.com/duosecurity/duo_api_golang v0.0.0-20230203160531-b221c950c2b0 h1:+0VqbFomxHYZLIsuLJ7FjAdjhJTQ4P3/o6paTMx5kAY=
|
||||
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/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
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/facebookgo/stack v0.0.0-20160209184415-751773369052 h1:JWuenKqqX8nojtoVVWjGfOF9635RETekkoH6Cc9SX0A=
|
||||
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.15/go.mod h1:NFNlTCilbRVkeLc+E5JDkcxUdkpiJGKDL8Zy7Ey2JTI=
|
||||
github.com/fasthttp/router v1.4.16 h1:faWJ9OtaHvAtodreyQLps58M80YFNzphMJtOJzeESXs=
|
||||
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/go.mod h1:nv8SD6pAx3n3KjJsEt4k1p0vstqclbNcrCwjc1OjuCI=
|
||||
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/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-crypt/crypt v0.2.3 h1:g9OPe39VmqonsTXP/zo4byEoxrxAAUG+DzBvjzGWvuw=
|
||||
github.com/go-crypt/crypt v0.2.3/go.mod h1:mbhOIjybuVuh0Vxveb//7UbGV8OCugJC7UPzqs1awYw=
|
||||
github.com/go-crypt/x v0.1.10 h1:HN8oQGrWcg5xPtIIGwPDWs9MvdYEUJrP7JeNkC46dvM=
|
||||
github.com/go-crypt/x v0.1.10/go.mod h1:OI04rm/Ojti3mrUFZAJnx66nFbnZ0CVPF7qG49mBZgI=
|
||||
github.com/go-crypt/crypt v0.2.5 h1:QYGV/OkamPz69fME+JbD0wVmPnAL3C1Ooypqb1FHnHk=
|
||||
github.com/go-crypt/crypt v0.2.5/go.mod h1:VtajXhpCQlYwf4ekvp1I/6bSFi1YKobq0QInA1AFCQQ=
|
||||
github.com/go-crypt/x v0.1.12 h1:UQvK75MBYGdeY7PdP/YbkUqiGxNzJq3BlO/lTVT6yuU=
|
||||
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/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=
|
||||
|
@ -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-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-rod/rod v0.112.3 h1:xbSaA9trZ8v/+eJRGOM6exK1RCsLPwwnzA78vpES0gk=
|
||||
github.com/go-rod/rod v0.112.3/go.mod h1:ElViL9ABbcshNQw93+11FrYRH92RRhMKleuILo6+5V0=
|
||||
github.com/go-rod/rod v0.112.4 h1:Ck002nM6rCORdVFtD778WxiadS5oJsmqytjXTG5bqiQ=
|
||||
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.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc=
|
||||
github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
|
||||
|
|
|
@ -426,7 +426,7 @@ authentication_backend:
|
|||
## 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
|
||||
## 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
|
||||
|
||||
## The additional_users_dn is prefixed to base_dn and delimited by a comma when searching for users.
|
||||
|
|
|
@ -105,6 +105,9 @@ func TestShouldValidateConfigurationWithFilters(t *testing.T) {
|
|||
testSetEnv(t, "JWT_SECRET", "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("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, "10.10.10.10", config.Notifier.SMTP.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) {
|
||||
|
|
|
@ -174,4 +174,21 @@ notifier:
|
|||
port: 1025
|
||||
sender: 'admin@{{ env "ROOT_DOMAIN" }}'
|
||||
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
|
||||
...
|
||||
|
|
|
@ -267,7 +267,9 @@ const (
|
|||
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'"
|
||||
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.
|
||||
|
|
|
@ -104,12 +104,22 @@ func validateSessionDomainName(i int, config *schema.SessionConfiguration, valid
|
|||
switch {
|
||||
case d.Domain == "":
|
||||
validator.Push(fmt.Errorf(errFmtSessionDomainRequired, sessionDomainDescriptor(i, d)))
|
||||
return
|
||||
case strings.HasPrefix(d.Domain, "*."):
|
||||
validator.Push(fmt.Errorf(errFmtSessionDomainMustBeRoot, sessionDomainDescriptor(i, d), d.Domain))
|
||||
return
|
||||
case strings.HasPrefix(d.Domain, "."):
|
||||
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):
|
||||
validator.Push(fmt.Errorf(errFmtSessionDomainInvalidDomain, sessionDomainDescriptor(i, d)))
|
||||
return
|
||||
}
|
||||
|
||||
if isCookieDomainAPublicSuffix(d.Domain) {
|
||||
validator.Push(fmt.Errorf(errFmtSessionDomainInvalidDomainPublic, sessionDomainDescriptor(i, d)))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
|
||||
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) {
|
||||
validator := schema.NewStructValidator()
|
||||
config := newDefaultSessionConfig()
|
||||
|
@ -675,10 +636,18 @@ func TestShouldRaiseErrorWhenDomainIsInvalid(t *testing.T) {
|
|||
testCases := []struct {
|
||||
name string
|
||||
have string
|
||||
warnings []string
|
||||
expected []string
|
||||
}{
|
||||
{"ShouldRaiseErrorOnMissingDomain", "", []string{"session: domain config #1 (domain ''): option 'domain' is required"}},
|
||||
{"ShouldNotRaiseErrorOnValidDomain", exampleDotCom, nil},
|
||||
{"ShouldNotRaiseErrorOnValidDomain", exampleDotCom, nil, 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 {
|
||||
|
@ -692,14 +661,18 @@ func TestShouldRaiseErrorWhenDomainIsInvalid(t *testing.T) {
|
|||
SessionCookieCommonConfiguration: schema.SessionCookieCommonConfiguration{
|
||||
Domain: tc.have,
|
||||
},
|
||||
AutheliaURL: MustParseURL("https://auth.example.com")},
|
||||
},
|
||||
}
|
||||
|
||||
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))
|
||||
|
||||
for i, expected := range tc.warnings {
|
||||
assert.EqualError(t, validator.Warnings()[i], expected)
|
||||
}
|
||||
|
||||
for i, expected := range tc.expected {
|
||||
assert.EqualError(t, validator.Errors()[i], expected)
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
|
@ -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))
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
|
@ -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:
|
||||
|
||||
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
|
||||
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)
|
||||
or 204 (No Content).
|
||||
*/
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
||||
// Integer mocks base method.
|
||||
func (m *MockRandom) Integer(arg0 int) int {
|
||||
// Intn mocks base method.
|
||||
func (m *MockRandom) Intn(arg0 int) int {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Integer", arg0)
|
||||
ret := m.ctrl.Call(m, "Intn", arg0)
|
||||
ret0, _ := ret[0].(int)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Integer indicates an expected call of Integer.
|
||||
func (mr *MockRandomMockRecorder) Integer(arg0 interface{}) *gomock.Call {
|
||||
// Intn indicates an expected call of Intn.
|
||||
func (mr *MockRandomMockRecorder) Intn(arg0 interface{}) *gomock.Call {
|
||||
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.
|
||||
func (m *MockRandom) IntegerErr(arg0 int) (int, error) {
|
||||
// IntnErr mocks base method.
|
||||
func (m *MockRandom) IntnErr(arg0 int) (int, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "IntegerErr", arg0)
|
||||
ret := m.ctrl.Call(m, "IntnErr", arg0)
|
||||
ret0, _ := ret[0].(int)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// IntegerErr indicates an expected call of IntegerErr.
|
||||
func (mr *MockRandomMockRecorder) IntegerErr(arg0 interface{}) *gomock.Call {
|
||||
// IntnErr indicates an expected call of IntnErr.
|
||||
func (mr *MockRandomMockRecorder) IntnErr(arg0 interface{}) *gomock.Call {
|
||||
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.
|
||||
|
|
|
@ -163,8 +163,8 @@ func (n *SMTPNotifier) Send(ctx context.Context, recipient mail.Address, subject
|
|||
}
|
||||
|
||||
func (n *SMTPNotifier) setMessageID(msg *gomail.Msg, domain string) {
|
||||
rn := n.random.Integer(100000000)
|
||||
rm := n.random.Integer(10000)
|
||||
rn := n.random.Intn(100000000)
|
||||
rm := n.random.Intn(10000)
|
||||
rs := n.random.StringCustom(17, random.CharSetAlphaNumeric)
|
||||
pid := os.Getpid() + rm
|
||||
|
||||
|
|
|
@ -180,7 +180,7 @@ func (s *Store) DeleteAccessTokenSession(ctx context.Context, signature string)
|
|||
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.
|
||||
// This implements a portion of oauth2.TokenRevocationStorage.
|
||||
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)
|
||||
}
|
||||
|
||||
// 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,
|
||||
// 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.
|
||||
|
@ -213,7 +213,7 @@ func (s *Store) RevokeRefreshToken(ctx context.Context, requestID string) (err e
|
|||
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.
|
||||
// This implements a portion of oauth2.TokenRevocationStorage.
|
||||
func (s *Store) RevokeRefreshTokenMaybeGracePeriod(ctx context.Context, requestID string, signature string) (err error) {
|
||||
|
|
|
@ -25,7 +25,7 @@ const (
|
|||
CharSetSymbolic = "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~"
|
||||
|
||||
// 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 = "-._~"
|
||||
|
||||
// CharSetAlphaNumeric are literally just valid alphanumeric printable ASCII chars.
|
||||
|
@ -35,7 +35,7 @@ const (
|
|||
CharSetASCII = CharSetAlphabetic + CharSetNumeric + CharSetSymbolic
|
||||
|
||||
// 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
|
||||
|
||||
// CharSetUnambiguousUpper are a set of unambiguous uppercase characters.
|
||||
|
|
|
@ -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
|
||||
// (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) {
|
||||
data = make([]byte, DefaultN)
|
||||
|
||||
_, err = rand.Read(data)
|
||||
|
||||
return data, err
|
||||
return r.BytesCustomErr(0, nil)
|
||||
}
|
||||
|
||||
// Bytes returns random data as bytes with the standard random.DefaultN length and can contain any byte values
|
||||
|
@ -49,9 +45,11 @@ func (r *Cryptographical) BytesCustomErr(n int, charset []byte) (data []byte, er
|
|||
|
||||
t := len(charset)
|
||||
|
||||
if t > 0 {
|
||||
for i := 0; i < n; i++ {
|
||||
data[i] = charset[data[i]%byte(t)]
|
||||
}
|
||||
}
|
||||
|
||||
return data, nil
|
||||
}
|
||||
|
@ -81,6 +79,36 @@ func (r *Cryptographical) StringCustom(n int, characters string) (data string) {
|
|||
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.
|
||||
func (r *Cryptographical) IntErr(max *big.Int) (value *big.Int, err error) {
|
||||
if max == nil {
|
||||
|
@ -105,32 +133,8 @@ func (r *Cryptographical) Int(max *big.Int) (value *big.Int) {
|
|||
return value
|
||||
}
|
||||
|
||||
// IntegerErr returns a random int error combination with a maximum of n.
|
||||
func (r *Cryptographical) IntegerErr(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
|
||||
}
|
||||
|
||||
// Integer returns a random int with a maximum of n.
|
||||
func (r *Cryptographical) Integer(n int) (value int) {
|
||||
value, _ = r.IntegerErr(n)
|
||||
|
||||
return value
|
||||
// Prime returns a number of the given bit length that is prime with high probability. Prime will return error for any
|
||||
// error returned by rand.Read or if bits < 2.
|
||||
func (r *Cryptographical) Prime(bits int) (prime *big.Int, err error) {
|
||||
return rand.Prime(rand.Reader, bits)
|
||||
}
|
|
@ -1,26 +1,36 @@
|
|||
package random
|
||||
|
||||
import (
|
||||
crand "crypto/rand"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"math/rand"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// NewMathematical runs rand.Seed with the current time and returns a random.Provider, specifically *random.Mathematical.
|
||||
func NewMathematical() *Mathematical {
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
|
||||
return &Mathematical{}
|
||||
return &Mathematical{
|
||||
rand: rand.New(rand.NewSource(time.Now().UnixNano())), //nolint:gosec
|
||||
lock: &sync.Mutex{},
|
||||
}
|
||||
}
|
||||
|
||||
// Mathematical is the random.Provider which uses math/rand and is COMPLETELY UNSAFE FOR PRODUCTION IN MOST SITUATIONS.
|
||||
// Use random.Cryptographical instead.
|
||||
type Mathematical struct{}
|
||||
type Mathematical struct {
|
||||
rand *rand.Rand
|
||||
lock *sync.Mutex
|
||||
}
|
||||
|
||||
// Read implements the io.Reader interface.
|
||||
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
|
||||
|
@ -28,7 +38,7 @@ func (r *Mathematical) Read(p []byte) (n int, err error) {
|
|||
func (r *Mathematical) BytesErr() (data []byte, err error) {
|
||||
data = make([]byte, DefaultN)
|
||||
|
||||
if _, err = rand.Read(data); err != nil { //nolint:gosec
|
||||
if _, err = r.Read(data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
@ -53,7 +63,7 @@ func (r *Mathematical) BytesCustomErr(n int, charset []byte) (data []byte, err e
|
|||
|
||||
data = make([]byte, n)
|
||||
|
||||
if _, err = rand.Read(data); err != nil { //nolint:gosec
|
||||
if _, err = r.Read(data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
@ -91,17 +101,18 @@ func (r *Mathematical) StringCustom(n int, characters string) (data string) {
|
|||
return string(r.BytesCustom(n, []byte(characters)))
|
||||
}
|
||||
|
||||
// IntErr returns a random *big.Int error combination with a maximum of max.
|
||||
func (r *Mathematical) IntErr(max *big.Int) (value *big.Int, err error) {
|
||||
if max == nil {
|
||||
return nil, fmt.Errorf("max is required")
|
||||
// Intn returns a random int with a maximum of n.
|
||||
func (r *Mathematical) Intn(n int) int {
|
||||
r.lock.Lock()
|
||||
|
||||
defer r.lock.Unlock()
|
||||
|
||||
return r.rand.Intn(n)
|
||||
}
|
||||
|
||||
if max.Sign() <= 0 {
|
||||
return nil, fmt.Errorf("max must be 1 or more")
|
||||
}
|
||||
|
||||
return big.NewInt(int64(rand.Intn(max.Sign()))), nil //nolint:gosec
|
||||
// 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.
|
||||
|
@ -115,12 +126,25 @@ func (r *Mathematical) Int(max *big.Int) (value *big.Int) {
|
|||
return value
|
||||
}
|
||||
|
||||
// IntegerErr returns a random int error combination with a maximum of n.
|
||||
func (r *Mathematical) IntegerErr(n int) (output int, err error) {
|
||||
return r.Integer(n), nil
|
||||
// IntErr returns a random *big.Int error combination with a maximum of max.
|
||||
func (r *Mathematical) IntErr(max *big.Int) (value *big.Int, err error) {
|
||||
if max == nil {
|
||||
return nil, fmt.Errorf("max is required")
|
||||
}
|
||||
|
||||
// Integer returns a random int with a maximum of n.
|
||||
func (r *Mathematical) Integer(n int) int {
|
||||
return rand.Intn(n) //nolint:gosec
|
||||
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
|
||||
}
|
||||
|
||||
// Prime returns a number of the given bit length that is prime with high probability. Prime will return error for any
|
||||
// error returned by rand.Read or if bits < 2.
|
||||
func (r *Mathematical) Prime(bits int) (prime *big.Int, err error) {
|
||||
return crand.Prime(r, bits)
|
||||
}
|
|
@ -32,15 +32,19 @@ type Provider interface {
|
|||
// StringCustom is an overload of GenerateCustom which takes a characters string and returns a 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(max *big.Int) (value *big.Int, err error)
|
||||
|
||||
// Int returns a random *big.Int with a maximum of max.
|
||||
Int(max *big.Int) (value *big.Int)
|
||||
|
||||
// IntegerErr returns a random int error combination with a maximum of n.
|
||||
IntegerErr(n int) (value int, err error)
|
||||
|
||||
// Integer returns a random integer with a maximum of n.
|
||||
Integer(n int) (value int)
|
||||
// Prime returns a number of the given bit length that is prime with high probability. Prime will return error for any
|
||||
// error returned by rand.Read or if bits < 2.
|
||||
Prime(bits int) (prime *big.Int, err error)
|
||||
}
|
||||
|
|
|
@ -4,11 +4,11 @@
|
|||
"Access your group membership": "Tilgang til ditt gruppemedlemskap",
|
||||
"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.",
|
||||
"Authenticated": "Verifisert",
|
||||
"Authenticated": "Autentisert",
|
||||
"Automatically refresh these permissions without user interaction": "Oppdater disse tillatelsene automatisk uten brukerinteraksjon",
|
||||
"Cancel": "Avbryt",
|
||||
"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.",
|
||||
"Could not obtain user settings": "Kan ikke hente brukerinnstillinger",
|
||||
"Deny": "Avslå",
|
||||
|
@ -16,15 +16,15 @@
|
|||
"Enter new password": "Skriv inn nytt passord",
|
||||
"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",
|
||||
"Hi": "Hi",
|
||||
"Hi": "Hei",
|
||||
"Incorrect username or password": "Ugyldig brukernavn eller passord.",
|
||||
"Loading": "Laster",
|
||||
"Login": "Innlogging",
|
||||
"Logout": "Logg",
|
||||
"Logout": "Logg ut",
|
||||
"Lost your device?": "Har du mistet enheten?",
|
||||
"Methods": "Metoder",
|
||||
"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 number": "Må ha minst ett tall",
|
||||
"Must have at least one special character": "Må ha minst ett spesialtegn",
|
||||
|
@ -39,6 +39,7 @@
|
|||
"Password": "Passord",
|
||||
"Passwords do not match": "Passordene samsvarer ikke.",
|
||||
"Powered by": "Drives av",
|
||||
"Privacy Policy": "Personvernerklæring",
|
||||
"Push Notification": "Push varsling",
|
||||
"Register device": "Registrer enheten",
|
||||
"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",
|
||||
"Reset password": "Tilbakestill passord",
|
||||
"Reset password?": "Tilbakestill passord?",
|
||||
"Reset": "Reset",
|
||||
"Scan QR Code": "Scan QR Code",
|
||||
"Reset": "Tilbakestill",
|
||||
"Scan QR Code": "Skann QR Kode",
|
||||
"Secret": "Hemmelig",
|
||||
"Security Key - WebAuthN": "Sikkerhetsnøkkel - WebAuthN",
|
||||
"Select a Device": "Velg en enhet",
|
||||
|
@ -67,6 +68,7 @@
|
|||
"Use OpenID to verify your identity": "Bruk OpenID for å bekrefte identiteten din",
|
||||
"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 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",
|
||||
"Your supplied password does not meet the password policy requirements": "Ditt angitte passord oppfyller ikke kravene for passord."
|
||||
}
|
||||
|
|
|
@ -4,11 +4,11 @@
|
|||
"Access your group membership": "Tilgang til ditt gruppemedlemskap",
|
||||
"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.",
|
||||
"Authenticated": "Verifisert",
|
||||
"Authenticated": "Autentisert",
|
||||
"Automatically refresh these permissions without user interaction": "Oppdater disse tillatelsene automatisk uten brukerinteraksjon",
|
||||
"Cancel": "Avbryt",
|
||||
"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.",
|
||||
"Could not obtain user settings": "Kan ikke hente brukerinnstillinger",
|
||||
"Deny": "Avslå",
|
||||
|
@ -16,15 +16,15 @@
|
|||
"Enter new password": "Skriv inn nytt passord",
|
||||
"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",
|
||||
"Hi": "Hi",
|
||||
"Hi": "Hei",
|
||||
"Incorrect username or password": "Ugyldig brukernavn eller passord.",
|
||||
"Loading": "Laster",
|
||||
"Login": "Innlogging",
|
||||
"Logout": "Logg",
|
||||
"Logout": "Logg ut",
|
||||
"Lost your device?": "Har du mistet enheten?",
|
||||
"Methods": "Metoder",
|
||||
"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 number": "Må ha minst ett tall",
|
||||
"Must have at least one special character": "Må ha minst ett spesialtegn",
|
||||
|
@ -39,6 +39,7 @@
|
|||
"Password": "Passord",
|
||||
"Passwords do not match": "Passordene samsvarer ikke.",
|
||||
"Powered by": "Drives av",
|
||||
"Privacy Policy": "Personvernerklæring",
|
||||
"Push Notification": "Push varsling",
|
||||
"Register device": "Registrer enheten",
|
||||
"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",
|
||||
"Reset password": "Tilbakestill passord",
|
||||
"Reset password?": "Tilbakestill passord?",
|
||||
"Reset": "Reset",
|
||||
"Scan QR Code": "Scan QR Code",
|
||||
"Reset": "Tilbakestill",
|
||||
"Scan QR Code": "Skann QR Kode",
|
||||
"Secret": "Hemmelig",
|
||||
"Security Key - WebAuthN": "Sikkerhetsnøkkel - WebAuthN",
|
||||
"Select a Device": "Velg en enhet",
|
||||
|
@ -67,6 +68,7 @@
|
|||
"Use OpenID to verify your identity": "Bruk OpenID for å bekrefte identiteten din",
|
||||
"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 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",
|
||||
"Your supplied password does not meet the password policy requirements": "Ditt angitte passord oppfyller ikke kravene for passord."
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
FROM golang:1.19.5-alpine
|
||||
FROM golang:1.20.0-alpine
|
||||
|
||||
ARG USER_ID
|
||||
ARG GROUP_ID
|
||||
|
|
|
@ -87,16 +87,20 @@ static_resources:
|
|||
authorization_request:
|
||||
allowed_headers:
|
||||
patterns:
|
||||
- exact: authorization
|
||||
- exact: proxy-authorization
|
||||
- exact: accept
|
||||
- exact: cookie
|
||||
- exact: proxy-authorization
|
||||
headers_to_add:
|
||||
- key: X-Forwarded-Proto
|
||||
value: '%REQ(:SCHEME)%'
|
||||
authorization_response:
|
||||
allowed_upstream_headers:
|
||||
patterns:
|
||||
- exact: authorization
|
||||
- exact: proxy-authorization
|
||||
- prefix: remote-
|
||||
- prefix: authelia-
|
||||
allowed_client_headers:
|
||||
patterns:
|
||||
- exact: set-cookie
|
||||
|
|
|
@ -82,15 +82,28 @@ backend fe_authelia
|
|||
server authelia-backend authelia-backend:9091 check backup resolvers docker ssl verify none
|
||||
|
||||
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_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_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-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-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
|
||||
|
||||
backend be_mail
|
||||
|
|
|
@ -752,9 +752,9 @@ M.base64 = {}
|
|||
--- URL safe base64 encoder
|
||||
--
|
||||
-- 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
|
||||
-- https://tools.ietf.org/html/rfc7515
|
||||
-- https://datatracker.ietf.org/doc/html/rfc7515
|
||||
--
|
||||
-- @param s String (can be binary data) to encode
|
||||
-- @param enc Function which implements base64 encoder (e.g. HAProxy base64 fetch)
|
||||
|
|
|
@ -12,7 +12,7 @@ services:
|
|||
- 'traefik.frontend.auth.forward.address=https://authelia-backend:9091/api/authz/forward-auth'
|
||||
- 'traefik.frontend.auth.forward.tls.insecureSkipVerify=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.enable=true'
|
||||
- 'traefik.http.routers.httpbin.rule=Host(`public.example.com`) && Path(`/headers`)'
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
version: '3'
|
||||
services:
|
||||
k3d:
|
||||
image: ghcr.io/k3d-io/k3d:5.4.6-dind
|
||||
image: ghcr.io/k3d-io/k3d:5.4.7-dind
|
||||
volumes:
|
||||
- './example/kube:/authelia'
|
||||
- './example/kube/authelia/configs/configuration.yml:/configmaps/authelia/configuration.yml'
|
||||
|
|
|
@ -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.tls.insecureSkipVerify=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.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
|
||||
|
|
|
@ -148,7 +148,7 @@ http {
|
|||
server_name ~^(public|admin|secure|dev|singlefactor|mx[1-2])(\.mail)?\.(?<basedomain>example([0-9])*\.com)$;
|
||||
|
||||
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_headers http://httpbin:8000/headers;
|
||||
|
||||
|
@ -163,22 +163,38 @@ http {
|
|||
# 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.
|
||||
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;
|
||||
proxy_set_header Remote-User $user;
|
||||
|
||||
auth_request_set $groups $upstream_http_remote_groups;
|
||||
proxy_set_header Remote-Groups $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;
|
||||
|
||||
auth_request_set $email $upstream_http_remote_email;
|
||||
proxy_set_header Remote-Email $email;
|
||||
## Include the Set-Cookie header if present.
|
||||
auth_request_set $cookie $upstream_http_set_cookie;
|
||||
add_header Set-Cookie $cookie;
|
||||
|
||||
# Route the request to the correct virtual host in the backend.
|
||||
proxy_set_header Host $http_host;
|
||||
## 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.
|
||||
# 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_set_header Proxy-Authorization $http_authorization;
|
||||
|
||||
# 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;
|
||||
# Route the request to the correct virtual host in the backend.
|
||||
proxy_set_header Host $http_host;
|
||||
|
||||
proxy_pass $upstream_endpoint;
|
||||
}
|
||||
|
||||
# Virtual endpoint forwarding requests to Authelia server.
|
||||
location /auth_verify {
|
||||
location /authelia {
|
||||
## Essential Proxy Configuration
|
||||
internal;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_pass $upstream_authelia;
|
||||
|
||||
# Provide either X-Original-URL and X-Forwarded-Proto or
|
||||
# X-Forwarded-Proto, X-Forwarded-Host and X-Forwarded-URI or both.
|
||||
|
@ -211,36 +222,64 @@ http {
|
|||
# See https://expressjs.com/en/guide/behind-proxies.html
|
||||
proxy_set_header X-Original-Method $request_method;
|
||||
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 Content-Length "";
|
||||
proxy_set_header Connection "";
|
||||
|
||||
# Authelia can receive Proxy-Authorization to authenticate however most of the clients
|
||||
# support Authorization instead. Therefore we rewrite Authorization into Proxy-Authorization.
|
||||
proxy_set_header Proxy-Authorization $http_authorization;
|
||||
|
||||
## Basic Proxy Configuration
|
||||
proxy_pass_request_body off;
|
||||
proxy_set_header Content-Length "";
|
||||
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.
|
||||
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;
|
||||
|
||||
## 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;
|
||||
proxy_set_header Remote-User $user;
|
||||
|
||||
auth_request_set $groups $upstream_http_remote_groups;
|
||||
proxy_set_header Remote-Groups $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;
|
||||
|
||||
auth_request_set $email $upstream_http_remote_email;
|
||||
proxy_set_header Remote-Email $email;
|
||||
## Include the Set-Cookie header if present.
|
||||
auth_request_set $cookie $upstream_http_set_cookie;
|
||||
add_header Set-Cookie $cookie;
|
||||
|
||||
set $target_url $scheme://$http_host$request_uri;
|
||||
## 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;
|
||||
|
@ -253,7 +292,7 @@ http {
|
|||
server_name ~^oidc(-public)?\.(?<basedomain>example([0-9])*\.com)$;
|
||||
|
||||
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;
|
||||
|
||||
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
|
||||
# to the virtual endpoint introduced by nginx and declared in the next block.
|
||||
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.
|
||||
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;
|
||||
}
|
||||
|
||||
# Virtual endpoint forwarding requests to Authelia server.
|
||||
location /auth_verify {
|
||||
location /authelia {
|
||||
## Essential Proxy Configuration
|
||||
internal;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_pass $upstream_authelia;
|
||||
|
||||
# Provide either X-Original-URL and X-Forwarded-Proto or
|
||||
# X-Forwarded-Proto, X-Forwarded-Host and X-Forwarded-URI or both.
|
||||
|
@ -297,17 +359,29 @@ http {
|
|||
# See https://expressjs.com/en/guide/behind-proxies.html
|
||||
proxy_set_header X-Original-Method $request_method;
|
||||
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 Content-Length "";
|
||||
proxy_set_header Connection "";
|
||||
|
||||
# Authelia can receive Proxy-Authorization to authenticate however most of the clients
|
||||
# support Authorization instead. Therefore we rewrite Authorization into Proxy-Authorization.
|
||||
proxy_set_header Proxy-Authorization $http_authorization;
|
||||
|
||||
## Basic Proxy Configuration
|
||||
proxy_pass_request_body off;
|
||||
proxy_set_header Content-Length "";
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1617,7 +1617,7 @@ notify-keyspace-events ""
|
|||
############################### GOPHER SERVER #################################
|
||||
|
||||
# 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
|
||||
# to the web, and the implementation both server and client side is so simple
|
||||
|
|
|
@ -1617,7 +1617,7 @@ notify-keyspace-events ""
|
|||
############################### GOPHER SERVER #################################
|
||||
|
||||
# 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
|
||||
# to the web, and the implementation both server and client side is so simple
|
||||
|
|
|
@ -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.tls.insecureSkipVerify=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:
|
||||
- '--accesslog=true'
|
||||
- '--api'
|
||||
|
|
|
@ -26,11 +26,11 @@
|
|||
"@fortawesome/free-solid-svg-icons": "6.2.1",
|
||||
"@fortawesome/react-fontawesome": "0.2.0",
|
||||
"@mui/icons-material": "5.11.0",
|
||||
"@mui/material": "5.11.6",
|
||||
"@mui/styles": "5.11.2",
|
||||
"@mui/material": "5.11.7",
|
||||
"@mui/styles": "5.11.7",
|
||||
"@simplewebauthn/browser": "7.0.1",
|
||||
"@simplewebauthn/typescript-types": "7.0.0",
|
||||
"axios": "1.2.6",
|
||||
"axios": "1.3.2",
|
||||
"broadcast-channel": "4.20.2",
|
||||
"classnames": "2.3.2",
|
||||
"i18next": "22.4.9",
|
||||
|
@ -39,7 +39,7 @@
|
|||
"qrcode.react": "3.1.0",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0",
|
||||
"react-i18next": "12.1.4",
|
||||
"react-i18next": "12.1.5",
|
||||
"react-loading": "2.0.3",
|
||||
"react-router-dom": "6.8.0",
|
||||
"react18-input-otp": "1.1.2",
|
||||
|
@ -82,7 +82,8 @@
|
|||
"^.+\\.(css|png|svg)$": "jest-transform-stub"
|
||||
},
|
||||
"transformIgnorePatterns": [
|
||||
"[/\\\\]node_modules[/\\\\].+\\.(js|jsx|mjs|cjs|ts|tsx)$"
|
||||
"[/\\\\]node_modules[/\\\\].+\\.(js|jsx|mjs|cjs|ts|tsx)$",
|
||||
"[/\\\\]node_modules[/\\\\](?!(@simplewebauthn)[/\\\\])"
|
||||
],
|
||||
"moduleNameMapper": {
|
||||
"^@root/(.*)$": [
|
||||
|
@ -150,14 +151,14 @@
|
|||
"@testing-library/jest-dom": "5.16.5",
|
||||
"@testing-library/react": "13.4.0",
|
||||
"@types/jest": "29.4.0",
|
||||
"@types/node": "18.11.18",
|
||||
"@types/node": "18.11.19",
|
||||
"@types/qrcode.react": "1.0.2",
|
||||
"@types/react": "18.0.27",
|
||||
"@types/react-dom": "18.0.10",
|
||||
"@types/zxcvbn": "4.4.1",
|
||||
"@typescript-eslint/eslint-plugin": "5.49.0",
|
||||
"@typescript-eslint/parser": "5.49.0",
|
||||
"@vitejs/plugin-react": "3.0.1",
|
||||
"@typescript-eslint/eslint-plugin": "5.50.0",
|
||||
"@typescript-eslint/parser": "5.50.0",
|
||||
"@vitejs/plugin-react": "3.1.0",
|
||||
"esbuild": "0.17.5",
|
||||
"esbuild-jest": "0.5.0",
|
||||
"eslint": "8.33.0",
|
||||
|
@ -177,8 +178,8 @@
|
|||
"jest-watch-typeahead": "2.2.2",
|
||||
"prettier": "2.8.3",
|
||||
"react-test-renderer": "18.2.0",
|
||||
"typescript": "4.9.4",
|
||||
"vite": "4.0.4",
|
||||
"typescript": "4.9.5",
|
||||
"vite": "4.1.1",
|
||||
"vite-plugin-eslint": "1.8.1",
|
||||
"vite-plugin-istanbul": "4.0.0",
|
||||
"vite-plugin-svgr": "2.4.0",
|
||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue