Merge branch 'master' into patch-1
commit
7a2c830b2e
|
@ -25,3 +25,5 @@ authelia-image-dev.tar
|
||||||
|
|
||||||
/authelia
|
/authelia
|
||||||
__debug_bin
|
__debug_bin
|
||||||
|
|
||||||
|
internal/suites/common/pki/ca/ca.private.pem
|
||||||
|
|
|
@ -15,7 +15,7 @@ RUN yarn global add pnpm && \
|
||||||
# =======================================
|
# =======================================
|
||||||
# ===== Build image for the backend =====
|
# ===== Build image for the backend =====
|
||||||
# =======================================
|
# =======================================
|
||||||
FROM golang:1.19.5-alpine AS builder-backend
|
FROM golang:1.20.0-alpine AS builder-backend
|
||||||
|
|
||||||
WORKDIR /go/src/app
|
WORKDIR /go/src/app
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ RUN yarn install --frozen-lockfile && yarn build
|
||||||
# =======================================
|
# =======================================
|
||||||
# ===== Build image for the backend =====
|
# ===== Build image for the backend =====
|
||||||
# =======================================
|
# =======================================
|
||||||
FROM golang:1.19.5-alpine AS builder-backend
|
FROM golang:1.20.0-alpine AS builder-backend
|
||||||
|
|
||||||
WORKDIR /go/src/app
|
WORKDIR /go/src/app
|
||||||
|
|
||||||
|
|
|
@ -816,7 +816,7 @@ paths:
|
||||||
summary: OAuth 2.0 Authorization Server Metadata
|
summary: OAuth 2.0 Authorization Server Metadata
|
||||||
description: >
|
description: >
|
||||||
This endpoint retrieves the OAuth 2.0 Authorization Server Metadata document (RFC8414) used by clients to
|
This endpoint retrieves the OAuth 2.0 Authorization Server Metadata document (RFC8414) used by clients to
|
||||||
perform discovery for an OAuth 2.0 Authorization Server. See https://www.rfc-editor.org/rfc/rfc8414.
|
perform discovery for an OAuth 2.0 Authorization Server. See https://datatracker.ietf.org/doc/html/rfc8414.
|
||||||
responses:
|
responses:
|
||||||
"200":
|
"200":
|
||||||
description: OK
|
description: OK
|
||||||
|
@ -2822,8 +2822,8 @@ components:
|
||||||
description: >
|
description: >
|
||||||
JSON array containing a list of the JWS [JWS] signing algorithms (alg values) [JWA] supported by the
|
JSON array containing a list of the JWS [JWS] signing algorithms (alg values) [JWA] supported by the
|
||||||
UserInfo Endpoint to encode the Claims in a JWT [JWT]. The value none MAY be included. See Also:
|
UserInfo Endpoint to encode the Claims in a JWT [JWT]. The value none MAY be included. See Also:
|
||||||
JWS: https://datatracker.ietf.org/doc/html/rfc7515 JWA: https://datatracker.ietf.org/doc/html/rfc7518 JWT:
|
JWS: https://datatracker.ietf.org/doc/html/rfc7515 JWA: https://datatracker.ietf.org/doc/html/rfc7518
|
||||||
https://datatracker.ietf.org/doc/html/rfc7519
|
JWT: https://datatracker.ietf.org/doc/html/rfc7519
|
||||||
type: array
|
type: array
|
||||||
example: ["none", "RS256"]
|
example: ["none", "RS256"]
|
||||||
items:
|
items:
|
||||||
|
|
|
@ -108,8 +108,9 @@ func genCLIDocWriteIndex(path, name string) (err error) {
|
||||||
func prepend(input string) string {
|
func prepend(input string) string {
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
|
|
||||||
pathz := strings.Split(strings.Replace(input, ".md", "", 1), "\\")
|
_, filename := filepath.Split(strings.Replace(input, ".md", "", 1))
|
||||||
parts := strings.Split(pathz[len(pathz)-1], "_")
|
|
||||||
|
parts := strings.Split(filename, "_")
|
||||||
|
|
||||||
cmd := parts[0]
|
cmd := parts[0]
|
||||||
|
|
||||||
|
|
|
@ -64,7 +64,7 @@ func cmdBootstrapRun(_ *cobra.Command, _ []string) {
|
||||||
|
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
bootstrapPrintln("Run 'authelia-scripts suites setup Standalone' to start Authelia and visit https://home.example.com:8080.")
|
bootstrapPrintln("Run 'authelia-scripts suites setup Standalone' to start Authelia and visit https://home.example.com:8080.")
|
||||||
bootstrapPrintln("More details at https://github.com/authelia/authelia/blob/master/docs/getting-started.md")
|
bootstrapPrintln("More details at https://www.authelia.com/contributing/development/build-and-test/")
|
||||||
}
|
}
|
||||||
|
|
||||||
var hostEntries = []HostEntry{
|
var hostEntries = []HostEntry{
|
||||||
|
|
|
@ -426,7 +426,7 @@ authentication_backend:
|
||||||
## changed once attributed to a user otherwise it would break the configuration for that user. Technically,
|
## changed once attributed to a user otherwise it would break the configuration for that user. Technically,
|
||||||
## non-unique attributes like 'mail' can also be used but we don't recommend using them, we instead advise to use
|
## non-unique attributes like 'mail' can also be used but we don't recommend using them, we instead advise to use
|
||||||
## a filter to perform alternative lookups and the attributes mentioned above (sAMAccountName and uid) to
|
## a filter to perform alternative lookups and the attributes mentioned above (sAMAccountName and uid) to
|
||||||
## follow https://www.ietf.org/rfc/rfc2307.txt.
|
## follow https://datatracker.ietf.org/doc/html/rfc2307.
|
||||||
# username_attribute: uid
|
# username_attribute: uid
|
||||||
|
|
||||||
## The additional_users_dn is prefixed to base_dn and delimited by a comma when searching for users.
|
## The additional_users_dn is prefixed to base_dn and delimited by a comma when searching for users.
|
||||||
|
|
|
@ -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/"
|
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].
|
Controls the hashing cost when hashing passwords using [Bcrypt].
|
||||||
|
|
||||||
[Argon2]: https://www.rfc-editor.org/rfc/rfc9106.html
|
[Argon2]: https://datatracker.ietf.org/doc/html/rfc9106
|
||||||
[Scrypt]: https://en.wikipedia.org/wiki/Scrypt
|
[Scrypt]: https://en.wikipedia.org/wiki/Scrypt
|
||||||
[PBKDF2]: https://www.ietf.org/rfc/rfc2898.html
|
[PBKDF2]: https://datatracker.ietf.org/doc/html/rfc2898
|
||||||
[SHA2 Crypt]: https://www.akkadia.org/drepper/SHA-crypt.txt
|
[SHA2 Crypt]: https://www.akkadia.org/drepper/SHA-crypt.txt
|
||||||
[Bcrypt]: https://en.wikipedia.org/wiki/Bcrypt
|
[Bcrypt]: https://en.wikipedia.org/wiki/Bcrypt
|
||||||
|
|
|
@ -316,4 +316,4 @@ for your users.
|
||||||
|
|
||||||
[username attribute]: #usernameattribute
|
[username attribute]: #usernameattribute
|
||||||
[TechNet wiki]: https://social.technet.microsoft.com/wiki/contents/articles/5392.active-directory-ldap-syntax-filters.aspx
|
[TechNet wiki]: https://social.technet.microsoft.com/wiki/contents/articles/5392.active-directory-ldap-syntax-filters.aspx
|
||||||
[RFC2307]: https://www.rfc-editor.org/rfc/rfc2307.html
|
[RFC2307]: https://datatracker.ietf.org/doc/html/rfc2307
|
||||||
|
|
|
@ -119,7 +119,7 @@ identity_providers:
|
||||||
clients:
|
clients:
|
||||||
- id: myapp
|
- id: myapp
|
||||||
description: My Application
|
description: My Application
|
||||||
secret: '$plaintext$this_is_a_secret'
|
secret: '$pbkdf2-sha512$310000$c8p78n7pUMln0jzvd4aK4Q$JNRBzwAo0ek5qKn50cFzzvE9RXV88h1wJn5KGiHrD0YKtZaR/nCb2CJPOsKaPK0hjf.9yHxzQGZziziccp6Yng' # The digest of 'insecure_secret'.
|
||||||
sector_identifier: ''
|
sector_identifier: ''
|
||||||
public: false
|
public: false
|
||||||
authorization_policy: two_factor
|
authorization_policy: two_factor
|
||||||
|
@ -170,9 +170,9 @@ encoded PEM format used to sign/encrypt the [OpenID Connect 1.0] [JWT]'s. When c
|
||||||
JSON key's in the JWKs [Discoverable Endpoint](../../integration/openid-connect/introduction.md#discoverable-endpoints)
|
JSON key's in the JWKs [Discoverable Endpoint](../../integration/openid-connect/introduction.md#discoverable-endpoints)
|
||||||
as per [RFC7517].
|
as per [RFC7517].
|
||||||
|
|
||||||
[RFC7517]: https://www.rfc-editor.org/rfc/rfc7517
|
[RFC7517]: https://datatracker.ietf.org/doc/html/rfc7517
|
||||||
[x5c]: https://www.rfc-editor.org/rfc/rfc7517#section-4.7
|
[x5c]: https://datatracker.ietf.org/doc/html/rfc7517#section-4.7
|
||||||
[x5t]: https://www.rfc-editor.org/rfc/rfc7517#section-4.8
|
[x5t]: https://datatracker.ietf.org/doc/html/rfc7517#section-4.8
|
||||||
|
|
||||||
The first certificate in the chain must have the public key for the [issuer_private_key](#issuerprivatekey), each
|
The first certificate in the chain must have the public key for the [issuer_private_key](#issuerprivatekey), each
|
||||||
certificate in the chain must be valid for the current date, and each certificate in the chain should be signed by the
|
certificate in the chain must be valid for the current date, and each certificate in the chain should be signed by the
|
||||||
|
@ -251,7 +251,7 @@ this value.
|
||||||
|
|
||||||
{{< confkey type="string" default="public_clients_only" required="no" >}}
|
{{< confkey type="string" default="public_clients_only" required="no" >}}
|
||||||
|
|
||||||
[Proof Key for Code Exchange](https://www.rfc-editor.org/rfc/rfc7636.html) enforcement policy: if specified, must be
|
[Proof Key for Code Exchange](https://datatracker.ietf.org/doc/html/rfc7636) enforcement policy: if specified, must be
|
||||||
either `never`, `public_clients_only` or `always`.
|
either `never`, `public_clients_only` or `always`.
|
||||||
|
|
||||||
If set to `public_clients_only` (default), [PKCE] will be required for public clients using the
|
If set to `public_clients_only` (default), [PKCE] will be required for public clients using the
|
||||||
|
@ -402,9 +402,6 @@ This enables the public client type for this client. This is for clients that ar
|
||||||
confidentiality of credentials, you can read more about client types in [RFC6749 Section 2.1]. This is particularly
|
confidentiality of credentials, you can read more about client types in [RFC6749 Section 2.1]. This is particularly
|
||||||
useful for SPA's and CLI tools. This option requires setting the [client secret](#secret) to a blank string.
|
useful for SPA's and CLI tools. This option requires setting the [client secret](#secret) to a blank string.
|
||||||
|
|
||||||
In addition to the standard rules for redirect URIs, public clients can use the `urn:ietf:wg:oauth:2.0:oob` redirect
|
|
||||||
URI.
|
|
||||||
|
|
||||||
#### redirect_uris
|
#### redirect_uris
|
||||||
|
|
||||||
{{< confkey type="list(string)" required="yes" >}}
|
{{< confkey type="list(string)" required="yes" >}}
|
||||||
|
@ -420,7 +417,6 @@ their redirect URIs are as follows:
|
||||||
attempt to authorize will fail and an error will be generated.
|
attempt to authorize will fail and an error will be generated.
|
||||||
2. The redirect URIs are case-sensitive.
|
2. The redirect URIs are case-sensitive.
|
||||||
3. The URI must include a scheme and that scheme must be one of `http` or `https`.
|
3. The URI must include a scheme and that scheme must be one of `http` or `https`.
|
||||||
4. The client can ignore rule 3 and use `urn:ietf:wg:oauth:2.0:oob` if it is a [public](#public) client type.
|
|
||||||
|
|
||||||
#### audience
|
#### audience
|
||||||
|
|
||||||
|
@ -434,30 +430,41 @@ A list of audiences this client is allowed to request.
|
||||||
|
|
||||||
A list of scopes to allow this client to consume. See
|
A list of scopes to allow this client to consume. See
|
||||||
[scope definitions](../../integration/openid-connect/introduction.md#scope-definitions) for more information. The
|
[scope definitions](../../integration/openid-connect/introduction.md#scope-definitions) for more information. The
|
||||||
documentation for the application you want to use with Authelia will most-likely provide you with the scopes to allow.
|
documentation for the application you are trying to configure [OpenID Connect 1.0] for will likely have a list of scopes
|
||||||
|
or claims required which can be matched with the above guide.
|
||||||
|
|
||||||
#### grant_types
|
#### grant_types
|
||||||
|
|
||||||
{{< confkey type="list(string)" default="refresh_token, authorization_code" required="no" >}}
|
{{< confkey type="list(string)" default="refresh_token, authorization_code" required="no" >}}
|
||||||
|
|
||||||
A list of grant types this client can return. *It is recommended that this isn't configured at this time unless you
|
*__Important Note:__ It is recommended that this isn't configured at this time unless you know what you're doing.*
|
||||||
know what you're doing*. Valid options are: `implicit`, `refresh_token`, `authorization_code`, `password`,
|
|
||||||
`client_credentials`.
|
The list of grant types this client is permitted to use in order to obtain access to the relevant tokens.
|
||||||
|
|
||||||
|
See the [Grant Types](../../integration/openid-connect/introduction.md#grant-types) section of the
|
||||||
|
[OpenID Connect 1.0 Integration Guide](../../integration/openid-connect/introduction.md#grant-types) for more information.
|
||||||
|
|
||||||
#### response_types
|
#### response_types
|
||||||
|
|
||||||
{{< confkey type="list(string)" default="code" required="no" >}}
|
{{< confkey type="list(string)" default="code" required="no" >}}
|
||||||
|
|
||||||
A list of response types this client can return. *It is recommended that this isn't configured at this time unless you
|
*__Important Note:__ It is recommended that this isn't configured at this time unless you know what you're doing.*
|
||||||
know what you're doing*. Valid options are: `code`, `code id_token`, `id_token`, `token id_token`, `token`,
|
|
||||||
`token id_token code`.
|
A list of response types this client supports.
|
||||||
|
|
||||||
|
See the [Response Types](../../integration/openid-connect/introduction.md#response-types) section of the
|
||||||
|
[OpenID Connect 1.0 Integration Guide](../../integration/openid-connect/introduction.md#response-types) for more information.
|
||||||
|
|
||||||
#### response_modes
|
#### response_modes
|
||||||
|
|
||||||
{{< confkey type="list(string)" default="form_post, query, fragment" required="no" >}}
|
{{< confkey type="list(string)" default="form_post, query, fragment" required="no" >}}
|
||||||
|
|
||||||
A list of response modes this client can return. It is recommended that this isn't configured at this time unless you
|
*__Important Note:__ It is recommended that this isn't configured at this time unless you know what you're doing.*
|
||||||
know what you're doing. Potential values are `form_post`, `query`, and `fragment`.
|
|
||||||
|
A list of response modes this client supports.
|
||||||
|
|
||||||
|
See the [Response Modes](../../integration/openid-connect/introduction.md#response-modes) section of the
|
||||||
|
[OpenID Connect 1.0 Integration Guide](../../integration/openid-connect/introduction.md#response-modes) for more information.
|
||||||
|
|
||||||
#### authorization_policy
|
#### authorization_policy
|
||||||
|
|
||||||
|
@ -495,14 +502,18 @@ more information.
|
||||||
|
|
||||||
{{< confkey type="string" default="auto" required="no" >}}
|
{{< confkey type="string" default="auto" required="no" >}}
|
||||||
|
|
||||||
|
*__Important Note:__ the `implicit` consent mode is not technically part of the specification. It theoretically could be
|
||||||
|
misused in certain conditions specifically with public clients or when the client credentials (i.e. client secret) has
|
||||||
|
been exposed to an attacker. For these reasons this mode is discouraged.*
|
||||||
|
|
||||||
Configures the consent mode. The following table describes the different modes:
|
Configures the consent mode. The following table describes the different modes:
|
||||||
|
|
||||||
| Value | Description |
|
| Value | Description |
|
||||||
|:--------------:|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|
|
|:--------------:|:----------------------------------------------------------------------------------------------------------------------------------------------:|
|
||||||
| auto | Automatically determined (default). Uses `explicit` unless [pre_configured_consent_duration] is specified in which case uses `pre-configured`. |
|
| auto | Automatically determined (default). Uses `explicit` unless [pre_configured_consent_duration] is specified in which case uses `pre-configured`. |
|
||||||
| explicit | Requires the user provide unique explicit consent for every authorization. |
|
| explicit | Requires the user provide unique explicit consent for every authorization. |
|
||||||
| implicit | Automatically assumes consent for every authorization, never asking the user if they wish to give consent. *__Note:__* this option is not technically part of the specification. |
|
| implicit | Automatically assumes consent for every authorization, never asking the user if they wish to give consent. |
|
||||||
| pre-configured | Allows the end-user to remember their consent for the [pre_configured_consent_duration]. |
|
| pre-configured | Allows the end-user to remember their consent for the [pre_configured_consent_duration]. |
|
||||||
|
|
||||||
[pre_configured_consent_duration]: #preconfiguredconsentduration
|
[pre_configured_consent_duration]: #preconfiguredconsentduration
|
||||||
|
|
||||||
|
@ -530,12 +541,12 @@ To integrate Authelia's [OpenID Connect 1.0] implementation with a relying party
|
||||||
|
|
||||||
[token lifespan]: https://docs.apigee.com/api-platform/antipatterns/oauth-long-expiration
|
[token lifespan]: https://docs.apigee.com/api-platform/antipatterns/oauth-long-expiration
|
||||||
[OpenID Connect 1.0]: https://openid.net/connect/
|
[OpenID Connect 1.0]: https://openid.net/connect/
|
||||||
[JWT]: https://www.rfc-editor.org/rfc/rfc7519.html
|
[JWT]: https://datatracker.ietf.org/doc/html/rfc7519
|
||||||
[RFC6234]: https://www.rfc-editor.org/rfc/rfc6234.html
|
[RFC6234]: https://datatracker.ietf.org/doc/html/rfc6234
|
||||||
[RFC4648]: https://www.rfc-editor.org/rfc/rfc4648.html
|
[RFC4648]: https://datatracker.ietf.org/doc/html/rfc4648
|
||||||
[RFC7468]: https://www.rfc-editor.org/rfc/rfc7468.html
|
[RFC7468]: https://datatracker.ietf.org/doc/html/rfc7468
|
||||||
[RFC6749 Section 2.1]: https://www.rfc-editor.org/rfc/rfc6749.html#section-2.1
|
[RFC6749 Section 2.1]: https://datatracker.ietf.org/doc/html/rfc6749#section-2.1
|
||||||
[PKCE]: https://www.rfc-editor.org/rfc/rfc7636.html
|
[PKCE]: https://datatracker.ietf.org/doc/html/rfc7636
|
||||||
[Authorization Code Flow]: https://openid.net/specs/openid-connect-core-1_0.html#CodeFlowAuth
|
[Authorization Code Flow]: https://openid.net/specs/openid-connect-core-1_0.html#CodeFlowAuth
|
||||||
[Subject Identifier Type]: https://openid.net/specs/openid-connect-core-1_0.html#SubjectIDTypes
|
[Subject Identifier Type]: https://openid.net/specs/openid-connect-core-1_0.html#SubjectIDTypes
|
||||||
[Pairwise Identifier Algorithm]: https://openid.net/specs/openid-connect-core-1_0.html#PairwiseAlg
|
[Pairwise Identifier Algorithm]: https://openid.net/specs/openid-connect-core-1_0.html#PairwiseAlg
|
||||||
|
|
|
@ -164,7 +164,7 @@ characters and the user password is changed to this value.
|
||||||
{{< confkey type="string" required="yes" >}}
|
{{< confkey type="string" required="yes" >}}
|
||||||
|
|
||||||
The sender is used to construct both the SMTP command `MAIL FROM` and to add the `FROM` header. This address must be
|
The sender is used to construct both the SMTP command `MAIL FROM` and to add the `FROM` header. This address must be
|
||||||
in [RFC5322](https://www.rfc-editor.org/rfc/rfc5322.html#section-3.4) format. This means it must one of two formats:
|
in [RFC5322](https://datatracker.ietf.org/doc/html/rfc5322#section-3.4) format. This means it must one of two formats:
|
||||||
|
|
||||||
* jsmith@domain.com
|
* jsmith@domain.com
|
||||||
* John Smith <jsmith@domain.com>
|
* John Smith <jsmith@domain.com>
|
||||||
|
|
|
@ -35,10 +35,18 @@ The way this format works is you can either configure an integer or a string in
|
||||||
supply an integer, it is considered a representation of seconds. If you supply a string, it parses the string in blocks
|
supply an integer, it is considered a representation of seconds. If you supply a string, it parses the string in blocks
|
||||||
of quantities and units (number followed by a unit letter). For example `5h` indicates a quantity of 5 units of `h`.
|
of quantities and units (number followed by a unit letter). For example `5h` indicates a quantity of 5 units of `h`.
|
||||||
|
|
||||||
|
The following is ignored:
|
||||||
|
- all spaces
|
||||||
|
- leading zeros
|
||||||
|
|
||||||
While you can use multiple of these blocks in combination, we suggest keeping it simple and use a single value.
|
While you can use multiple of these blocks in combination, we suggest keeping it simple and use a single value.
|
||||||
|
|
||||||
### Unit Legend
|
### Unit Legend
|
||||||
|
|
||||||
|
#### Short Units
|
||||||
|
|
||||||
|
These values have been available for a long time.
|
||||||
|
|
||||||
| Unit | Associated Letter |
|
| Unit | Associated Letter |
|
||||||
|:-------:|:-----------------:|
|
|:-------:|:-----------------:|
|
||||||
| Years | y |
|
| Years | y |
|
||||||
|
@ -49,6 +57,21 @@ While you can use multiple of these blocks in combination, we suggest keeping it
|
||||||
| Minutes | m |
|
| Minutes | m |
|
||||||
| Seconds | s |
|
| Seconds | s |
|
||||||
|
|
||||||
|
#### Long Units
|
||||||
|
|
||||||
|
These values are more human readable but have only been available since v4.38.0.
|
||||||
|
|
||||||
|
| Unit | Human Readable Long Unit |
|
||||||
|
|:------------:|:-----------------------------:|
|
||||||
|
| Years | `year`, `years` |
|
||||||
|
| Months | `month`, `months` |
|
||||||
|
| Weeks | `week`, `weeks` |
|
||||||
|
| Days | `day`, `days` |
|
||||||
|
| Hours | `hour`, `hours` |
|
||||||
|
| Minutes | `minute`, `minutes` |
|
||||||
|
| Seconds | `second`, `seconds` |
|
||||||
|
| Milliseconds | `millisecond`, `milliseconds` |
|
||||||
|
|
||||||
### Examples
|
### Examples
|
||||||
|
|
||||||
| Desired Value | Configuration Examples |
|
| Desired Value | Configuration Examples |
|
||||||
|
@ -154,7 +177,7 @@ The value must be one or more certificates encoded in the DER base64 ([RFC4648])
|
||||||
|
|
||||||
### private_key
|
### private_key
|
||||||
|
|
||||||
{{< confkey type="string" required="yes" >}}
|
{{< confkey type="string" required="no" >}}
|
||||||
|
|
||||||
*__Important Note:__ This can also be defined using a [secret](../methods/secrets.md) which is __strongly recommended__
|
*__Important Note:__ This can also be defined using a [secret](../methods/secrets.md) which is __strongly recommended__
|
||||||
especially for containerized deployments.*
|
especially for containerized deployments.*
|
||||||
|
@ -163,6 +186,8 @@ The private key to be used with the [certificate_chain](#certificatechain) for m
|
||||||
|
|
||||||
The value must be one private key encoded in the DER base64 ([RFC4648]) encoded PEM format.
|
The value must be one private key encoded in the DER base64 ([RFC4648]) encoded PEM format.
|
||||||
|
|
||||||
|
[RFC4648]: https://datatracker.ietf.org/doc/html/rfc4648
|
||||||
|
|
||||||
## Server Buffers
|
## Server Buffers
|
||||||
|
|
||||||
### read
|
### read
|
||||||
|
|
|
@ -172,5 +172,5 @@ at least a minimal configuration that has the storage backend connection details
|
||||||
See the [CLI Documentation](../../reference/cli/authelia/authelia_storage_user_totp_export.md) for methods to perform
|
See the [CLI Documentation](../../reference/cli/authelia/authelia_storage_user_totp_export.md) for methods to perform
|
||||||
exports.
|
exports.
|
||||||
|
|
||||||
[RFC4226]: https://www.rfc-editor.org/rfc/rfc4226.html
|
[RFC4226]: https://datatracker.ietf.org/doc/html/rfc4226
|
||||||
[RFC6238]: https://www.rfc-editor.org/rfc/rfc6238.html
|
[RFC6238]: https://datatracker.ietf.org/doc/html/rfc6238
|
||||||
|
|
|
@ -588,8 +588,8 @@ The match type `Equals` matches if the value extracted from the pattern is equal
|
||||||
match value is a list/slice).
|
match value is a list/slice).
|
||||||
|
|
||||||
The regex groups are case-insensitive due to the fact that the regex groups are used in domain criteria and domain names
|
The regex groups are case-insensitive due to the fact that the regex groups are used in domain criteria and domain names
|
||||||
should not be compared in a case-sensitive way as per the [RFC4343](https://www.rfc-editor.org/rfc/rfc4343.html)
|
should not be compared in a case-sensitive way as per the [RFC4343](https://datatracker.ietf.org/doc/html/rfc4343)
|
||||||
abstract and [RFC3986 Section 3.2.2](https://www.rfc-editor.org/rfc/rfc3986#section-3.2.2).
|
abstract and [RFC3986 Section 3.2.2](https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.2).
|
||||||
|
|
||||||
We do not currently apply any other normalization to usernames or groups when matching these groups. As such it's
|
We do not currently apply any other normalization to usernames or groups when matching these groups. As such it's
|
||||||
generally *__not recommended__* to use these patterns with usernames or groups which contain characters that are not
|
generally *__not recommended__* to use these patterns with usernames or groups which contain characters that are not
|
||||||
|
@ -664,6 +664,6 @@ access_control:
|
||||||
policy: bypass
|
policy: bypass
|
||||||
```
|
```
|
||||||
|
|
||||||
[RFC7231]: https://www.rfc-editor.org/rfc/rfc7231.html
|
[RFC7231]: https://datatracker.ietf.org/doc/html/rfc7231
|
||||||
[RFC5789]: https://www.rfc-editor.org/rfc/rfc5789.html
|
[RFC5789]: https://datatracker.ietf.org/doc/html/rfc5789
|
||||||
[RFC4918]: https://www.rfc-editor.org/rfc/rfc4918.html
|
[RFC4918]: https://datatracker.ietf.org/doc/html/rfc4918
|
||||||
|
|
|
@ -137,11 +137,12 @@ cookies for this domain.
|
||||||
For example if Authelia is accessible via the URL `https://auth.example.com` the domain should be either
|
For example if Authelia is accessible via the URL `https://auth.example.com` the domain should be either
|
||||||
`auth.example.com` or `example.com`.
|
`auth.example.com` or `example.com`.
|
||||||
|
|
||||||
Please note most good DynamicDNS solutions fall into a specially protected group of domains and browsers do not allow
|
The value must not match a domain on the [Public Suffix List](https://publicsuffix.org/list/) as 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`
|
websites to write cookies for these domains. This includes most Dynamic DNS services such as `duckdns.org`. You should
|
||||||
for the domain value as browsers will not allow `john.duckdns.org` to read or write cookies for `duckdns.org`.
|
use your domain instead of `duckdns.org` for this value, for example `example.duckdns.org`.
|
||||||
|
|
||||||
Consequently, if you have `john.duckdns.org` and `mary.duckdns.org` you cannot share cookies between these domains.
|
Consequently, if you have `example.duckdns.org` and `example-auth.duckdns.org` you cannot share cookies between these
|
||||||
|
domains.
|
||||||
|
|
||||||
#### authelia_url
|
#### authelia_url
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ In order to build and contribute to __Authelia__, you need to make sure the foll
|
||||||
* General:
|
* General:
|
||||||
* [git]
|
* [git]
|
||||||
* Backend Development:
|
* Backend Development:
|
||||||
* [go] *(v1.19 or greater)*
|
* [go] *(v1.20 or greater)*
|
||||||
* [gcc]
|
* [gcc]
|
||||||
* Frontend Development
|
* Frontend Development
|
||||||
* [Node.js] *(v18 or greater)*
|
* [Node.js] *(v18 or greater)*
|
||||||
|
|
|
@ -22,14 +22,7 @@ community: true
|
||||||
|
|
||||||
## Before You Begin
|
## Before You Begin
|
||||||
|
|
||||||
### Common Notes
|
{{% oidc-common %}}
|
||||||
|
|
||||||
1. You are *__required__* to utilize a unique client id for every client.
|
|
||||||
2. The client id on this page is merely an example and you can theoretically use any alphanumeric string.
|
|
||||||
3. You *__should not__* use the client secret in this example, We *__strongly recommend__* reading the
|
|
||||||
[Generating Client Secrets] guide instead.
|
|
||||||
|
|
||||||
[Generating Client Secrets]: ../specific-information.md#generating-client-secrets
|
|
||||||
|
|
||||||
### Assumptions
|
### Assumptions
|
||||||
|
|
||||||
|
@ -38,7 +31,7 @@ This example makes the following assumptions:
|
||||||
* __Application Root URL:__ `https://guacamole.example.com`
|
* __Application Root URL:__ `https://guacamole.example.com`
|
||||||
* __Authelia Root URL:__ `https://auth.example.com`
|
* __Authelia Root URL:__ `https://auth.example.com`
|
||||||
* __Client ID:__ `guacamole`
|
* __Client ID:__ `guacamole`
|
||||||
* __Client Secret:__ `guacamole_client_secret`
|
* __Client Secret:__ `insecure_secret`
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
|
@ -66,7 +59,7 @@ The following YAML configuration is an example __Authelia__
|
||||||
```yaml
|
```yaml
|
||||||
- id: guacamole
|
- id: guacamole
|
||||||
description: Apache Guacamole
|
description: Apache Guacamole
|
||||||
secret: '$plaintext$guacamole_client_secret'
|
secret: '$pbkdf2-sha512$310000$c8p78n7pUMln0jzvd4aK4Q$JNRBzwAo0ek5qKn50cFzzvE9RXV88h1wJn5KGiHrD0YKtZaR/nCb2CJPOsKaPK0hjf.9yHxzQGZziziccp6Yng' # The digest of 'insecure_secret'.
|
||||||
public: false
|
public: false
|
||||||
authorization_policy: two_factor
|
authorization_policy: two_factor
|
||||||
redirect_uris:
|
redirect_uris:
|
||||||
|
|
|
@ -22,14 +22,7 @@ community: true
|
||||||
|
|
||||||
## Before You Begin
|
## Before You Begin
|
||||||
|
|
||||||
### Common Notes
|
{{% oidc-common %}}
|
||||||
|
|
||||||
1. You are *__required__* to utilize a unique client id for every client.
|
|
||||||
2. The client id on this page is merely an example and you can theoretically use any alphanumeric string.
|
|
||||||
3. You *__should not__* use the client secret in this example, We *__strongly recommend__* reading the
|
|
||||||
[Generating Client Secrets] guide instead.
|
|
||||||
|
|
||||||
[Generating Client Secrets]: ../specific-information.md#generating-client-secrets
|
|
||||||
|
|
||||||
### Assumptions
|
### Assumptions
|
||||||
|
|
||||||
|
@ -38,7 +31,7 @@ This example makes the following assumptions:
|
||||||
* __Application Root URL:__ `https://argocd.example.com`
|
* __Application Root URL:__ `https://argocd.example.com`
|
||||||
* __Authelia Root URL:__ `https://auth.example.com`
|
* __Authelia Root URL:__ `https://auth.example.com`
|
||||||
* __Client ID:__ `argocd`
|
* __Client ID:__ `argocd`
|
||||||
* __Client Secret:__ `argocd_client_secret`
|
* __Client Secret:__ `insecure_secret`
|
||||||
* __CLI Client ID:__ `argocd-cli`
|
* __CLI Client ID:__ `argocd-cli`
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
@ -51,7 +44,7 @@ To configure [Argo CD] to utilize Authelia as an [OpenID Connect 1.0] Provider u
|
||||||
name: Authelia
|
name: Authelia
|
||||||
issuer: https://auth.example.com
|
issuer: https://auth.example.com
|
||||||
clientID: argocd
|
clientID: argocd
|
||||||
clientSecret: argocd_client_secret
|
clientSecret: insecure_secret
|
||||||
cliClientID: argocd-cli
|
cliClientID: argocd-cli
|
||||||
requestedScopes:
|
requestedScopes:
|
||||||
- openid
|
- openid
|
||||||
|
@ -69,7 +62,7 @@ which will operate with the above example:
|
||||||
```yaml
|
```yaml
|
||||||
- id: argocd
|
- id: argocd
|
||||||
description: Argo CD
|
description: Argo CD
|
||||||
secret: '$plaintext$argocd_client_secret'
|
secret: '$pbkdf2-sha512$310000$c8p78n7pUMln0jzvd4aK4Q$JNRBzwAo0ek5qKn50cFzzvE9RXV88h1wJn5KGiHrD0YKtZaR/nCb2CJPOsKaPK0hjf.9yHxzQGZziziccp6Yng' # The digest of 'insecure_secret'.
|
||||||
public: false
|
public: false
|
||||||
authorization_policy: two_factor
|
authorization_policy: two_factor
|
||||||
redirect_uris:
|
redirect_uris:
|
||||||
|
|
|
@ -22,14 +22,7 @@ community: true
|
||||||
|
|
||||||
## Before You Begin
|
## Before You Begin
|
||||||
|
|
||||||
### Common Notes
|
{{% oidc-common %}}
|
||||||
|
|
||||||
1. You are *__required__* to utilize a unique client id for every client.
|
|
||||||
2. The client id on this page is merely an example and you can theoretically use any alphanumeric string.
|
|
||||||
3. You *__should not__* use the client secret in this example, We *__strongly recommend__* reading the
|
|
||||||
[Generating Client Secrets] guide instead.
|
|
||||||
|
|
||||||
[Generating Client Secrets]: ../specific-information.md#generating-client-secrets
|
|
||||||
|
|
||||||
### Assumptions
|
### Assumptions
|
||||||
|
|
||||||
|
@ -38,13 +31,13 @@ This example makes the following assumptions:
|
||||||
* __Application Root URL:__ `https://bookstack.example.com`
|
* __Application Root URL:__ `https://bookstack.example.com`
|
||||||
* __Authelia Root URL:__ `https://auth.example.com`
|
* __Authelia Root URL:__ `https://auth.example.com`
|
||||||
* __Client ID:__ `bookstack`
|
* __Client ID:__ `bookstack`
|
||||||
* __Client Secret:__ `bookstack_client_secret`
|
* __Client Secret:__ `insecure_secret`
|
||||||
|
|
||||||
*__Important Note:__ [BookStack] does not properly URL encode the secret per [RFC6749 Appendix B] at the time this
|
*__Important Note:__ [BookStack] does not properly URL encode the secret per [RFC6749 Appendix B] at the time this
|
||||||
article was last modified (noted at the bottom). This means you'll either have to use only alphanumeric characters for
|
article was last modified (noted at the bottom). This means you'll either have to use only alphanumeric characters for
|
||||||
the secret or URL encode the secret yourself.*
|
the secret or URL encode the secret yourself.*
|
||||||
|
|
||||||
[RFC6749 Appendix B]: https://www.rfc-editor.org/rfc/rfc6749#appendix-B
|
[RFC6749 Appendix B]: https://datatracker.ietf.org/doc/html/rfc6749#appendix-B
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
|
@ -58,7 +51,7 @@ To configure [BookStack] to utilize Authelia as an [OpenID Connect 1.0] Provider
|
||||||
2. OIDC_NAME: `Authelia`
|
2. OIDC_NAME: `Authelia`
|
||||||
3. OIDC_DISPLAY_NAME_CLAIMS: `name`
|
3. OIDC_DISPLAY_NAME_CLAIMS: `name`
|
||||||
4. OIDC_CLIENT_ID: `bookstack`
|
4. OIDC_CLIENT_ID: `bookstack`
|
||||||
5. OIDC_CLIENT_SECRET: `bookstack_client_secret`
|
5. OIDC_CLIENT_SECRET: `insecure_secret`
|
||||||
6. OIDC_ISSUER: `https://auth.example.com`
|
6. OIDC_ISSUER: `https://auth.example.com`
|
||||||
7. OIDC_ISSUER_DISCOVER: `true`
|
7. OIDC_ISSUER_DISCOVER: `true`
|
||||||
|
|
||||||
|
@ -71,7 +64,7 @@ which will operate with the above example:
|
||||||
```yaml
|
```yaml
|
||||||
- id: bookstack
|
- id: bookstack
|
||||||
description: BookStack
|
description: BookStack
|
||||||
secret: '$plaintext$bookstack_client_secret'
|
secret: '$pbkdf2-sha512$310000$c8p78n7pUMln0jzvd4aK4Q$JNRBzwAo0ek5qKn50cFzzvE9RXV88h1wJn5KGiHrD0YKtZaR/nCb2CJPOsKaPK0hjf.9yHxzQGZziziccp6Yng' # The digest of 'insecure_secret'.
|
||||||
public: false
|
public: false
|
||||||
authorization_policy: two_factor
|
authorization_policy: two_factor
|
||||||
redirect_uris:
|
redirect_uris:
|
||||||
|
|
|
@ -20,14 +20,7 @@ community: true
|
||||||
|
|
||||||
## Before You Begin
|
## Before You Begin
|
||||||
|
|
||||||
### Common Notes
|
{{% oidc-common %}}
|
||||||
|
|
||||||
1. You are *__required__* to utilize a unique client id for every client.
|
|
||||||
2. The client id on this page is merely an example and you can theoretically use any alphanumeric string.
|
|
||||||
3. You *__should not__* use the client secret in this example, We *__strongly recommend__* reading the
|
|
||||||
[Generating Client Secrets] guide instead.
|
|
||||||
|
|
||||||
[Generating Client Secrets]: ../specific-information.md#generating-client-secrets
|
|
||||||
|
|
||||||
### Assumptions
|
### Assumptions
|
||||||
|
|
||||||
|
@ -36,13 +29,13 @@ This example makes the following assumptions:
|
||||||
* __Cloudflare Team Name:__ `example-team`
|
* __Cloudflare Team Name:__ `example-team`
|
||||||
* __Authelia Root URL:__ `https://auth.example.com`
|
* __Authelia Root URL:__ `https://auth.example.com`
|
||||||
* __Client ID:__ `cloudflare`
|
* __Client ID:__ `cloudflare`
|
||||||
* __Client Secret:__ `cloudflare_client_secret`
|
* __Client Secret:__ `insecure_secret`
|
||||||
|
|
||||||
*__Important Note:__ [Cloudflare Zero Trust] does not properly URL encode the secret per [RFC6749 Appendix B] at the
|
*__Important Note:__ [Cloudflare Zero Trust] does not properly URL encode the secret per [RFC6749 Appendix B] at the
|
||||||
time this article was last modified (noted at the bottom). This means you'll either have to use only alphanumeric
|
time this article was last modified (noted at the bottom). This means you'll either have to use only alphanumeric
|
||||||
characters for the secret or URL encode the secret yourself.*
|
characters for the secret or URL encode the secret yourself.*
|
||||||
|
|
||||||
[RFC6749 Appendix B]: https://www.rfc-editor.org/rfc/rfc6749#appendix-B
|
[RFC6749 Appendix B]: https://datatracker.ietf.org/doc/html/rfc6749#appendix-B
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
|
@ -62,7 +55,7 @@ To configure [Cloudflare Zero Trust] to utilize Authelia as an [OpenID Connect 1
|
||||||
6. Set the following values:
|
6. Set the following values:
|
||||||
1. Name: `Authelia`
|
1. Name: `Authelia`
|
||||||
2. App ID: `cloudflare`
|
2. App ID: `cloudflare`
|
||||||
3. Client Secret: `cloudflare_client_secret`
|
3. Client Secret: `insecure_secret`
|
||||||
4. Auth URL: `https://auth.example.com/api/oidc/authorization`
|
4. Auth URL: `https://auth.example.com/api/oidc/authorization`
|
||||||
5. Token URL: `https://auth.example.com/api/oidc/token`
|
5. Token URL: `https://auth.example.com/api/oidc/token`
|
||||||
6. Certificate URL: `https://auth.example.com/jwks.json`
|
6. Certificate URL: `https://auth.example.com/jwks.json`
|
||||||
|
@ -79,7 +72,7 @@ which will operate with the above example:
|
||||||
```yaml
|
```yaml
|
||||||
- id: cloudflare
|
- id: cloudflare
|
||||||
description: Cloudflare ZeroTrust
|
description: Cloudflare ZeroTrust
|
||||||
secret: '$plaintext$cloudflare_client_secret'
|
secret: '$pbkdf2-sha512$310000$c8p78n7pUMln0jzvd4aK4Q$JNRBzwAo0ek5qKn50cFzzvE9RXV88h1wJn5KGiHrD0YKtZaR/nCb2CJPOsKaPK0hjf.9yHxzQGZziziccp6Yng' # The digest of 'insecure_secret'.
|
||||||
public: false
|
public: false
|
||||||
authorization_policy: two_factor
|
authorization_policy: two_factor
|
||||||
redirect_uris:
|
redirect_uris:
|
||||||
|
|
|
@ -22,14 +22,7 @@ community: true
|
||||||
|
|
||||||
## Before You Begin
|
## Before You Begin
|
||||||
|
|
||||||
### Common Notes
|
{{% oidc-common %}}
|
||||||
|
|
||||||
1. You are *__required__* to utilize a unique client id for every client.
|
|
||||||
2. The client id on this page is merely an example and you can theoretically use any alphanumeric string.
|
|
||||||
3. You *__should not__* use the client secret in this example, We *__strongly recommend__* reading the
|
|
||||||
[Generating Client Secrets] guide instead.
|
|
||||||
|
|
||||||
[Generating Client Secrets]: ../specific-information.md#generating-client-secrets
|
|
||||||
|
|
||||||
### Assumptions
|
### Assumptions
|
||||||
|
|
||||||
|
@ -38,7 +31,7 @@ This example makes the following assumptions:
|
||||||
* __Application Root URL:__ `https://gitea.example.com`
|
* __Application Root URL:__ `https://gitea.example.com`
|
||||||
* __Authelia Root URL:__ `https://auth.example.com`
|
* __Authelia Root URL:__ `https://auth.example.com`
|
||||||
* __Client ID:__ `gitea`
|
* __Client ID:__ `gitea`
|
||||||
* __Client Secret:__ `gitea_client_secret`
|
* __Client Secret:__ `insecure_secret`
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
|
@ -54,7 +47,7 @@ To configure [Gitea] to utilize Authelia as an [OpenID Connect 1.0] Provider:
|
||||||
1. Authentication Name: `authelia`
|
1. Authentication Name: `authelia`
|
||||||
2. OAuth2 Provider: `OpenID Connect`
|
2. OAuth2 Provider: `OpenID Connect`
|
||||||
3. Client ID (Key): `gitea`
|
3. Client ID (Key): `gitea`
|
||||||
4. Client Secret: `gitea_client_secret`
|
4. Client Secret: `insecure_secret`
|
||||||
5. OpenID Connect Auto Discovery URL: `https://auth.example.com/.well-known/openid-configuration`
|
5. OpenID Connect Auto Discovery URL: `https://auth.example.com/.well-known/openid-configuration`
|
||||||
|
|
||||||
{{< figure src="gitea.png" alt="Gitea" width="300" >}}
|
{{< figure src="gitea.png" alt="Gitea" width="300" >}}
|
||||||
|
@ -86,7 +79,7 @@ will operate with the above example:
|
||||||
```yaml
|
```yaml
|
||||||
- id: gitea
|
- id: gitea
|
||||||
description: Gitea
|
description: Gitea
|
||||||
secret: '$plaintext$gitea_client_secret'
|
secret: '$pbkdf2-sha512$310000$c8p78n7pUMln0jzvd4aK4Q$JNRBzwAo0ek5qKn50cFzzvE9RXV88h1wJn5KGiHrD0YKtZaR/nCb2CJPOsKaPK0hjf.9yHxzQGZziziccp6Yng' # The digest of 'insecure_secret'.
|
||||||
public: false
|
public: false
|
||||||
authorization_policy: two_factor
|
authorization_policy: two_factor
|
||||||
redirect_uris:
|
redirect_uris:
|
||||||
|
|
|
@ -22,14 +22,7 @@ community: true
|
||||||
|
|
||||||
## Before You Begin
|
## Before You Begin
|
||||||
|
|
||||||
### Common Notes
|
{{% oidc-common %}}
|
||||||
|
|
||||||
1. You are *__required__* to utilize a unique client id for every client.
|
|
||||||
2. The client id on this page is merely an example and you can theoretically use any alphanumeric string.
|
|
||||||
3. You *__should not__* use the client secret in this example, We *__strongly recommend__* reading the
|
|
||||||
[Generating Client Secrets] guide instead.
|
|
||||||
|
|
||||||
[Generating Client Secrets]: ../specific-information.md#generating-client-secrets
|
|
||||||
|
|
||||||
### Assumptions
|
### Assumptions
|
||||||
|
|
||||||
|
@ -38,7 +31,7 @@ This example makes the following assumptions:
|
||||||
* __Application Root URL:__ `https://gitlab.example.com`
|
* __Application Root URL:__ `https://gitlab.example.com`
|
||||||
* __Authelia Root URL:__ `https://auth.example.com`
|
* __Authelia Root URL:__ `https://auth.example.com`
|
||||||
* __Client ID:__ `gitlab`
|
* __Client ID:__ `gitlab`
|
||||||
* __Client Secret:__ `gitlab_client_secret`
|
* __Client Secret:__ `insecure_secret`
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
|
@ -65,7 +58,7 @@ gitlab_rails['omniauth_providers'] = [
|
||||||
send_scope_to_token_endpoint: "false",
|
send_scope_to_token_endpoint: "false",
|
||||||
client_options: {
|
client_options: {
|
||||||
identifier: "gitlab",
|
identifier: "gitlab",
|
||||||
secret: "gitlab_client_secret",
|
secret: "insecure_secret",
|
||||||
redirect_uri: "https://gitlab.example.com/users/auth/openid_connect/callback"
|
redirect_uri: "https://gitlab.example.com/users/auth/openid_connect/callback"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -82,7 +75,7 @@ which will operate with the above example:
|
||||||
```yaml
|
```yaml
|
||||||
- id: gitlab
|
- id: gitlab
|
||||||
description: GitLab
|
description: GitLab
|
||||||
secret: '$plaintext$gitlab_client_secret'
|
secret: '$pbkdf2-sha512$310000$c8p78n7pUMln0jzvd4aK4Q$JNRBzwAo0ek5qKn50cFzzvE9RXV88h1wJn5KGiHrD0YKtZaR/nCb2CJPOsKaPK0hjf.9yHxzQGZziziccp6Yng' # The digest of 'insecure_secret'.
|
||||||
public: false
|
public: false
|
||||||
authorization_policy: two_factor
|
authorization_policy: two_factor
|
||||||
redirect_uris:
|
redirect_uris:
|
||||||
|
|
|
@ -22,14 +22,7 @@ community: true
|
||||||
|
|
||||||
## Before You Begin
|
## Before You Begin
|
||||||
|
|
||||||
### Common Notes
|
{{% oidc-common %}}
|
||||||
|
|
||||||
1. You are *__required__* to utilize a unique client id for every client.
|
|
||||||
2. The client id on this page is merely an example and you can theoretically use any alphanumeric string.
|
|
||||||
3. You *__should not__* use the client secret in this example, We *__strongly recommend__* reading the
|
|
||||||
[Generating Client Secrets] guide instead.
|
|
||||||
|
|
||||||
[Generating Client Secrets]: ../specific-information.md#generating-client-secrets
|
|
||||||
|
|
||||||
### Assumptions
|
### Assumptions
|
||||||
|
|
||||||
|
@ -38,7 +31,7 @@ This example makes the following assumptions:
|
||||||
* __Application Root URL:__ `https://grafana.example.com`
|
* __Application Root URL:__ `https://grafana.example.com`
|
||||||
* __Authelia Root URL:__ `https://auth.example.com`
|
* __Authelia Root URL:__ `https://auth.example.com`
|
||||||
* __Client ID:__ `grafana`
|
* __Client ID:__ `grafana`
|
||||||
* __Client Secret:__ `grafana_client_secret`
|
* __Client Secret:__ `insecure_secret`
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
|
@ -58,7 +51,7 @@ enabled = true
|
||||||
name = Authelia
|
name = Authelia
|
||||||
icon = signin
|
icon = signin
|
||||||
client_id = grafana
|
client_id = grafana
|
||||||
client_secret = grafana_client_secret
|
client_secret = insecure_secret
|
||||||
scopes = openid profile email groups
|
scopes = openid profile email groups
|
||||||
empty_scopes = false
|
empty_scopes = false
|
||||||
auth_url = https://auth.example.com/api/oidc/authorization
|
auth_url = https://auth.example.com/api/oidc/authorization
|
||||||
|
@ -80,7 +73,7 @@ Configure the following environment variables:
|
||||||
| GF_AUTH_GENERIC_OAUTH_ENABLED | true |
|
| GF_AUTH_GENERIC_OAUTH_ENABLED | true |
|
||||||
| GF_AUTH_GENERIC_OAUTH_NAME | Authelia |
|
| GF_AUTH_GENERIC_OAUTH_NAME | Authelia |
|
||||||
| GF_AUTH_GENERIC_OAUTH_CLIENT_ID | grafana |
|
| GF_AUTH_GENERIC_OAUTH_CLIENT_ID | grafana |
|
||||||
| GF_AUTH_GENERIC_OAUTH_CLIENT_SECRET | grafana_client_secret |
|
| GF_AUTH_GENERIC_OAUTH_CLIENT_SECRET | insecure_secret |
|
||||||
| GF_AUTH_GENERIC_OAUTH_SCOPES | openid profile email groups |
|
| GF_AUTH_GENERIC_OAUTH_SCOPES | openid profile email groups |
|
||||||
| GF_AUTH_GENERIC_OAUTH_EMPTY_SCOPES | false |
|
| GF_AUTH_GENERIC_OAUTH_EMPTY_SCOPES | false |
|
||||||
| GF_AUTH_GENERIC_OAUTH_AUTH_URL | https://auth.example.com/api/oidc/authorization |
|
| GF_AUTH_GENERIC_OAUTH_AUTH_URL | https://auth.example.com/api/oidc/authorization |
|
||||||
|
@ -100,7 +93,7 @@ which will operate with the above example:
|
||||||
```yaml
|
```yaml
|
||||||
- id: grafana
|
- id: grafana
|
||||||
description: Grafana
|
description: Grafana
|
||||||
secret: '$plaintext$grafana_client_secret'
|
secret: '$pbkdf2-sha512$310000$c8p78n7pUMln0jzvd4aK4Q$JNRBzwAo0ek5qKn50cFzzvE9RXV88h1wJn5KGiHrD0YKtZaR/nCb2CJPOsKaPK0hjf.9yHxzQGZziziccp6Yng' # The digest of 'insecure_secret'.
|
||||||
public: false
|
public: false
|
||||||
authorization_policy: two_factor
|
authorization_policy: two_factor
|
||||||
redirect_uris:
|
redirect_uris:
|
||||||
|
|
|
@ -22,14 +22,7 @@ community: true
|
||||||
|
|
||||||
## Before You Begin
|
## Before You Begin
|
||||||
|
|
||||||
### Common Notes
|
{{% oidc-common %}}
|
||||||
|
|
||||||
1. You are *__required__* to utilize a unique client id for every client.
|
|
||||||
2. The client id on this page is merely an example and you can theoretically use any alphanumeric string.
|
|
||||||
3. You *__should not__* use the client secret in this example, We *__strongly recommend__* reading the
|
|
||||||
[Generating Client Secrets] guide instead.
|
|
||||||
|
|
||||||
[Generating Client Secrets]: ../specific-information.md#generating-client-secrets
|
|
||||||
|
|
||||||
### Assumptions
|
### Assumptions
|
||||||
|
|
||||||
|
@ -38,7 +31,7 @@ This example makes the following assumptions:
|
||||||
* __Application Root URL:__ `https://harbor.example.com`
|
* __Application Root URL:__ `https://harbor.example.com`
|
||||||
* __Authelia Root URL:__ `https://auth.example.com`
|
* __Authelia Root URL:__ `https://auth.example.com`
|
||||||
* __Client ID:__ `harbor`
|
* __Client ID:__ `harbor`
|
||||||
* __Client Secret:__ `harbor_client_secret`
|
* __Client Secret:__ `insecure_secret`
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
|
@ -54,7 +47,7 @@ To configure [Harbor] to utilize Authelia as an [OpenID Connect 1.0] Provider:
|
||||||
1. OIDC Provider Name: `Authelia`
|
1. OIDC Provider Name: `Authelia`
|
||||||
2. OIDC Provider Endpoint: `https://auth.example.com`
|
2. OIDC Provider Endpoint: `https://auth.example.com`
|
||||||
3. OIDC Client ID: `harbor`
|
3. OIDC Client ID: `harbor`
|
||||||
4. OIDC Client Secret: `harbor_client_secret`
|
4. OIDC Client Secret: `insecure_secret`
|
||||||
5. Group Claim Name: `groups`
|
5. Group Claim Name: `groups`
|
||||||
6. OIDC Scope: `openid,profile,email,groups`
|
6. OIDC Scope: `openid,profile,email,groups`
|
||||||
7. For OIDC Admin Group you can specify a group name that matches your authentication backend.
|
7. For OIDC Admin Group you can specify a group name that matches your authentication backend.
|
||||||
|
@ -73,7 +66,7 @@ which will operate with the above example:
|
||||||
```yaml
|
```yaml
|
||||||
- id: harbor
|
- id: harbor
|
||||||
description: Harbor
|
description: Harbor
|
||||||
secret: '$plaintext$harbor_client_secret'
|
secret: '$pbkdf2-sha512$310000$c8p78n7pUMln0jzvd4aK4Q$JNRBzwAo0ek5qKn50cFzzvE9RXV88h1wJn5KGiHrD0YKtZaR/nCb2CJPOsKaPK0hjf.9yHxzQGZziziccp6Yng' # The digest of 'insecure_secret'.
|
||||||
public: false
|
public: false
|
||||||
authorization_policy: two_factor
|
authorization_policy: two_factor
|
||||||
redirect_uris:
|
redirect_uris:
|
||||||
|
|
|
@ -22,14 +22,7 @@ community: true
|
||||||
|
|
||||||
## Before You Begin
|
## Before You Begin
|
||||||
|
|
||||||
### Common Notes
|
{{% oidc-common %}}
|
||||||
|
|
||||||
1. You are *__required__* to utilize a unique client id for every client.
|
|
||||||
2. The client id on this page is merely an example and you can theoretically use any alphanumeric string.
|
|
||||||
3. You *__should not__* use the client secret in this example, We *__strongly recommend__* reading the
|
|
||||||
[Generating Client Secrets] guide instead.
|
|
||||||
|
|
||||||
[Generating Client Secrets]: ../specific-information.md#generating-client-secrets
|
|
||||||
|
|
||||||
### Assumptions
|
### Assumptions
|
||||||
|
|
||||||
|
@ -38,7 +31,7 @@ This example makes the following assumptions:
|
||||||
* __Application Root URL:__ `https://vault.example.com`
|
* __Application Root URL:__ `https://vault.example.com`
|
||||||
* __Authelia Root URL:__ `https://auth.example.com`
|
* __Authelia Root URL:__ `https://auth.example.com`
|
||||||
* __Client ID:__ `vault`
|
* __Client ID:__ `vault`
|
||||||
* __Client Secret:__ `vault_client_secret`
|
* __Client Secret:__ `insecure_secret`
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
|
@ -56,7 +49,7 @@ which will operate with the above example:
|
||||||
```yaml
|
```yaml
|
||||||
- id: vault
|
- id: vault
|
||||||
description: HashiCorp Vault
|
description: HashiCorp Vault
|
||||||
secret: '$plaintext$vault_client_secret'
|
secret: '$pbkdf2-sha512$310000$c8p78n7pUMln0jzvd4aK4Q$JNRBzwAo0ek5qKn50cFzzvE9RXV88h1wJn5KGiHrD0YKtZaR/nCb2CJPOsKaPK0hjf.9yHxzQGZziziccp6Yng' # The digest of 'insecure_secret'.
|
||||||
public: false
|
public: false
|
||||||
authorization_policy: two_factor
|
authorization_policy: two_factor
|
||||||
redirect_uris:
|
redirect_uris:
|
||||||
|
|
|
@ -87,6 +87,68 @@ This scope includes the profile information the authentication backend reports a
|
||||||
| preferred_username | string | username | The username the user used to login with |
|
| preferred_username | string | username | The username the user used to login with |
|
||||||
| name | string | display_name | The users display name |
|
| name | string | display_name | The users display name |
|
||||||
|
|
||||||
|
## Parameters
|
||||||
|
|
||||||
|
The following section describes advanced parameters which can be used in various endpoints as well as their related
|
||||||
|
configuration options.
|
||||||
|
|
||||||
|
### Grant Types
|
||||||
|
|
||||||
|
The following describes the various [OAuth 2.0] and [OpenID Connect 1.0] grant types and their support level. The value
|
||||||
|
field is both the required value for the `grant_type` parameter in the authorization request and the `grant_types`
|
||||||
|
configuration option.
|
||||||
|
|
||||||
|
| Grant Type | Supported | Value | Notes |
|
||||||
|
|:-----------------------------------------------:|:---------:|:----------------------------------------------:|:-------------------------------------------------------------------:|
|
||||||
|
| [OAuth 2.0 Authorization Code] | Yes | `authorization_code` | |
|
||||||
|
| [OAuth 2.0 Resource Owner Password Credentials] | No | `password` | This Grant Type has been deprecated and should not normally be used |
|
||||||
|
| [OAuth 2.0 Client Credentials] | Yes | `client_credentials` | |
|
||||||
|
| [OAuth 2.0 Implicit] | Yes | `implicit` | This Grant Type has been deprecated and should not normally be used |
|
||||||
|
| [OAuth 2.0 Refresh Token] | Yes | `refresh_token` | |
|
||||||
|
| [OAuth 2.0 Device Code] | No | `urn:ietf:params:oauth:grant-type:device_code` | |
|
||||||
|
|
|
||||||
|
|
||||||
|
[OAuth 2.0 Authorization Code]: https://datatracker.ietf.org/doc/html/rfc6749#section-1.3.1
|
||||||
|
[OAuth 2.0 Implicit]: https://datatracker.ietf.org/doc/html/rfc6749#section-1.3.2
|
||||||
|
[OAuth 2.0 Resource Owner Password Credentials]: https://datatracker.ietf.org/doc/html/rfc6749#section-1.3.3
|
||||||
|
[OAuth 2.0 Client Credentials]: https://datatracker.ietf.org/doc/html/rfc6749#section-1.3.4
|
||||||
|
[OAuth 2.0 Refresh Token]: https://datatracker.ietf.org/doc/html/rfc6749#section-1.5
|
||||||
|
[OAuth 2.0 Device Code]: https://datatracker.ietf.org/doc/html/rfc8628#section-3.4
|
||||||
|
|
||||||
|
### Response Types
|
||||||
|
|
||||||
|
The following describes the supported response types. See the [OAuth 2.0 Multiple Response Type Encoding Practices] for
|
||||||
|
more technical information.
|
||||||
|
|
||||||
|
| Flow Type | Values |
|
||||||
|
|:-------------------------:|:---------------------:|
|
||||||
|
| [Authorization Code Flow] | `code` |
|
||||||
|
| [Implicit Flow] | `token id_token` |
|
||||||
|
| [Implicit Flow] | `id_token` |
|
||||||
|
| [Implicit Flow] | `token` |
|
||||||
|
| [Hybrid Flow] | `code token` |
|
||||||
|
| [Hybrid Flow] | `code id_token` |
|
||||||
|
| [Hybrid Flow] | `code token id_token` |
|
||||||
|
|
||||||
|
[Authorization Code Flow]: https://openid.net/specs/openid-connect-core-1_0.html#CodeFlowAuth
|
||||||
|
[Implicit Flow]: https://openid.net/specs/openid-connect-core-1_0.html#ImplicitFlowAuth
|
||||||
|
[Hybrid Flow]: https://openid.net/specs/openid-connect-core-1_0.html#HybridFlowAuth
|
||||||
|
|
||||||
|
[OAuth 2.0 Multiple Response Type Encoding Practices]: https://openid.net/specs/oauth-v2-multiple-response-types-1_0.html
|
||||||
|
|
||||||
|
### Response Modes
|
||||||
|
|
||||||
|
The following describes the supported response modes. See the [OAuth 2.0 Multiple Response Type Encoding Practices] for
|
||||||
|
more technical information.
|
||||||
|
|
||||||
|
| Name | Value |
|
||||||
|
|:---------------------:|:-----------:|
|
||||||
|
| Query String | `query` |
|
||||||
|
| Fragment | `fragment` |
|
||||||
|
| [OAuth 2.0 Form Post] | `form_post` |
|
||||||
|
|
||||||
|
[OAuth 2.0 Form Post]: https://openid.net/specs/oauth-v2-form-post-response-mode-1_0.html
|
||||||
|
|
||||||
## Authentication Method References
|
## Authentication Method References
|
||||||
|
|
||||||
Authelia currently supports adding the `amr` [Claim] to the [ID Token] utilizing the [RFC8176] Authentication Method
|
Authelia currently supports adding the `amr` [Claim] to the [ID Token] utilizing the [RFC8176] Authentication Method
|
||||||
|
@ -166,16 +228,16 @@ These endpoints implement OpenID Connect elements.
|
||||||
[OpenID Connect 1.0]: https://openid.net/connect/
|
[OpenID Connect 1.0]: https://openid.net/connect/
|
||||||
|
|
||||||
[OpenID Connect Discovery]: https://openid.net/specs/openid-connect-discovery-1_0.html
|
[OpenID Connect Discovery]: https://openid.net/specs/openid-connect-discovery-1_0.html
|
||||||
[OAuth 2.0 Authorization Server Metadata]: https://www.rfc-editor.org/rfc/rfc8414.html
|
[OAuth 2.0 Authorization Server Metadata]: https://datatracker.ietf.org/doc/html/rfc8414
|
||||||
|
|
||||||
[JSON Web Key Sets]: https://www.rfc-editor.org/rfc/rfc7517.html#section-5
|
[JSON Web Key Sets]: https://datatracker.ietf.org/doc/html/rfc7517#section-5
|
||||||
|
|
||||||
[Authorization]: https://openid.net/specs/openid-connect-core-1_0.html#AuthorizationEndpoint
|
[Authorization]: https://openid.net/specs/openid-connect-core-1_0.html#AuthorizationEndpoint
|
||||||
[Token]: https://openid.net/specs/openid-connect-core-1_0.html#TokenEndpoint
|
[Token]: https://openid.net/specs/openid-connect-core-1_0.html#TokenEndpoint
|
||||||
[UserInfo]: https://openid.net/specs/openid-connect-core-1_0.html#UserInfo
|
[UserInfo]: https://openid.net/specs/openid-connect-core-1_0.html#UserInfo
|
||||||
[Introspection]: https://www.rfc-editor.org/rfc/rfc7662.html
|
[Introspection]: https://datatracker.ietf.org/doc/html/rfc7662
|
||||||
[Revocation]: https://www.rfc-editor.org/rfc/rfc7009.html
|
[Revocation]: https://datatracker.ietf.org/doc/html/rfc7009
|
||||||
|
|
||||||
[RFC8176]: https://www.rfc-editor.org/rfc/rfc8176.html
|
[RFC8176]: https://datatracker.ietf.org/doc/html/rfc8176
|
||||||
[RFC4122]: https://www.rfc-editor.org/rfc/rfc4122.html
|
[RFC4122]: https://datatracker.ietf.org/doc/html/rfc4122
|
||||||
[Subject Identifier Types]: https://openid.net/specs/openid-connect-core-1_0.html#SubjectIDTypes
|
[Subject Identifier Types]: https://openid.net/specs/openid-connect-core-1_0.html#SubjectIDTypes
|
||||||
|
|
|
@ -22,14 +22,7 @@ community: true
|
||||||
|
|
||||||
## Before You Begin
|
## Before You Begin
|
||||||
|
|
||||||
### Common Notes
|
{{% oidc-common %}}
|
||||||
|
|
||||||
1. You are *__required__* to utilize a unique client id for every client.
|
|
||||||
2. The client id on this page is merely an example and you can theoretically use any alphanumeric string.
|
|
||||||
3. You *__should not__* use the client secret in this example, We *__strongly recommend__* reading the
|
|
||||||
[Generating Client Secrets] guide instead.
|
|
||||||
|
|
||||||
[Generating Client Secrets]: ../specific-information.md#generating-client-secrets
|
|
||||||
|
|
||||||
### Assumptions
|
### Assumptions
|
||||||
|
|
||||||
|
@ -38,7 +31,7 @@ This example makes the following assumptions:
|
||||||
* __Application Root URL:__ `https://komga.example.com`
|
* __Application Root URL:__ `https://komga.example.com`
|
||||||
* __Authelia Root URL:__ `https://auth.example.com`
|
* __Authelia Root URL:__ `https://auth.example.com`
|
||||||
* __Client ID:__ `komga`
|
* __Client ID:__ `komga`
|
||||||
* __Client Secret:__ `komga_client_secret`
|
* __Client Secret:__ `insecure_secret`
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
|
@ -58,7 +51,7 @@ spring:
|
||||||
registration:
|
registration:
|
||||||
authelia:
|
authelia:
|
||||||
client-id: `komga`
|
client-id: `komga`
|
||||||
client-secret: `komga_client_secret`
|
client-secret: `insecure_secret`
|
||||||
client-name: Authelia
|
client-name: Authelia
|
||||||
scope: openid,profile,email
|
scope: openid,profile,email
|
||||||
authorization-grant-type: authorization_code
|
authorization-grant-type: authorization_code
|
||||||
|
@ -78,7 +71,7 @@ which will operate with the above example:
|
||||||
```yaml
|
```yaml
|
||||||
- id: komga
|
- id: komga
|
||||||
description: Komga
|
description: Komga
|
||||||
secret: '$plaintext$komga_client_secret'
|
secret: '$pbkdf2-sha512$310000$c8p78n7pUMln0jzvd4aK4Q$JNRBzwAo0ek5qKn50cFzzvE9RXV88h1wJn5KGiHrD0YKtZaR/nCb2CJPOsKaPK0hjf.9yHxzQGZziziccp6Yng' # The digest of 'insecure_secret'.
|
||||||
public: false
|
public: false
|
||||||
authorization_policy: two_factor
|
authorization_policy: two_factor
|
||||||
redirect_uris:
|
redirect_uris:
|
||||||
|
|
|
@ -22,14 +22,7 @@ community: true
|
||||||
|
|
||||||
## Before You Begin
|
## Before You Begin
|
||||||
|
|
||||||
### Common Notes
|
{{% oidc-common %}}
|
||||||
|
|
||||||
1. You are *__required__* to utilize a unique client id for every client.
|
|
||||||
2. The client id on this page is merely an example and you can theoretically use any alphanumeric string.
|
|
||||||
3. You *__should not__* use the client secret in this example, We *__strongly recommend__* reading the
|
|
||||||
[Generating Client Secrets] guide instead.
|
|
||||||
|
|
||||||
[Generating Client Secrets]: ../specific-information.md#generating-client-secrets
|
|
||||||
|
|
||||||
### Assumptions
|
### Assumptions
|
||||||
|
|
||||||
|
@ -38,7 +31,7 @@ This example makes the following assumptions:
|
||||||
* __Application Root URL:__ `https://nextcloud.example.com`
|
* __Application Root URL:__ `https://nextcloud.example.com`
|
||||||
* __Authelia Root URL:__ `https://auth.example.com`
|
* __Authelia Root URL:__ `https://auth.example.com`
|
||||||
* __Client ID:__ `nextcloud`
|
* __Client ID:__ `nextcloud`
|
||||||
* __Client Secret:__ `nextcloud_client_secret`
|
* __Client Secret:__ `insecure_secret`
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
|
@ -55,7 +48,7 @@ $CONFIG = array (
|
||||||
'lost_password_link' => 'disabled',
|
'lost_password_link' => 'disabled',
|
||||||
'oidc_login_provider_url' => 'https://auth.example.com',
|
'oidc_login_provider_url' => 'https://auth.example.com',
|
||||||
'oidc_login_client_id' => 'nextcloud',
|
'oidc_login_client_id' => 'nextcloud',
|
||||||
'oidc_login_client_secret' => 'nextcloud_client_secret',
|
'oidc_login_client_secret' => 'insecure_secret',
|
||||||
'oidc_login_auto_redirect' => false,
|
'oidc_login_auto_redirect' => false,
|
||||||
'oidc_login_end_session_redirect' => false,
|
'oidc_login_end_session_redirect' => false,
|
||||||
'oidc_login_button_text' => 'Log in with Authelia',
|
'oidc_login_button_text' => 'Log in with Authelia',
|
||||||
|
@ -94,7 +87,7 @@ which will operate with the above example:
|
||||||
```yaml
|
```yaml
|
||||||
- id: nextcloud
|
- id: nextcloud
|
||||||
description: NextCloud
|
description: NextCloud
|
||||||
secret: '$plaintext$nextcloud_client_secret'
|
secret: '$pbkdf2-sha512$310000$c8p78n7pUMln0jzvd4aK4Q$JNRBzwAo0ek5qKn50cFzzvE9RXV88h1wJn5KGiHrD0YKtZaR/nCb2CJPOsKaPK0hjf.9yHxzQGZziziccp6Yng' # The digest of 'insecure_secret'.
|
||||||
public: false
|
public: false
|
||||||
authorization_policy: two_factor
|
authorization_policy: two_factor
|
||||||
redirect_uris:
|
redirect_uris:
|
||||||
|
|
|
@ -22,14 +22,7 @@ community: true
|
||||||
|
|
||||||
## Before You Begin
|
## Before You Begin
|
||||||
|
|
||||||
### Common Notes
|
{{% oidc-common %}}
|
||||||
|
|
||||||
1. You are *__required__* to utilize a unique client id for every client.
|
|
||||||
2. The client id on this page is merely an example and you can theoretically use any alphanumeric string.
|
|
||||||
3. You *__should not__* use the client secret in this example, We *__strongly recommend__* reading the
|
|
||||||
[Generating Client Secrets] guide instead.
|
|
||||||
|
|
||||||
[Generating Client Secrets]: ../specific-information.md#generating-client-secrets
|
|
||||||
|
|
||||||
### Assumptions
|
### Assumptions
|
||||||
|
|
||||||
|
@ -38,7 +31,7 @@ This example makes the following assumptions:
|
||||||
* __Application Root URL:__ `https://outline.example.com`
|
* __Application Root URL:__ `https://outline.example.com`
|
||||||
* __Authelia Root URL:__ `https://auth.example.com`
|
* __Authelia Root URL:__ `https://auth.example.com`
|
||||||
* __Client ID:__ `outline`
|
* __Client ID:__ `outline`
|
||||||
* __Client Secret:__ `outline_client_secret`
|
* __Client Secret:__ `insecure_secret`
|
||||||
|
|
||||||
*__Important Note:__ At the time of this writing [Outline] requires the `offline_access` scope by default. Failure to include this scope will result
|
*__Important Note:__ At the time of this writing [Outline] requires the `offline_access` scope by default. Failure to include this scope will result
|
||||||
in an error as [Outline] will attempt to use a refresh token that is never issued.*
|
in an error as [Outline] will attempt to use a refresh token that is never issued.*
|
||||||
|
@ -55,7 +48,7 @@ URL=https://outline.example.com
|
||||||
FORCE_HTTPS=true
|
FORCE_HTTPS=true
|
||||||
|
|
||||||
OIDC_CLIENT_ID=outline
|
OIDC_CLIENT_ID=outline
|
||||||
OIDC_CLIENT_SECRET=outline_client_secret
|
OIDC_CLIENT_SECRET=insecure_secret
|
||||||
OIDC_AUTH_URI=https://auth.example.com/api/oidc/authorization
|
OIDC_AUTH_URI=https://auth.example.com/api/oidc/authorization
|
||||||
OIDC_TOKEN_URI=https://auth.example.com/api/oidc/token
|
OIDC_TOKEN_URI=https://auth.example.com/api/oidc/token
|
||||||
OIDC_USERINFO_URI=https://auth.example.com/api/oidc/userinfo
|
OIDC_USERINFO_URI=https://auth.example.com/api/oidc/userinfo
|
||||||
|
@ -73,7 +66,7 @@ which will operate with the above example:
|
||||||
```yaml
|
```yaml
|
||||||
- id: outline
|
- id: outline
|
||||||
description: Outline
|
description: Outline
|
||||||
secret: '$plaintext$outline_client_secret'
|
secret: '$pbkdf2-sha512$310000$c8p78n7pUMln0jzvd4aK4Q$JNRBzwAo0ek5qKn50cFzzvE9RXV88h1wJn5KGiHrD0YKtZaR/nCb2CJPOsKaPK0hjf.9yHxzQGZziziccp6Yng' # The digest of 'insecure_secret'.
|
||||||
public: false
|
public: false
|
||||||
authorization_policy: two_factor
|
authorization_policy: two_factor
|
||||||
redirect_uris:
|
redirect_uris:
|
||||||
|
|
|
@ -24,14 +24,7 @@ aliases:
|
||||||
|
|
||||||
## Before You Begin
|
## Before You Begin
|
||||||
|
|
||||||
### Common Notes
|
{{% oidc-common %}}
|
||||||
|
|
||||||
1. You are *__required__* to utilize a unique client id for every client.
|
|
||||||
2. The client id on this page is merely an example and you can theoretically use any alphanumeric string.
|
|
||||||
3. You *__should not__* use the client secret in this example, We *__strongly recommend__* reading the
|
|
||||||
[Generating Client Secrets] guide instead.
|
|
||||||
|
|
||||||
[Generating Client Secrets]: ../specific-information.md#generating-client-secrets
|
|
||||||
|
|
||||||
### Assumptions
|
### Assumptions
|
||||||
|
|
||||||
|
@ -40,7 +33,7 @@ This example makes the following assumptions:
|
||||||
* __Application Root URL:__ `https://portainer.example.com`
|
* __Application Root URL:__ `https://portainer.example.com`
|
||||||
* __Authelia Root URL:__ `https://auth.example.com`
|
* __Authelia Root URL:__ `https://auth.example.com`
|
||||||
* __Client ID:__ `portainer`
|
* __Client ID:__ `portainer`
|
||||||
* __Client Secret:__ `portainer_client_secret`
|
* __Client Secret:__ `insecure_secret`
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
|
@ -55,7 +48,7 @@ To configure [Portainer] to utilize Authelia as an [OpenID Connect 1.0] Provider
|
||||||
2. Provider: Custom
|
2. Provider: Custom
|
||||||
3. Enable *Automatic User Provision* if you want users to automatically be created in [Portainer].
|
3. Enable *Automatic User Provision* if you want users to automatically be created in [Portainer].
|
||||||
4. Client ID: `portainer`
|
4. Client ID: `portainer`
|
||||||
5. Client Secret: `portainer_client_secret`
|
5. Client Secret: `insecure_secret`
|
||||||
6. Authorization URL: `https://auth.example.com/api/oidc/authorization`
|
6. Authorization URL: `https://auth.example.com/api/oidc/authorization`
|
||||||
7. Access Token URL: `https://auth.example.com/api/oidc/token`
|
7. Access Token URL: `https://auth.example.com/api/oidc/token`
|
||||||
8. Resource URL: `https://auth.example.com/api/oidc/userinfo`
|
8. Resource URL: `https://auth.example.com/api/oidc/userinfo`
|
||||||
|
@ -75,7 +68,7 @@ which will operate with the above example:
|
||||||
```yaml
|
```yaml
|
||||||
- id: portainer
|
- id: portainer
|
||||||
description: Portainer
|
description: Portainer
|
||||||
secret: '$plaintext$portainer_client_secret'
|
secret: '$pbkdf2-sha512$310000$c8p78n7pUMln0jzvd4aK4Q$JNRBzwAo0ek5qKn50cFzzvE9RXV88h1wJn5KGiHrD0YKtZaR/nCb2CJPOsKaPK0hjf.9yHxzQGZziziccp6Yng' # The digest of 'insecure_secret'.
|
||||||
public: false
|
public: false
|
||||||
authorization_policy: two_factor
|
authorization_policy: two_factor
|
||||||
redirect_uris:
|
redirect_uris:
|
||||||
|
|
|
@ -43,7 +43,7 @@ This example makes the following assumptions:
|
||||||
* __Application Root URL:__ `https://proxmox.example.com`
|
* __Application Root URL:__ `https://proxmox.example.com`
|
||||||
* __Authelia Root URL:__ `https://auth.example.com`
|
* __Authelia Root URL:__ `https://auth.example.com`
|
||||||
* __Client ID:__ `proxmox`
|
* __Client ID:__ `proxmox`
|
||||||
* __Client Secret:__ `proxmox_client_secret`
|
* __Client Secret:__ `insecure_secret`
|
||||||
* __Realm__ `authelia`
|
* __Realm__ `authelia`
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
@ -60,7 +60,7 @@ To configure [Proxmox] to utilize Authelia as an [OpenID Connect 1.0] Provider:
|
||||||
1. Issuer URL: `https://auth.example.com`
|
1. Issuer URL: `https://auth.example.com`
|
||||||
2. Realm: `authelia`
|
2. Realm: `authelia`
|
||||||
3. Client ID: `proxmox`
|
3. Client ID: `proxmox`
|
||||||
4. Client Key: `proxmox_client_secret`
|
4. Client Key: `insecure_secret`
|
||||||
5. Username Claim `preferred_username`
|
5. Username Claim `preferred_username`
|
||||||
6. Scopes: `openid profile email`
|
6. Scopes: `openid profile email`
|
||||||
7. Enable *Autocreate Users* if you want users to automatically be created in [Proxmox].
|
7. Enable *Autocreate Users* if you want users to automatically be created in [Proxmox].
|
||||||
|
@ -76,7 +76,7 @@ which will operate with the above example:
|
||||||
```yaml
|
```yaml
|
||||||
- id: proxmox
|
- id: proxmox
|
||||||
description: Proxmox
|
description: Proxmox
|
||||||
secret: '$plaintext$proxmox_client_secret'
|
secret: '$pbkdf2-sha512$310000$c8p78n7pUMln0jzvd4aK4Q$JNRBzwAo0ek5qKn50cFzzvE9RXV88h1wJn5KGiHrD0YKtZaR/nCb2CJPOsKaPK0hjf.9yHxzQGZziziccp6Yng' # The digest of 'insecure_secret'.
|
||||||
public: false
|
public: false
|
||||||
authorization_policy: two_factor
|
authorization_policy: two_factor
|
||||||
redirect_uris:
|
redirect_uris:
|
||||||
|
|
|
@ -22,14 +22,7 @@ community: true
|
||||||
|
|
||||||
## Before You Begin
|
## Before You Begin
|
||||||
|
|
||||||
### Common Notes
|
{{% oidc-common %}}
|
||||||
|
|
||||||
1. You are *__required__* to utilize a unique client id for every client.
|
|
||||||
2. The client id on this page is merely an example and you can theoretically use any alphanumeric string.
|
|
||||||
3. You *__should not__* use the client secret in this example, We *__strongly recommend__* reading the
|
|
||||||
[Generating Client Secrets] guide instead.
|
|
||||||
|
|
||||||
[Generating Client Secrets]: ../specific-information.md#generating-client-secrets
|
|
||||||
|
|
||||||
### Assumptions
|
### Assumptions
|
||||||
|
|
||||||
|
@ -38,7 +31,7 @@ This example makes the following assumptions:
|
||||||
* __Application Root URL:__ `https://seafile.example.com`
|
* __Application Root URL:__ `https://seafile.example.com`
|
||||||
* __Authelia Root URL:__ `https://auth.example.com`
|
* __Authelia Root URL:__ `https://auth.example.com`
|
||||||
* __Client ID:__ `seafile`
|
* __Client ID:__ `seafile`
|
||||||
* __Client Secret:__ `seafile_client_secret`
|
* __Client Secret:__ `insecure_secret`
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
|
@ -55,7 +48,7 @@ To configure [Seafile] to utilize Authelia as an [OpenID Connect 1.0] Provider:
|
||||||
ENABLE_OAUTH = True
|
ENABLE_OAUTH = True
|
||||||
OAUTH_ENABLE_INSECURE_TRANSPORT = False
|
OAUTH_ENABLE_INSECURE_TRANSPORT = False
|
||||||
OAUTH_CLIENT_ID = "seafile"
|
OAUTH_CLIENT_ID = "seafile"
|
||||||
OAUTH_CLIENT_SECRET = "seafile_client_secret"
|
OAUTH_CLIENT_SECRET = "insecure_secret"
|
||||||
OAUTH_REDIRECT_URL = 'https://seafile.example.com/oauth/callback/'
|
OAUTH_REDIRECT_URL = 'https://seafile.example.com/oauth/callback/'
|
||||||
OAUTH_PROVIDER_DOMAIN = 'auth.example.com'
|
OAUTH_PROVIDER_DOMAIN = 'auth.example.com'
|
||||||
OAUTH_AUTHORIZATION_URL = 'https://auth.example.com/api/oidc/authorization'
|
OAUTH_AUTHORIZATION_URL = 'https://auth.example.com/api/oidc/authorization'
|
||||||
|
@ -82,7 +75,7 @@ which will operate with the above example:
|
||||||
```yaml
|
```yaml
|
||||||
- id: seafile
|
- id: seafile
|
||||||
description: Seafile
|
description: Seafile
|
||||||
secret: '$plaintext$seafile_client_secret'
|
secret: '$pbkdf2-sha512$310000$c8p78n7pUMln0jzvd4aK4Q$JNRBzwAo0ek5qKn50cFzzvE9RXV88h1wJn5KGiHrD0YKtZaR/nCb2CJPOsKaPK0hjf.9yHxzQGZziziccp6Yng' # The digest of 'insecure_secret'.
|
||||||
public: false
|
public: false
|
||||||
authorization_policy: two_factor
|
authorization_policy: two_factor
|
||||||
redirect_uris:
|
redirect_uris:
|
||||||
|
|
|
@ -34,6 +34,22 @@ using PBKDF2 which can be stored in the Authelia configuration.
|
||||||
|
|
||||||
### Plaintext
|
### Plaintext
|
||||||
|
|
||||||
Authelia supports storing the plaintext secret in the configuration. This may be discontinued in the future. Plaintext
|
Authelia *technically* supports storing the plaintext secret in the configuration. This will likely be completely
|
||||||
is either denoted by the `$plaintext$` prefix where everything after the prefix is the secret. In addition if the secret
|
unavailable in the future as it was a mistake to implement it like this in the first place. While some other OpenID
|
||||||
does not start with the `$` character it's considered as a plaintext secret for the time being but is deprecated.
|
Connect 1.0 providers operate in this way, it's more often than not that they operating in this way in error. The
|
||||||
|
current *technical support* for this is only to prevent massive upheaval to users and give them time to migrate.
|
||||||
|
|
||||||
|
As per [RFC6819 Section 5.1.4.1.3](https://datatracker.ietf.org/doc/html/rfc6819#section-5.1.4.1.3) the secret should
|
||||||
|
only be stored by the authorization server as hashes / digests unless there is a very specific specification or protocol
|
||||||
|
that is implemented by the authorization server which requires access to the secret in the clear to operate properly in
|
||||||
|
which case the secret should be encrypted and not be stored in plaintext. The most likely long term outcome is that the
|
||||||
|
client configurations will be stored in the database with the secret both salted and peppered.
|
||||||
|
|
||||||
|
Authelia currently does not implement any of the specifications or protocols which require secrets being accessible in
|
||||||
|
the clear and currently has no plans to implement any of these. As such it's *__strongly discouraged and heavily
|
||||||
|
deprecated__* and we instead recommended that users remove this from their configuration entirely and use the
|
||||||
|
[Generating Client Secrets](#generating-client-secrets) guide.
|
||||||
|
|
||||||
|
Plaintext is either denoted by the `$plaintext$` prefix where everything after the prefix is the secret. In addition if
|
||||||
|
the secret does not start with the `$` character it's considered as a plaintext secret for the time being but is
|
||||||
|
deprecated as is the `$plaintext$` prefix.
|
||||||
|
|
|
@ -22,14 +22,7 @@ community: true
|
||||||
|
|
||||||
## Before You Begin
|
## Before You Begin
|
||||||
|
|
||||||
### Common Notes
|
{{% oidc-common %}}
|
||||||
|
|
||||||
1. You are *__required__* to utilize a unique client id for every client.
|
|
||||||
2. The client id on this page is merely an example and you can theoretically use any alphanumeric string.
|
|
||||||
3. You *__should not__* use the client secret in this example, We *__strongly recommend__* reading the
|
|
||||||
[Generating Client Secrets] guide instead.
|
|
||||||
|
|
||||||
[Generating Client Secrets]: ../specific-information.md#generating-client-secrets
|
|
||||||
|
|
||||||
### Assumptions
|
### Assumptions
|
||||||
|
|
||||||
|
@ -38,7 +31,7 @@ This example makes the following assumptions:
|
||||||
* __Application Root URL:__ `https://matrix.example.com/`
|
* __Application Root URL:__ `https://matrix.example.com/`
|
||||||
* __Authelia Root URL:__ `https://auth.example.com`
|
* __Authelia Root URL:__ `https://auth.example.com`
|
||||||
* __Client ID:__ `synapse`
|
* __Client ID:__ `synapse`
|
||||||
* __Client Secret:__ `synapse_client_secret`
|
* __Client Secret:__ `insecure_secret`
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
|
@ -56,7 +49,7 @@ oidc_providers:
|
||||||
discover: true
|
discover: true
|
||||||
issuer: "https://auth.example.com"
|
issuer: "https://auth.example.com"
|
||||||
client_id: "synapse"
|
client_id: "synapse"
|
||||||
client_secret: "synapse_client_secret"
|
client_secret: "insecure_secret"
|
||||||
scopes: ["openid", "profile", "email"]
|
scopes: ["openid", "profile", "email"]
|
||||||
allow_existing_users: true
|
allow_existing_users: true
|
||||||
user_mapping_provider:
|
user_mapping_provider:
|
||||||
|
@ -76,7 +69,7 @@ which will operate with the above example:
|
||||||
```yaml
|
```yaml
|
||||||
- id: synapse
|
- id: synapse
|
||||||
description: Synapse
|
description: Synapse
|
||||||
secret: '$plaintext$synapse_client_secret'
|
secret: '$pbkdf2-sha512$310000$c8p78n7pUMln0jzvd4aK4Q$JNRBzwAo0ek5qKn50cFzzvE9RXV88h1wJn5KGiHrD0YKtZaR/nCb2CJPOsKaPK0hjf.9yHxzQGZziziccp6Yng' # The digest of 'insecure_secret'.
|
||||||
public: false
|
public: false
|
||||||
authorization_policy: two_factor
|
authorization_policy: two_factor
|
||||||
redirect_uris:
|
redirect_uris:
|
||||||
|
|
|
@ -22,14 +22,7 @@ community: true
|
||||||
|
|
||||||
## Before You Begin
|
## Before You Begin
|
||||||
|
|
||||||
### Common Notes
|
{{% oidc-common %}}
|
||||||
|
|
||||||
1. You are *__required__* to utilize a unique client id for every client.
|
|
||||||
2. The client id on this page is merely an example and you can theoretically use any alphanumeric string.
|
|
||||||
3. You *__should not__* use the client secret in this example, We *__strongly recommend__* reading the
|
|
||||||
[Generating Client Secrets] guide instead.
|
|
||||||
|
|
||||||
[Generating Client Secrets]: ../specific-information.md#generating-client-secrets
|
|
||||||
|
|
||||||
### Specific Notes
|
### Specific Notes
|
||||||
|
|
||||||
|
@ -43,7 +36,7 @@ This example makes the following assumptions:
|
||||||
* __Application Root URL:__ `https://dsm.example.com/`
|
* __Application Root URL:__ `https://dsm.example.com/`
|
||||||
* __Authelia Root URL:__ `https://auth.example.com`
|
* __Authelia Root URL:__ `https://auth.example.com`
|
||||||
* __Client ID:__ `synology-dsm`
|
* __Client ID:__ `synology-dsm`
|
||||||
* __Client Secret:__ `synology-dsm_client_secret`
|
* __Client Secret:__ `insecure_secret`
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
|
@ -61,7 +54,7 @@ To configure [Synology DSM] to utilize Authelia as an [OpenID Connect 1.0] Provi
|
||||||
* Name: `Authelia`
|
* Name: `Authelia`
|
||||||
* Well Known URL: `https://auth.example.com/.well-known/openid-configuration`
|
* Well Known URL: `https://auth.example.com/.well-known/openid-configuration`
|
||||||
* Application ID: `synology-dsm`
|
* Application ID: `synology-dsm`
|
||||||
* Application Key: `synology-dsm_client_secret`
|
* Application Key: `insecure_secret`
|
||||||
* Redirect URL: `https://dsm.example.com`
|
* Redirect URL: `https://dsm.example.com`
|
||||||
* Authorisation Scope: `openid profile groups email`
|
* Authorisation Scope: `openid profile groups email`
|
||||||
* Username Claim: `preferred_username`
|
* Username Claim: `preferred_username`
|
||||||
|
@ -78,7 +71,7 @@ which will operate with the above example:
|
||||||
```yaml
|
```yaml
|
||||||
- id: synology-dsm
|
- id: synology-dsm
|
||||||
description: Synology DSM
|
description: Synology DSM
|
||||||
secret: '$plaintext$synology-dsm_client_secret'
|
secret: '$pbkdf2-sha512$310000$c8p78n7pUMln0jzvd4aK4Q$JNRBzwAo0ek5qKn50cFzzvE9RXV88h1wJn5KGiHrD0YKtZaR/nCb2CJPOsKaPK0hjf.9yHxzQGZziziccp6Yng' # The digest of 'insecure_secret'.
|
||||||
public: false
|
public: false
|
||||||
authorization_policy: two_factor
|
authorization_policy: two_factor
|
||||||
redirect_uris:
|
redirect_uris:
|
||||||
|
|
|
@ -102,7 +102,7 @@ nextcloud.example.com {
|
||||||
## The following commented line is for configuring the Authelia URL in the proxy. We strongly suggest
|
## The following commented line is for configuring the Authelia URL in the proxy. We strongly suggest
|
||||||
## this is configured in the Session Cookies section of the Authelia configuration.
|
## this is configured in the Session Cookies section of the Authelia configuration.
|
||||||
# uri /api/authz/forward-auth?authelia_url=https://auth.example.com/
|
# uri /api/authz/forward-auth?authelia_url=https://auth.example.com/
|
||||||
copy_headers Remote-User Remote-Groups Remote-Name Remote-Email
|
copy_headers Authorization Proxy-Authorization Remote-User Remote-Groups Remote-Email Remote-Name
|
||||||
|
|
||||||
## This import needs to be included if you're relying on a trusted proxies configuration.
|
## This import needs to be included if you're relying on a trusted proxies configuration.
|
||||||
import trusted_proxy_list
|
import trusted_proxy_list
|
||||||
|
@ -141,7 +141,7 @@ example.com {
|
||||||
handle @nextcloud {
|
handle @nextcloud {
|
||||||
forward_auth authelia:9091 {
|
forward_auth authelia:9091 {
|
||||||
uri /api/authz/forward-auth?authelia_url=https://example.com/authelia/
|
uri /api/authz/forward-auth?authelia_url=https://example.com/authelia/
|
||||||
copy_headers Remote-User Remote-Groups Remote-Name Remote-Email
|
copy_headers Authorization Proxy-Authorization Remote-User Remote-Groups Remote-Email Remote-Name
|
||||||
|
|
||||||
## This import needs to be included if you're relying on a trusted proxies configuration.
|
## This import needs to be included if you're relying on a trusted proxies configuration.
|
||||||
import trusted_proxy_list
|
import trusted_proxy_list
|
||||||
|
@ -198,10 +198,12 @@ nextcloud.example.com {
|
||||||
## 2. Copy the relevant headers from the auth request and provide them to the backend.
|
## 2. Copy the relevant headers from the auth request and provide them to the backend.
|
||||||
@good status 2xx
|
@good status 2xx
|
||||||
handle_response @good {
|
handle_response @good {
|
||||||
|
request_header Authorization {http.reverse_proxy.header.Authorization}
|
||||||
|
request_header Proxy-Authorization {http.reverse_proxy.header.Proxy-Authorization}
|
||||||
request_header Remote-User {http.reverse_proxy.header.Remote-User}
|
request_header Remote-User {http.reverse_proxy.header.Remote-User}
|
||||||
request_header Remote-Groups {http.reverse_proxy.header.Remote-Groups}
|
request_header Remote-Groups {http.reverse_proxy.header.Remote-Groups}
|
||||||
request_header Remote-Name {http.reverse_proxy.header.Remote-Name}
|
|
||||||
request_header Remote-Email {http.reverse_proxy.header.Remote-Email}
|
request_header Remote-Email {http.reverse_proxy.header.Remote-Email}
|
||||||
|
request_header Remote-Name {http.reverse_proxy.header.Remote-Name}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -168,6 +168,13 @@ static_resources:
|
||||||
- name: envoy.filters.http.ext_authz
|
- name: envoy.filters.http.ext_authz
|
||||||
typed_config:
|
typed_config:
|
||||||
"@type": type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz
|
"@type": type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz
|
||||||
|
transport_api_version: v3
|
||||||
|
allowed_headers:
|
||||||
|
patterns:
|
||||||
|
- exact: authorization
|
||||||
|
- exact: proxy-authorization
|
||||||
|
- exact: accept
|
||||||
|
- exact: cookie
|
||||||
http_service:
|
http_service:
|
||||||
path_prefix: /api/authz/ext-authz/
|
path_prefix: /api/authz/ext-authz/
|
||||||
server_uri:
|
server_uri:
|
||||||
|
@ -177,9 +184,10 @@ static_resources:
|
||||||
authorization_request:
|
authorization_request:
|
||||||
allowed_headers:
|
allowed_headers:
|
||||||
patterns:
|
patterns:
|
||||||
|
- exact: authorization
|
||||||
|
- exact: proxy-authorization
|
||||||
- exact: accept
|
- exact: accept
|
||||||
- exact: cookie
|
- exact: cookie
|
||||||
- exact: proxy-authorization
|
|
||||||
headers_to_add:
|
headers_to_add:
|
||||||
- key: X-Forwarded-Proto
|
- key: X-Forwarded-Proto
|
||||||
value: '%REQ(:SCHEME)%'
|
value: '%REQ(:SCHEME)%'
|
||||||
|
@ -207,9 +215,9 @@ static_resources:
|
||||||
clusters:
|
clusters:
|
||||||
- name: nextcloud
|
- name: nextcloud
|
||||||
connect_timeout: 0.25s
|
connect_timeout: 0.25s
|
||||||
type: LOGICAL_DNS
|
type: logical_dns
|
||||||
dns_lookup_family: V4_ONLY
|
dns_lookup_family: v4_only
|
||||||
lb_policy: ROUND_ROBIN
|
lb_policy: round_robin
|
||||||
load_assignment:
|
load_assignment:
|
||||||
cluster_name: nextcloud
|
cluster_name: nextcloud
|
||||||
endpoints:
|
endpoints:
|
||||||
|
@ -221,9 +229,9 @@ static_resources:
|
||||||
port_value: 80
|
port_value: 80
|
||||||
- name: authelia
|
- name: authelia
|
||||||
connect_timeout: 0.25s
|
connect_timeout: 0.25s
|
||||||
type: LOGICAL_DNS
|
type: logical_dns
|
||||||
dns_lookup_family: V4_ONLY
|
dns_lookup_family: v4_only
|
||||||
lb_policy: ROUND_ROBIN
|
lb_policy: round_robin
|
||||||
load_assignment:
|
load_assignment:
|
||||||
cluster_name: authelia
|
cluster_name: authelia
|
||||||
endpoints:
|
endpoints:
|
||||||
|
@ -233,6 +241,17 @@ static_resources:
|
||||||
socket_address:
|
socket_address:
|
||||||
address: authelia
|
address: authelia
|
||||||
port_value: 9091
|
port_value: 9091
|
||||||
|
layered_runtime:
|
||||||
|
layers:
|
||||||
|
- name: static_layer_0
|
||||||
|
static_layer:
|
||||||
|
envoy:
|
||||||
|
resource_limits:
|
||||||
|
listener:
|
||||||
|
example_listener_name:
|
||||||
|
connection_limit: 10000
|
||||||
|
overload:
|
||||||
|
global_downstream_max_connections: 50000
|
||||||
```
|
```
|
||||||
{{< /details >}}
|
{{< /details >}}
|
||||||
|
|
||||||
|
|
|
@ -218,29 +218,53 @@ backend be_authelia
|
||||||
server authelia authelia:9091
|
server authelia authelia:9091
|
||||||
|
|
||||||
backend be_nextcloud
|
backend be_nextcloud
|
||||||
# Pass Remote-User, Remote-Name, Remote-Email and Remote-Groups headers
|
## Pass the special authorization response headers to the protected application.
|
||||||
|
acl authorization_exist var(req.auth_response_header.authorization) -m found
|
||||||
|
acl proxy_authorization_exist var(req.auth_response_header.proxy_authorization) -m found
|
||||||
|
|
||||||
|
http-request set-header Authorization %[var(req.auth_response_header.authorization)] if authorization_exist
|
||||||
|
http-request set-header Proxy-Authorization %[var(req.auth_response_header.proxy_authorization)] if proxy_authorization_exist
|
||||||
|
|
||||||
|
## Pass the special metadata response headers to the protected application.
|
||||||
acl remote_user_exist var(req.auth_response_header.remote_user) -m found
|
acl remote_user_exist var(req.auth_response_header.remote_user) -m found
|
||||||
acl remote_groups_exist var(req.auth_response_header.remote_groups) -m found
|
acl remote_groups_exist var(req.auth_response_header.remote_groups) -m found
|
||||||
acl remote_name_exist var(req.auth_response_header.remote_name) -m found
|
acl remote_name_exist var(req.auth_response_header.remote_name) -m found
|
||||||
acl remote_email_exist var(req.auth_response_header.remote_email) -m found
|
acl remote_email_exist var(req.auth_response_header.remote_email) -m found
|
||||||
|
|
||||||
http-request set-header Remote-User %[var(req.auth_response_header.remote_user)] if remote_user_exist
|
http-request set-header Remote-User %[var(req.auth_response_header.remote_user)] if remote_user_exist
|
||||||
http-request set-header Remote-Groups %[var(req.auth_response_header.remote_groups)] if remote_groups_exist
|
http-request set-header Remote-Groups %[var(req.auth_response_header.remote_groups)] if remote_groups_exist
|
||||||
http-request set-header Remote-Name %[var(req.auth_response_header.remote_name)] if remote_name_exist
|
http-request set-header Remote-Name %[var(req.auth_response_header.remote_name)] if remote_name_exist
|
||||||
http-request set-header Remote-Email %[var(req.auth_response_header.remote_email)] if remote_email_exist
|
http-request set-header Remote-Email %[var(req.auth_response_header.remote_email)] if remote_email_exist
|
||||||
|
|
||||||
|
## Pass the Set-Cookie response headers to the user.
|
||||||
|
acl set_cookie_exist var(req.auth_response_header.set_cookie) -m found
|
||||||
|
http-response set-header Set-Cookie %[var(req.auth_response_header.set_cookie)] if set_cookie_exist
|
||||||
|
|
||||||
server nextcloud nextcloud:443 ssl verify none
|
server nextcloud nextcloud:443 ssl verify none
|
||||||
|
|
||||||
backend be_heimdall
|
backend be_heimdall
|
||||||
# Pass Remote-User, Remote-Name, Remote-Email and Remote-Groups headers
|
## Pass the special authorization response headers to the protected application.
|
||||||
|
acl authorization_exist var(req.auth_response_header.authorization) -m found
|
||||||
|
acl proxy_authorization_exist var(req.auth_response_header.proxy_authorization) -m found
|
||||||
|
|
||||||
|
http-request set-header Authorization %[var(req.auth_response_header.authorization)] if authorization_exist
|
||||||
|
http-request set-header Proxy-Authorization %[var(req.auth_response_header.proxy_authorization)] if proxy_authorization_exist
|
||||||
|
|
||||||
|
## Pass the special metadata response headers to the protected application.
|
||||||
acl remote_user_exist var(req.auth_response_header.remote_user) -m found
|
acl remote_user_exist var(req.auth_response_header.remote_user) -m found
|
||||||
acl remote_groups_exist var(req.auth_response_header.remote_groups) -m found
|
acl remote_groups_exist var(req.auth_response_header.remote_groups) -m found
|
||||||
acl remote_name_exist var(req.auth_response_header.remote_name) -m found
|
acl remote_name_exist var(req.auth_response_header.remote_name) -m found
|
||||||
acl remote_email_exist var(req.auth_response_header.remote_email) -m found
|
acl remote_email_exist var(req.auth_response_header.remote_email) -m found
|
||||||
|
|
||||||
http-request set-header Remote-User %[var(req.auth_response_header.remote_user)] if remote_user_exist
|
http-request set-header Remote-User %[var(req.auth_response_header.remote_user)] if remote_user_exist
|
||||||
http-request set-header Remote-Groups %[var(req.auth_response_header.remote_groups)] if remote_groups_exist
|
http-request set-header Remote-Groups %[var(req.auth_response_header.remote_groups)] if remote_groups_exist
|
||||||
http-request set-header Remote-Name %[var(req.auth_response_header.remote_name)] if remote_name_exist
|
http-request set-header Remote-Name %[var(req.auth_response_header.remote_name)] if remote_name_exist
|
||||||
http-request set-header Remote-Email %[var(req.auth_response_header.remote_email)] if remote_email_exist
|
http-request set-header Remote-Email %[var(req.auth_response_header.remote_email)] if remote_email_exist
|
||||||
|
|
||||||
|
## Pass the Set-Cookie response headers to the user.
|
||||||
|
acl set_cookie_exist var(req.auth_response_header.set_cookie) -m found
|
||||||
|
http-response set-header Set-Cookie %[var(req.auth_response_header.set_cookie)] if set_cookie_exist
|
||||||
|
|
||||||
server heimdall heimdall:443 ssl verify none
|
server heimdall heimdall:443 ssl verify none
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -325,29 +349,53 @@ listen authelia_proxy
|
||||||
server authelia authelia:9091 ssl verify none
|
server authelia authelia:9091 ssl verify none
|
||||||
|
|
||||||
backend be_nextcloud
|
backend be_nextcloud
|
||||||
# Pass Remote-User, Remote-Name, Remote-Email and Remote-Groups headers
|
## Pass the special authorization response headers to the protected application.
|
||||||
|
acl authorization_exist var(req.auth_response_header.authorization) -m found
|
||||||
|
acl proxy_authorization_exist var(req.auth_response_header.proxy_authorization) -m found
|
||||||
|
|
||||||
|
http-request set-header Authorization %[var(req.auth_response_header.authorization)] if authorization_exist
|
||||||
|
http-request set-header Proxy-Authorization %[var(req.auth_response_header.proxy_authorization)] if proxy_authorization_exist
|
||||||
|
|
||||||
|
## Pass the special metadata response headers to the protected application.
|
||||||
acl remote_user_exist var(req.auth_response_header.remote_user) -m found
|
acl remote_user_exist var(req.auth_response_header.remote_user) -m found
|
||||||
acl remote_groups_exist var(req.auth_response_header.remote_groups) -m found
|
acl remote_groups_exist var(req.auth_response_header.remote_groups) -m found
|
||||||
acl remote_name_exist var(req.auth_response_header.remote_name) -m found
|
acl remote_name_exist var(req.auth_response_header.remote_name) -m found
|
||||||
acl remote_email_exist var(req.auth_response_header.remote_email) -m found
|
acl remote_email_exist var(req.auth_response_header.remote_email) -m found
|
||||||
|
|
||||||
http-request set-header Remote-User %[var(req.auth_response_header.remote_user)] if remote_user_exist
|
http-request set-header Remote-User %[var(req.auth_response_header.remote_user)] if remote_user_exist
|
||||||
http-request set-header Remote-Groups %[var(req.auth_response_header.remote_groups)] if remote_groups_exist
|
http-request set-header Remote-Groups %[var(req.auth_response_header.remote_groups)] if remote_groups_exist
|
||||||
http-request set-header Remote-Name %[var(req.auth_response_header.remote_name)] if remote_name_exist
|
http-request set-header Remote-Name %[var(req.auth_response_header.remote_name)] if remote_name_exist
|
||||||
http-request set-header Remote-Email %[var(req.auth_response_header.remote_email)] if remote_email_exist
|
http-request set-header Remote-Email %[var(req.auth_response_header.remote_email)] if remote_email_exist
|
||||||
|
|
||||||
|
## Pass the Set-Cookie response headers to the user.
|
||||||
|
acl set_cookie_exist var(req.auth_response_header.set_cookie) -m found
|
||||||
|
http-response set-header Set-Cookie %[var(req.auth_response_header.set_cookie)] if set_cookie_exist
|
||||||
|
|
||||||
server nextcloud nextcloud:443 ssl verify none
|
server nextcloud nextcloud:443 ssl verify none
|
||||||
|
|
||||||
backend be_heimdall
|
backend be_heimdall
|
||||||
# Pass Remote-User, Remote-Name, Remote-Email and Remote-Groups headers
|
## Pass the special authorization response headers to the protected application.
|
||||||
|
acl authorization_exist var(req.auth_response_header.authorization) -m found
|
||||||
|
acl proxy_authorization_exist var(req.auth_response_header.proxy_authorization) -m found
|
||||||
|
|
||||||
|
http-request set-header Authorization %[var(req.auth_response_header.authorization)] if authorization_exist
|
||||||
|
http-request set-header Proxy-Authorization %[var(req.auth_response_header.proxy_authorization)] if proxy_authorization_exist
|
||||||
|
|
||||||
|
## Pass the special metadata response headers to the protected application.
|
||||||
acl remote_user_exist var(req.auth_response_header.remote_user) -m found
|
acl remote_user_exist var(req.auth_response_header.remote_user) -m found
|
||||||
acl remote_groups_exist var(req.auth_response_header.remote_groups) -m found
|
acl remote_groups_exist var(req.auth_response_header.remote_groups) -m found
|
||||||
acl remote_name_exist var(req.auth_response_header.remote_name) -m found
|
acl remote_name_exist var(req.auth_response_header.remote_name) -m found
|
||||||
acl remote_email_exist var(req.auth_response_header.remote_email) -m found
|
acl remote_email_exist var(req.auth_response_header.remote_email) -m found
|
||||||
|
|
||||||
http-request set-header Remote-User %[var(req.auth_response_header.remote_user)] if remote_user_exist
|
http-request set-header Remote-User %[var(req.auth_response_header.remote_user)] if remote_user_exist
|
||||||
http-request set-header Remote-Groups %[var(req.auth_response_header.remote_groups)] if remote_groups_exist
|
http-request set-header Remote-Groups %[var(req.auth_response_header.remote_groups)] if remote_groups_exist
|
||||||
http-request set-header Remote-Name %[var(req.auth_response_header.remote_name)] if remote_name_exist
|
http-request set-header Remote-Name %[var(req.auth_response_header.remote_name)] if remote_name_exist
|
||||||
http-request set-header Remote-Email %[var(req.auth_response_header.remote_email)] if remote_email_exist
|
http-request set-header Remote-Email %[var(req.auth_response_header.remote_email)] if remote_email_exist
|
||||||
|
|
||||||
|
## Pass the Set-Cookie response headers to the user.
|
||||||
|
acl set_cookie_exist var(req.auth_response_header.set_cookie) -m found
|
||||||
|
http-response set-header Set-Cookie %[var(req.auth_response_header.set_cookie)] if set_cookie_exist
|
||||||
|
|
||||||
server heimdall heimdall:443 ssl verify none
|
server heimdall heimdall:443 ssl verify none
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -433,17 +433,29 @@ set_escape_uri $target_url $scheme://$http_host$request_uri;
|
||||||
## Uncomment this line if you're using NGINX without the http_set_misc module.
|
## Uncomment this line if you're using NGINX without the http_set_misc module.
|
||||||
# set $target_url $scheme://$http_host$request_uri;
|
# set $target_url $scheme://$http_host$request_uri;
|
||||||
|
|
||||||
## Save the upstream response headers from Authelia to variables.
|
## Save the upstream authorization response headers from Authelia to variables.
|
||||||
|
auth_request_set $authorization $upstream_http_authorization;
|
||||||
|
auth_request_set $proxy_authorization $upstream_http_proxy_authorization;
|
||||||
|
|
||||||
|
## Inject the authorization response headers from the variables into the request made to the backend.
|
||||||
|
proxy_set_header Authorization $authorization;
|
||||||
|
proxy_set_header Proxy-Authorization $proxy_authorization;
|
||||||
|
|
||||||
|
## Save the upstream metadata response headers from Authelia to variables.
|
||||||
auth_request_set $user $upstream_http_remote_user;
|
auth_request_set $user $upstream_http_remote_user;
|
||||||
auth_request_set $groups $upstream_http_remote_groups;
|
auth_request_set $groups $upstream_http_remote_groups;
|
||||||
auth_request_set $name $upstream_http_remote_name;
|
auth_request_set $name $upstream_http_remote_name;
|
||||||
auth_request_set $email $upstream_http_remote_email;
|
auth_request_set $email $upstream_http_remote_email;
|
||||||
|
|
||||||
## Inject the response headers from the variables into the request made to the backend.
|
## Inject the metadata response headers from the variables into the request made to the backend.
|
||||||
proxy_set_header Remote-User $user;
|
proxy_set_header Remote-User $user;
|
||||||
proxy_set_header Remote-Groups $groups;
|
proxy_set_header Remote-Groups $groups;
|
||||||
proxy_set_header Remote-Name $name;
|
|
||||||
proxy_set_header Remote-Email $email;
|
proxy_set_header Remote-Email $email;
|
||||||
|
proxy_set_header Remote-Name $name;
|
||||||
|
|
||||||
|
## Include the Set-Cookie header if present.
|
||||||
|
auth_request_set $cookie $upstream_http_set_cookie;
|
||||||
|
add_header Set-Cookie $cookie;
|
||||||
|
|
||||||
## If the subreqest returns 200 pass to the backend, if the subrequest returns 401 redirect to the portal.
|
## If the subreqest returns 200 pass to the backend, if the subrequest returns 401 redirect to the portal.
|
||||||
error_page 401 =302 https://auth.example.com/?rd=$target_url;
|
error_page 401 =302 https://auth.example.com/?rd=$target_url;
|
||||||
|
|
|
@ -157,7 +157,7 @@ services:
|
||||||
## configured in the Session Cookies section of the Authelia configuration.
|
## configured in the Session Cookies section of the Authelia configuration.
|
||||||
# - 'traefik.http.middlewares.authelia.forwardAuth.address=http://authelia:9091/api/authz/forward-auth?authelia_url=https%3A%2F%2Fauth.example.com%2F'
|
# - 'traefik.http.middlewares.authelia.forwardAuth.address=http://authelia:9091/api/authz/forward-auth?authelia_url=https%3A%2F%2Fauth.example.com%2F'
|
||||||
- 'traefik.http.middlewares.authelia.forwardAuth.trustForwardHeader=true'
|
- 'traefik.http.middlewares.authelia.forwardAuth.trustForwardHeader=true'
|
||||||
- 'traefik.http.middlewares.authelia.forwardAuth.authResponseHeaders=Authorization,Proxy-Authorization,Remote-User,Remote-Groups,Remote-Name,Remote-Email'
|
- 'traefik.http.middlewares.authelia.forwardAuth.authResponseHeaders=Authorization,Proxy-Authorization,Remote-User,Remote-Groups,Remote-Email,Remote-Name'
|
||||||
nextcloud:
|
nextcloud:
|
||||||
container_name: nextcloud
|
container_name: nextcloud
|
||||||
image: linuxserver/nextcloud
|
image: linuxserver/nextcloud
|
||||||
|
@ -503,7 +503,7 @@ This can be avoided a couple different ways:
|
||||||
## configured in the Session Cookies section of the Authelia configuration.
|
## configured in the Session Cookies section of the Authelia configuration.
|
||||||
# - 'traefik.http.middlewares.authelia.forwardAuth.address=http://authelia:9091/api/authz/forward-auth?authelia_url=https%3A%2F%2Fauth.example.com%2F'
|
# - 'traefik.http.middlewares.authelia.forwardAuth.address=http://authelia:9091/api/authz/forward-auth?authelia_url=https%3A%2F%2Fauth.example.com%2F'
|
||||||
- 'traefik.http.middlewares.authelia.forwardAuth.trustForwardHeader=true'
|
- 'traefik.http.middlewares.authelia.forwardAuth.trustForwardHeader=true'
|
||||||
- 'traefik.http.middlewares.authelia.forwardAuth.authResponseHeaders=Authorization,Proxy-Authorization,Remote-User,Remote-Groups,Remote-Name,Remote-Email'
|
- 'traefik.http.middlewares.authelia.forwardAuth.authResponseHeaders=Authorization,Proxy-Authorization,Remote-User,Remote-Groups,Remote-Email,Remote-Name'
|
||||||
```
|
```
|
||||||
|
|
||||||
## See Also
|
## See Also
|
||||||
|
|
|
@ -137,7 +137,7 @@ services:
|
||||||
## configured in the Session Cookies section of the Authelia configuration.
|
## configured in the Session Cookies section of the Authelia configuration.
|
||||||
# - 'traefik.frontend.auth.forward.address=http://authelia:9091/api/authz/forward-auth?authelia_url=https%3A%2F%2Fauth.example.com%2F'
|
# - 'traefik.frontend.auth.forward.address=http://authelia:9091/api/authz/forward-auth?authelia_url=https%3A%2F%2Fauth.example.com%2F'
|
||||||
- 'traefik.frontend.auth.forward.trustForwardHeader=true'
|
- 'traefik.frontend.auth.forward.trustForwardHeader=true'
|
||||||
- 'traefik.frontend.auth.forward.authResponseHeaders=Authorization,Proxy-Authorization,Remote-User,Remote-Groups,Remote-Name,Remote-Email'
|
- 'traefik.frontend.auth.forward.authResponseHeaders=Authorization,Proxy-Authorization,Remote-User,Remote-Groups,Remote-Email,Remote-Name'
|
||||||
expose:
|
expose:
|
||||||
- 443
|
- 443
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
@ -156,7 +156,7 @@ services:
|
||||||
- 'traefik.frontend.rule=Host:heimdall.example.com'
|
- 'traefik.frontend.rule=Host:heimdall.example.com'
|
||||||
- 'traefik.frontend.auth.forward.address=http://authelia:9091/api/authz/forward-auth/basic'
|
- 'traefik.frontend.auth.forward.address=http://authelia:9091/api/authz/forward-auth/basic'
|
||||||
- 'traefik.frontend.auth.forward.trustForwardHeader=true'
|
- 'traefik.frontend.auth.forward.trustForwardHeader=true'
|
||||||
- 'traefik.frontend.auth.forward.authResponseHeaders=Authorization,Proxy-Authorization,Remote-User,Remote-Groups,Remote-Name,Remote-Email'
|
- 'traefik.frontend.auth.forward.authResponseHeaders=Authorization,Proxy-Authorization,Remote-User,Remote-Groups,Remote-Email,Remote-Name'
|
||||||
expose:
|
expose:
|
||||||
- 443
|
- 443
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
|
|
@ -216,9 +216,9 @@ to port 587 (_the `submission` port, a common alternative that uses STARTTLS ins
|
||||||
|
|
||||||
[docs-config-smtp-port]: ../../configuration/notifications/smtp.md#port
|
[docs-config-smtp-port]: ../../configuration/notifications/smtp.md#port
|
||||||
[cleartext]: https://cwe.mitre.org/data/definitions/312.html
|
[cleartext]: https://cwe.mitre.org/data/definitions/312.html
|
||||||
[service-submissions]: https://www.rfc-editor.org/rfc/rfc8314#section-7.3
|
[service-submissions]: https://datatracker.ietf.org/doc/html/rfc8314#section-7.3
|
||||||
[port-465]: https://www.rfc-editor.org/rfc/rfc8314#section-3.3
|
[port-465]: https://datatracker.ietf.org/doc/html/rfc8314#section-3.3
|
||||||
[smtp-auth]: https://www.rfc-editor.org/rfc/rfc6409#section-4.3
|
[smtp-auth]: https://datatracker.ietf.org/doc/html/rfc6409#section-4.3
|
||||||
|
|
||||||
## Protection against open redirects
|
## Protection against open redirects
|
||||||
|
|
||||||
|
|
|
@ -35,28 +35,31 @@ authelia crypto certificate ecdsa generate --help
|
||||||
### Options
|
### Options
|
||||||
|
|
||||||
```
|
```
|
||||||
--ca create the certificate as a certificate authority certificate
|
--bundle enables generating the certificate bundle if the --path.ca flag is set
|
||||||
-n, --common-name string certificate common name
|
--ca create the certificate as a certificate authority certificate
|
||||||
--country strings certificate country
|
-n, --common-name string certificate common name
|
||||||
-b, --curve string Sets the elliptic curve which can be P224, P256, P384, or P521 (default "P256")
|
--country strings certificate country
|
||||||
-d, --directory string directory where the generated keys, certificates, etc will be stored
|
-b, --curve string Sets the elliptic curve which can be P224, P256, P384, or P521 (default "P256")
|
||||||
--duration duration duration of time the certificate is valid for (default 8760h0m0s)
|
-d, --directory string directory where the generated keys, certificates, etc will be stored
|
||||||
--extended-usage strings specify the extended usage types of the certificate
|
--duration string duration of time the certificate is valid for (default "1y")
|
||||||
--file.ca-certificate string certificate authority certificate to use when signing this certificate (default "ca.public.crt")
|
--extended-usage strings specify the extended usage types of the certificate
|
||||||
--file.ca-private-key string certificate authority private key to use to signing this certificate (default "ca.private.pem")
|
--file.ca-certificate string certificate authority certificate to use when signing this certificate (default "ca.public.crt")
|
||||||
--file.certificate string name of the file to export the certificate data to (default "public.crt")
|
--file.ca-private-key string certificate authority private key to use to signing this certificate (default "ca.private.pem")
|
||||||
--file.private-key string name of the file to export the private key data to (default "private.pem")
|
--file.certificate string name of the file to export the certificate data to (default "public.crt")
|
||||||
-h, --help help for generate
|
--file.certificate-bundle string name of the file to export the certificate bundle data to when the --bundle flag is set (default "public.bundle.crt")
|
||||||
-l, --locality strings certificate locality
|
--file.private-key string name of the file to export the private key data to (default "private.pem")
|
||||||
--not-before string earliest date and time the certificate is considered valid formatted as Jan 2 15:04:05 2006 (default is now)
|
-h, --help help for generate
|
||||||
-o, --organization strings certificate organization (default [Authelia])
|
-l, --locality strings certificate locality
|
||||||
--organizational-unit strings certificate organizational unit
|
--not-after string latest date and time the certificate is considered valid in various formats
|
||||||
--path.ca string source directory of the certificate authority files, if not provided the certificate will be self-signed
|
--not-before string earliest date and time the certificate is considered valid in various formats (default is now)
|
||||||
-p, --postcode strings certificate postcode
|
-o, --organization strings certificate organization (default [Authelia])
|
||||||
--province strings certificate province
|
--organizational-unit strings certificate organizational unit
|
||||||
--sans strings subject alternative names
|
--path.ca string source directory of the certificate authority files, if not provided the certificate will be self-signed
|
||||||
--signature string signature algorithm for the certificate (default "SHA256")
|
-p, --postcode strings certificate postcode
|
||||||
-s, --street-address strings certificate street address
|
--province strings certificate province
|
||||||
|
--sans strings subject alternative names
|
||||||
|
--signature string signature algorithm for the certificate (default "SHA256")
|
||||||
|
-s, --street-address strings certificate street address
|
||||||
```
|
```
|
||||||
|
|
||||||
### Options inherited from parent commands
|
### Options inherited from parent commands
|
||||||
|
|
|
@ -39,12 +39,13 @@ authelia crypto certificate ecdsa request --help
|
||||||
--country strings certificate country
|
--country strings certificate country
|
||||||
-b, --curve string Sets the elliptic curve which can be P224, P256, P384, or P521 (default "P256")
|
-b, --curve string Sets the elliptic curve which can be P224, P256, P384, or P521 (default "P256")
|
||||||
-d, --directory string directory where the generated keys, certificates, etc will be stored
|
-d, --directory string directory where the generated keys, certificates, etc will be stored
|
||||||
--duration duration duration of time the certificate is valid for (default 8760h0m0s)
|
--duration string duration of time the certificate is valid for (default "1y")
|
||||||
--file.csr string name of the file to export the certificate request data to (default "request.csr")
|
--file.csr string name of the file to export the certificate request data to (default "request.csr")
|
||||||
--file.private-key string name of the file to export the private key data to (default "private.pem")
|
--file.private-key string name of the file to export the private key data to (default "private.pem")
|
||||||
-h, --help help for request
|
-h, --help help for request
|
||||||
-l, --locality strings certificate locality
|
-l, --locality strings certificate locality
|
||||||
--not-before string earliest date and time the certificate is considered valid formatted as Jan 2 15:04:05 2006 (default is now)
|
--not-after string latest date and time the certificate is considered valid in various formats
|
||||||
|
--not-before string earliest date and time the certificate is considered valid in various formats (default is now)
|
||||||
-o, --organization strings certificate organization (default [Authelia])
|
-o, --organization strings certificate organization (default [Authelia])
|
||||||
--organizational-unit strings certificate organizational unit
|
--organizational-unit strings certificate organizational unit
|
||||||
-p, --postcode strings certificate postcode
|
-p, --postcode strings certificate postcode
|
||||||
|
|
|
@ -35,27 +35,30 @@ authelia crypto certificate ed25519 request --help
|
||||||
### Options
|
### Options
|
||||||
|
|
||||||
```
|
```
|
||||||
--ca create the certificate as a certificate authority certificate
|
--bundle enables generating the certificate bundle if the --path.ca flag is set
|
||||||
-n, --common-name string certificate common name
|
--ca create the certificate as a certificate authority certificate
|
||||||
--country strings certificate country
|
-n, --common-name string certificate common name
|
||||||
-d, --directory string directory where the generated keys, certificates, etc will be stored
|
--country strings certificate country
|
||||||
--duration duration duration of time the certificate is valid for (default 8760h0m0s)
|
-d, --directory string directory where the generated keys, certificates, etc will be stored
|
||||||
--extended-usage strings specify the extended usage types of the certificate
|
--duration string duration of time the certificate is valid for (default "1y")
|
||||||
--file.ca-certificate string certificate authority certificate to use when signing this certificate (default "ca.public.crt")
|
--extended-usage strings specify the extended usage types of the certificate
|
||||||
--file.ca-private-key string certificate authority private key to use to signing this certificate (default "ca.private.pem")
|
--file.ca-certificate string certificate authority certificate to use when signing this certificate (default "ca.public.crt")
|
||||||
--file.certificate string name of the file to export the certificate data to (default "public.crt")
|
--file.ca-private-key string certificate authority private key to use to signing this certificate (default "ca.private.pem")
|
||||||
--file.private-key string name of the file to export the private key data to (default "private.pem")
|
--file.certificate string name of the file to export the certificate data to (default "public.crt")
|
||||||
-h, --help help for generate
|
--file.certificate-bundle string name of the file to export the certificate bundle data to when the --bundle flag is set (default "public.bundle.crt")
|
||||||
-l, --locality strings certificate locality
|
--file.private-key string name of the file to export the private key data to (default "private.pem")
|
||||||
--not-before string earliest date and time the certificate is considered valid formatted as Jan 2 15:04:05 2006 (default is now)
|
-h, --help help for generate
|
||||||
-o, --organization strings certificate organization (default [Authelia])
|
-l, --locality strings certificate locality
|
||||||
--organizational-unit strings certificate organizational unit
|
--not-after string latest date and time the certificate is considered valid in various formats
|
||||||
--path.ca string source directory of the certificate authority files, if not provided the certificate will be self-signed
|
--not-before string earliest date and time the certificate is considered valid in various formats (default is now)
|
||||||
-p, --postcode strings certificate postcode
|
-o, --organization strings certificate organization (default [Authelia])
|
||||||
--province strings certificate province
|
--organizational-unit strings certificate organizational unit
|
||||||
--sans strings subject alternative names
|
--path.ca string source directory of the certificate authority files, if not provided the certificate will be self-signed
|
||||||
--signature string signature algorithm for the certificate (default "SHA256")
|
-p, --postcode strings certificate postcode
|
||||||
-s, --street-address strings certificate street address
|
--province strings certificate province
|
||||||
|
--sans strings subject alternative names
|
||||||
|
--signature string signature algorithm for the certificate (default "SHA256")
|
||||||
|
-s, --street-address strings certificate street address
|
||||||
```
|
```
|
||||||
|
|
||||||
### Options inherited from parent commands
|
### Options inherited from parent commands
|
||||||
|
|
|
@ -38,12 +38,13 @@ authelia crypto certificate ed25519 request --help
|
||||||
-n, --common-name string certificate common name
|
-n, --common-name string certificate common name
|
||||||
--country strings certificate country
|
--country strings certificate country
|
||||||
-d, --directory string directory where the generated keys, certificates, etc will be stored
|
-d, --directory string directory where the generated keys, certificates, etc will be stored
|
||||||
--duration duration duration of time the certificate is valid for (default 8760h0m0s)
|
--duration string duration of time the certificate is valid for (default "1y")
|
||||||
--file.csr string name of the file to export the certificate request data to (default "request.csr")
|
--file.csr string name of the file to export the certificate request data to (default "request.csr")
|
||||||
--file.private-key string name of the file to export the private key data to (default "private.pem")
|
--file.private-key string name of the file to export the private key data to (default "private.pem")
|
||||||
-h, --help help for request
|
-h, --help help for request
|
||||||
-l, --locality strings certificate locality
|
-l, --locality strings certificate locality
|
||||||
--not-before string earliest date and time the certificate is considered valid formatted as Jan 2 15:04:05 2006 (default is now)
|
--not-after string latest date and time the certificate is considered valid in various formats
|
||||||
|
--not-before string earliest date and time the certificate is considered valid in various formats (default is now)
|
||||||
-o, --organization strings certificate organization (default [Authelia])
|
-o, --organization strings certificate organization (default [Authelia])
|
||||||
--organizational-unit strings certificate organizational unit
|
--organizational-unit strings certificate organizational unit
|
||||||
-p, --postcode strings certificate postcode
|
-p, --postcode strings certificate postcode
|
||||||
|
|
|
@ -35,28 +35,31 @@ authelia crypto certificate rsa generate --help
|
||||||
### Options
|
### Options
|
||||||
|
|
||||||
```
|
```
|
||||||
-b, --bits int number of RSA bits for the certificate (default 2048)
|
-b, --bits int number of RSA bits for the certificate (default 2048)
|
||||||
--ca create the certificate as a certificate authority certificate
|
--bundle enables generating the certificate bundle if the --path.ca flag is set
|
||||||
-n, --common-name string certificate common name
|
--ca create the certificate as a certificate authority certificate
|
||||||
--country strings certificate country
|
-n, --common-name string certificate common name
|
||||||
-d, --directory string directory where the generated keys, certificates, etc will be stored
|
--country strings certificate country
|
||||||
--duration duration duration of time the certificate is valid for (default 8760h0m0s)
|
-d, --directory string directory where the generated keys, certificates, etc will be stored
|
||||||
--extended-usage strings specify the extended usage types of the certificate
|
--duration string duration of time the certificate is valid for (default "1y")
|
||||||
--file.ca-certificate string certificate authority certificate to use when signing this certificate (default "ca.public.crt")
|
--extended-usage strings specify the extended usage types of the certificate
|
||||||
--file.ca-private-key string certificate authority private key to use to signing this certificate (default "ca.private.pem")
|
--file.ca-certificate string certificate authority certificate to use when signing this certificate (default "ca.public.crt")
|
||||||
--file.certificate string name of the file to export the certificate data to (default "public.crt")
|
--file.ca-private-key string certificate authority private key to use to signing this certificate (default "ca.private.pem")
|
||||||
--file.private-key string name of the file to export the private key data to (default "private.pem")
|
--file.certificate string name of the file to export the certificate data to (default "public.crt")
|
||||||
-h, --help help for generate
|
--file.certificate-bundle string name of the file to export the certificate bundle data to when the --bundle flag is set (default "public.bundle.crt")
|
||||||
-l, --locality strings certificate locality
|
--file.private-key string name of the file to export the private key data to (default "private.pem")
|
||||||
--not-before string earliest date and time the certificate is considered valid formatted as Jan 2 15:04:05 2006 (default is now)
|
-h, --help help for generate
|
||||||
-o, --organization strings certificate organization (default [Authelia])
|
-l, --locality strings certificate locality
|
||||||
--organizational-unit strings certificate organizational unit
|
--not-after string latest date and time the certificate is considered valid in various formats
|
||||||
--path.ca string source directory of the certificate authority files, if not provided the certificate will be self-signed
|
--not-before string earliest date and time the certificate is considered valid in various formats (default is now)
|
||||||
-p, --postcode strings certificate postcode
|
-o, --organization strings certificate organization (default [Authelia])
|
||||||
--province strings certificate province
|
--organizational-unit strings certificate organizational unit
|
||||||
--sans strings subject alternative names
|
--path.ca string source directory of the certificate authority files, if not provided the certificate will be self-signed
|
||||||
--signature string signature algorithm for the certificate (default "SHA256")
|
-p, --postcode strings certificate postcode
|
||||||
-s, --street-address strings certificate street address
|
--province strings certificate province
|
||||||
|
--sans strings subject alternative names
|
||||||
|
--signature string signature algorithm for the certificate (default "SHA256")
|
||||||
|
-s, --street-address strings certificate street address
|
||||||
```
|
```
|
||||||
|
|
||||||
### Options inherited from parent commands
|
### Options inherited from parent commands
|
||||||
|
|
|
@ -39,12 +39,13 @@ authelia crypto certificate rsa request --help
|
||||||
-n, --common-name string certificate common name
|
-n, --common-name string certificate common name
|
||||||
--country strings certificate country
|
--country strings certificate country
|
||||||
-d, --directory string directory where the generated keys, certificates, etc will be stored
|
-d, --directory string directory where the generated keys, certificates, etc will be stored
|
||||||
--duration duration duration of time the certificate is valid for (default 8760h0m0s)
|
--duration string duration of time the certificate is valid for (default "1y")
|
||||||
--file.csr string name of the file to export the certificate request data to (default "request.csr")
|
--file.csr string name of the file to export the certificate request data to (default "request.csr")
|
||||||
--file.private-key string name of the file to export the private key data to (default "private.pem")
|
--file.private-key string name of the file to export the private key data to (default "private.pem")
|
||||||
-h, --help help for request
|
-h, --help help for request
|
||||||
-l, --locality strings certificate locality
|
-l, --locality strings certificate locality
|
||||||
--not-before string earliest date and time the certificate is considered valid formatted as Jan 2 15:04:05 2006 (default is now)
|
--not-after string latest date and time the certificate is considered valid in various formats
|
||||||
|
--not-before string earliest date and time the certificate is considered valid in various formats (default is now)
|
||||||
-o, --organization strings certificate organization (default [Authelia])
|
-o, --organization strings certificate organization (default [Authelia])
|
||||||
--organizational-unit strings certificate organizational unit
|
--organizational-unit strings certificate organizational unit
|
||||||
-p, --postcode strings certificate postcode
|
-p, --postcode strings certificate postcode
|
||||||
|
|
|
@ -56,6 +56,9 @@ The following implementations exist:
|
||||||
- Specific configuration defaults for [Active Directory]
|
- Specific configuration defaults for [Active Directory]
|
||||||
- Special implementation details:
|
- Special implementation details:
|
||||||
- Includes a special encoding format required for changing passwords with [Active Directory]
|
- Includes a special encoding format required for changing passwords with [Active Directory]
|
||||||
|
- `rfc2307bis`:
|
||||||
|
- Specific configuration defaults for [RFC2307bis]
|
||||||
|
- No special implementation details
|
||||||
- `freeipa`:
|
- `freeipa`:
|
||||||
- Specific configuration defaults for [FreeIPA]
|
- Specific configuration defaults for [FreeIPA]
|
||||||
- No special implementation details
|
- No special implementation details
|
||||||
|
@ -70,11 +73,17 @@ The following implementations exist:
|
||||||
[FreeIPA]: https://www.freeipa.org/
|
[FreeIPA]: https://www.freeipa.org/
|
||||||
[lldap]: https://github.com/nitnelave/lldap
|
[lldap]: https://github.com/nitnelave/lldap
|
||||||
[GLAuth]: https://glauth.github.io/
|
[GLAuth]: https://glauth.github.io/
|
||||||
|
[RFC2307bis]: https://datatracker.ietf.org/doc/html/draft-howard-rfc2307bis-02
|
||||||
|
|
||||||
### Filter replacements
|
### Filter replacements
|
||||||
|
|
||||||
Various replacements occur in the user and groups filter. The replacements either occur at startup or upon an LDAP
|
Various replacements occur in the user and groups filter. The replacements either occur at startup or upon an LDAP
|
||||||
search.
|
search which is indicated by the phase column.
|
||||||
|
|
||||||
|
The phases exist to optimize performance. The replacements in the startup phase are replaced once before the connection
|
||||||
|
is ever established. In addition to this, during the startup phase we purposefully check the filters for which search
|
||||||
|
phase replacements exist so we only have to check if the replacement is necessary once, and we don't needlessly perform
|
||||||
|
every possible replacement on every search regardless of if it's needed or not.
|
||||||
|
|
||||||
#### Users filter replacements
|
#### Users filter replacements
|
||||||
|
|
||||||
|
@ -117,6 +126,7 @@ Username column.
|
||||||
|:---------------:|:--------------:|:------------:|:----:|:----------:|
|
|:---------------:|:--------------:|:------------:|:----:|:----------:|
|
||||||
| custom | N/A | displayName | mail | cn |
|
| custom | N/A | displayName | mail | cn |
|
||||||
| activedirectory | sAMAccountName | displayName | mail | cn |
|
| activedirectory | sAMAccountName | displayName | mail | cn |
|
||||||
|
| rfc2307bis | uid | displayName | mail | cn |
|
||||||
| freeipa | uid | displayName | mail | cn |
|
| freeipa | uid | displayName | mail | cn |
|
||||||
| lldap | uid | cn | mail | cn |
|
| lldap | uid | cn | mail | cn |
|
||||||
| glauth | cn | description | mail | cn |
|
| glauth | cn | description | mail | cn |
|
||||||
|
@ -130,20 +140,32 @@ the following conditions:
|
||||||
- The [Active Directory] implementation achieves this via the `(!(userAccountControl:1.2.840.113556.1.4.803:=2))` filter.
|
- The [Active Directory] implementation achieves this via the `(!(userAccountControl:1.2.840.113556.1.4.803:=2))` filter.
|
||||||
- The [FreeIPA] implementation achieves this via the `(!(nsAccountLock=TRUE))` filter.
|
- The [FreeIPA] implementation achieves this via the `(!(nsAccountLock=TRUE))` filter.
|
||||||
- The [GLAuth] implementation achieves this via the `(!(accountStatus=inactive))` filter.
|
- The [GLAuth] implementation achieves this via the `(!(accountStatus=inactive))` filter.
|
||||||
|
- The following implementations have no suitable attribute for this as far as we're aware:
|
||||||
|
- [RFC2307bis]
|
||||||
|
- [lldap]
|
||||||
- Their password is expired:
|
- Their password is expired:
|
||||||
- The [Active Directory] implementation achieves this via the `(!(pwdLastSet=0))` filter.
|
- The [Active Directory] implementation achieves this via the `(!(pwdLastSet=0))` filter.
|
||||||
- The [FreeIPA] implementation achieves this via the `(krbPasswordExpiration>={date-time:generalized})` filter.
|
- The [FreeIPA] implementation achieves this via the `(krbPasswordExpiration>={date-time:generalized})` filter.
|
||||||
|
- The following implementations have no suitable attribute for this as far as we're aware:
|
||||||
|
- [RFC2307bis]
|
||||||
|
- [GLAuth]
|
||||||
|
- [lldap]
|
||||||
- Their account is expired:
|
- Their account is expired:
|
||||||
- The [Active Directory] implementation achieves this via the `(|(!(accountExpires=*))(accountExpires=0)(accountExpires>={date-time:microsoft-nt}))` filter.
|
- The [Active Directory] implementation achieves this via the `(|(!(accountExpires=*))(accountExpires=0)(accountExpires>={date-time:microsoft-nt}))` filter.
|
||||||
- The [FreeIPA] implementation achieves this via the `(|(!(krbPrincipalExpiration=*))(krbPrincipalExpiration>={date-time:generalized}))` filter.
|
- The [FreeIPA] implementation achieves this via the `(|(!(krbPrincipalExpiration=*))(krbPrincipalExpiration>={date-time:generalized}))` filter.
|
||||||
|
- The following implementations have no suitable attribute for this as far as we're aware:
|
||||||
|
- [RFC2307bis]
|
||||||
|
- [GLAuth]
|
||||||
|
- [lldap]
|
||||||
|
|
||||||
| Implementation | Users Filter | Groups Filter |
|
| Implementation | Users Filter | Groups Filter |
|
||||||
|:---------------:|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|:----------------------------------------------------------------------------:|
|
|:---------------:|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|:-----------------------------------------------------------------------------------------------------------------------------------------:|
|
||||||
| custom | N/A | N/A |
|
| custom | N/A | N/A |
|
||||||
| activedirectory | (&(|({username_attribute}={input})({mail_attribute}={input}))(sAMAccountType=805306368)(!(userAccountControl:1.2.840.113556.1.4.803:=2))(!(pwdLastSet=0))(|(!(accountExpires=*))(accountExpires=0)(accountExpires>={date-time:microsoft-nt}))) | (&(member={dn})(|(sAMAccountType=268435456)(sAMAccountType=536870912))) |
|
| activedirectory | (&(|({username_attribute}={input})({mail_attribute}={input}))(sAMAccountType=805306368)(!(userAccountControl:1.2.840.113556.1.4.803:=2))(!(pwdLastSet=0))(|(!(accountExpires=*))(accountExpires=0)(accountExpires>={date-time:microsoft-nt}))) | (&(member={dn})(|(sAMAccountType=268435456)(sAMAccountType=536870912))) |
|
||||||
| freeipa | (&(|({username_attribute}={input})({mail_attribute}={input}))(objectClass=person)(!(nsAccountLock=TRUE))(krbPasswordExpiration>={date-time:generalized})(|(!(krbPrincipalExpiration=*))(krbPrincipalExpiration>={date-time:generalized}))) | (&(member={dn})(objectClass=groupOfNames)) |
|
| rfc2307bis | (&(|({username_attribute}={input})({mail_attribute}={input}))(|(objectClass=inetOrgPerson)(objectClass=organizationalPerson))) | (&(|(member={dn})(uniqueMember={dn}))(|(objectClass=groupOfNames)(objectClass=groupOfUniqueNames)(objectClass=groupOfMembers))) |
|
||||||
| lldap | (&(|({username_attribute}={input})({mail_attribute}={input}))(objectClass=person)) | (&(member={dn})(objectClass=groupOfNames)) |
|
| freeipa | (&(|({username_attribute}={input})({mail_attribute}={input}))(objectClass=person)(!(nsAccountLock=TRUE))(krbPasswordExpiration>={date-time:generalized})(|(!(krbPrincipalExpiration=*))(krbPrincipalExpiration>={date-time:generalized}))) | (&(member={dn})(objectClass=groupOfNames)) |
|
||||||
| glauth | (&(|({username_attribute}={input})({mail_attribute}={input}))(objectClass=posixAccount)(!(accountStatus=inactive))) | (&(uniqueMember={dn})(objectClass=posixGroup)) |
|
| lldap | (&(|({username_attribute}={input})({mail_attribute}={input}))(objectClass=person)) | (&(member={dn})(objectClass=groupOfNames)) |
|
||||||
|
| glauth | (&(|({username_attribute}={input})({mail_attribute}={input}))(objectClass=posixAccount)(!(accountStatus=inactive))) | (&(uniqueMember={dn})(objectClass=posixGroup)) |
|
||||||
|
|
||||||
##### Microsoft Active Directory sAMAccountType
|
##### Microsoft Active Directory sAMAccountType
|
||||||
|
|
||||||
|
|
|
@ -193,14 +193,14 @@ This table suggests the parameters for the [SHA2 Crypt] algorithm:
|
||||||
| Standard CPU | sha512 | 50000 | 16 |
|
| Standard CPU | sha512 | 50000 | 16 |
|
||||||
| High End CPU | sha512 | 150000 | 16 |
|
| High End CPU | sha512 | 150000 | 16 |
|
||||||
|
|
||||||
[Argon2]: https://www.rfc-editor.org/rfc/rfc9106.html
|
[Argon2]: https://datatracker.ietf.org/doc/html/rfc9106
|
||||||
[Scrypt]: https://en.wikipedia.org/wiki/Scrypt
|
[Scrypt]: https://en.wikipedia.org/wiki/Scrypt
|
||||||
[PBKDF2]: https://www.ietf.org/rfc/rfc2898.html
|
[PBKDF2]: https://datatracker.ietf.org/doc/html/rfc2898
|
||||||
[SHA2 Crypt]: https://www.akkadia.org/drepper/SHA-crypt.txt
|
[SHA2 Crypt]: https://www.akkadia.org/drepper/SHA-crypt.txt
|
||||||
[Bcrypt]: https://en.wikipedia.org/wiki/Bcrypt
|
[Bcrypt]: https://en.wikipedia.org/wiki/Bcrypt
|
||||||
[FIPS-140 compliance]: https://csrc.nist.gov/publications/detail/fips/140/2/final
|
[FIPS-140 compliance]: https://csrc.nist.gov/publications/detail/fips/140/2/final
|
||||||
|
|
||||||
[RFC9106 Parameter Choice]: https://www.rfc-editor.org/rfc/rfc9106.html#section-4
|
[RFC9106 Parameter Choice]: https://datatracker.ietf.org/doc/html/rfc9106#section-4
|
||||||
[YAML]: https://yaml.org/
|
[YAML]: https://yaml.org/
|
||||||
[crypt hash generate]: ../cli/authelia/authelia_crypto_hash_generate.md
|
[crypt hash generate]: ../cli/authelia/authelia_crypto_hash_generate.md
|
||||||
[Password Hashing Competition]: https://en.wikipedia.org/wiki/Password_Hashing_Competition
|
[Password Hashing Competition]: https://en.wikipedia.org/wiki/Password_Hashing_Competition
|
||||||
|
|
|
@ -46,7 +46,7 @@ utilize these overrides should either check for changes to the files in the
|
||||||
|
|
||||||
The locales directory holds folders of internationalization locales. This directory can be utilized to override these
|
The locales directory holds folders of internationalization locales. This directory can be utilized to override these
|
||||||
locales. They are the names of locales that are returned by the `navigator.langauge` ECMAScript command. These are
|
locales. They are the names of locales that are returned by the `navigator.langauge` ECMAScript command. These are
|
||||||
generally those in the [RFC5646 / BCP47 Format](https://www.rfc-editor.org/rfc/rfc5646.html) specifically the language
|
generally those in the [RFC5646 / BCP47 Format](https://datatracker.ietf.org/doc/html/rfc5646) specifically the language
|
||||||
codes from [Crowdin](https://support.crowdin.com/api/language-codes/).
|
codes from [Crowdin](https://support.crowdin.com/api/language-codes/).
|
||||||
|
|
||||||
Each directory has JSON files which you can explore the format of in the
|
Each directory has JSON files which you can explore the format of in the
|
||||||
|
|
|
@ -78,6 +78,9 @@ The following functions which mimic the behaviour of helm exist in most templati
|
||||||
- kindIs
|
- kindIs
|
||||||
- default
|
- default
|
||||||
- empty
|
- empty
|
||||||
|
- indent
|
||||||
|
- nindent
|
||||||
|
- uuidv4
|
||||||
|
|
||||||
See the [Helm Documentation](https://helm.sh/docs/chart_template_guide/function_list/) for more information. Please
|
See the [Helm Documentation](https://helm.sh/docs/chart_template_guide/function_list/) for more information. Please
|
||||||
note that only the functions listed above are supported and the functions don't necessarily behave exactly the same.
|
note that only the functions listed above are supported and the functions don't necessarily behave exactly the same.
|
||||||
|
@ -92,3 +95,7 @@ The following is a list of special functions and their syntax.
|
||||||
#### iterate
|
#### iterate
|
||||||
|
|
||||||
Input is a single uint. Returns a slice of uints from 0 to the provided uint.
|
Input is a single uint. Returns a slice of uints from 0 to the provided uint.
|
||||||
|
|
||||||
|
#### fileContent
|
||||||
|
|
||||||
|
Input is a path. Returns the content of a file.
|
||||||
|
|
|
@ -39,11 +39,11 @@ Feature List:
|
||||||
* [User Consent](https://openid.net/specs/openid-connect-core-1_0.html#Consent)
|
* [User Consent](https://openid.net/specs/openid-connect-core-1_0.html#Consent)
|
||||||
* [Authorization Code Flow](https://openid.net/specs/openid-connect-core-1_0.html#CodeFlowSteps)
|
* [Authorization Code Flow](https://openid.net/specs/openid-connect-core-1_0.html#CodeFlowSteps)
|
||||||
* [OpenID Connect Discovery](https://openid.net/specs/openid-connect-discovery-1_0.html)
|
* [OpenID Connect Discovery](https://openid.net/specs/openid-connect-discovery-1_0.html)
|
||||||
* [RS256 Signature Strategy](https://www.rfc-editor.org/rfc/rfc7518.html#section-3.1)
|
* [RS256 Signature Strategy](https://datatracker.ietf.org/doc/html/rfc7518#section-3.1)
|
||||||
* Per Client Scope/Grant Type/Response Type Restriction
|
* Per Client Scope/Grant Type/Response Type Restriction
|
||||||
* Per Client Authorization Policy (1FA/2FA)
|
* Per Client Authorization Policy (1FA/2FA)
|
||||||
* Per Client List of Valid Redirection URI's
|
* Per Client List of Valid Redirection URI's
|
||||||
* [Confidential Client Type](https://www.rfc-editor.org/rfc/rfc6749.html#section-2.1)
|
* [Confidential Client Type](https://datatracker.ietf.org/doc/html/rfc6749#section-2.1)
|
||||||
|
|
||||||
### Beta 2
|
### Beta 2
|
||||||
|
|
||||||
|
@ -56,7 +56,7 @@ Feature List:
|
||||||
* Token/Code Lifespan
|
* Token/Code Lifespan
|
||||||
* Client Debug Messages
|
* Client Debug Messages
|
||||||
* Client Audience
|
* Client Audience
|
||||||
* [Public Client Type](https://www.rfc-editor.org/rfc/rfc6749.html#section-2.1)
|
* [Public Client Type](https://datatracker.ietf.org/doc/html/rfc6749#section-2.1)
|
||||||
|
|
||||||
### Beta 3
|
### Beta 3
|
||||||
|
|
||||||
|
@ -97,7 +97,7 @@ Feature List:
|
||||||
|
|
||||||
Feature List:
|
Feature List:
|
||||||
|
|
||||||
* [JWK's backed by X509 Certificate Chains](https://www.rfc-editor.org/rfc/rfc7517#section-4.7)
|
* [JWK's backed by X509 Certificate Chains](https://datatracker.ietf.org/doc/html/rfc7517#section-4.7)
|
||||||
* Hashed Client Secrets
|
* Hashed Client Secrets
|
||||||
* Per-Client [Consent](https://openid.net/specs/openid-connect-core-1_0.html#Consent) Mode:
|
* Per-Client [Consent](https://openid.net/specs/openid-connect-core-1_0.html#Consent) Mode:
|
||||||
* Explicit:
|
* Explicit:
|
||||||
|
@ -115,7 +115,7 @@ Feature List:
|
||||||
|
|
||||||
{{< roadmap-status stage="in-progress" version="v4.38.0" >}}
|
{{< roadmap-status stage="in-progress" version="v4.38.0" >}}
|
||||||
|
|
||||||
* [OAuth 2.0 Pushed Authorization Requests](https://www.rfc-editor.org/rfc/rfc9126.html)
|
* [OAuth 2.0 Pushed Authorization Requests](https://datatracker.ietf.org/doc/html/rfc9126)
|
||||||
* Per-Client [Proof Key Code Exchange (PKCE)] Policy
|
* Per-Client [Proof Key Code Exchange (PKCE)] Policy
|
||||||
|
|
||||||
### Beta 7
|
### Beta 7
|
||||||
|
@ -177,7 +177,7 @@ Should be implemented alongside [Dynamic Client Registration](#openid-connect-dy
|
||||||
|
|
||||||
{{< roadmap-status stage="complete" version="v4.34.0" >}}
|
{{< roadmap-status stage="complete" version="v4.34.0" >}}
|
||||||
|
|
||||||
See the [IETF Specification RFC8414](https://www.rfc-editor.org/rfc/rfc8414.html) for more information.
|
See the [IETF Specification RFC8414](https://datatracker.ietf.org/doc/html/rfc8414) for more information.
|
||||||
|
|
||||||
#### OpenID Connect Session Management
|
#### OpenID Connect Session Management
|
||||||
|
|
||||||
|
@ -205,9 +205,9 @@ The `preferred_username` claim was missing and was fixed.
|
||||||
|
|
||||||
[Cross Origin Resource Sharing]: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
|
[Cross Origin Resource Sharing]: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
|
||||||
|
|
||||||
[RFC8176]: https://www.rfc-editor.org/rfc/rfc8176.html
|
[RFC8176]: https://datatracker.ietf.org/doc/html/rfc8176
|
||||||
[RFC8693 Section 4.3]: https://www.rfc-editor.org/rfc/rfc8693.html/#section-4.3
|
[RFC8693 Section 4.3]: https://datatracker.ietf.org/doc/html/rfc8693/#section-4.3
|
||||||
[RFC4122]: https://www.rfc-editor.org/rfc/rfc4122.html
|
[RFC4122]: https://datatracker.ietf.org/doc/html/rfc4122
|
||||||
|
|
||||||
[OpenID Connect]: https://openid.net/connect/
|
[OpenID Connect]: https://openid.net/connect/
|
||||||
[OpenID Connect Front-Channel Logout]: https://openid.net/specs/openid-connect-frontchannel-1_0.html
|
[OpenID Connect Front-Channel Logout]: https://openid.net/specs/openid-connect-frontchannel-1_0.html
|
||||||
|
@ -219,4 +219,4 @@ The `preferred_username` claim was missing and was fixed.
|
||||||
[OpenID Connect Core (Subject Identifier Types)]: https://openid.net/specs/openid-connect-core-1_0.html#SubjectIDTypes
|
[OpenID Connect Core (Subject Identifier Types)]: https://openid.net/specs/openid-connect-core-1_0.html#SubjectIDTypes
|
||||||
[OpenID Connect Core (Pairwise Identifier Algorithm)]: https://openid.net/specs/openid-connect-core-1_0.html#PairwiseAlg
|
[OpenID Connect Core (Pairwise Identifier Algorithm)]: https://openid.net/specs/openid-connect-core-1_0.html#PairwiseAlg
|
||||||
[OpenID Connect Core (Mandatory to Implement Features for All OpenID Providers)]: https://openid.net/specs/openid-connect-core-1_0.html#ServerMTI
|
[OpenID Connect Core (Mandatory to Implement Features for All OpenID Providers)]: https://openid.net/specs/openid-connect-core-1_0.html#ServerMTI
|
||||||
[Proof Key Code Exchange (PKCE)]: https://www.rfc-editor.org/rfc/rfc7636.html
|
[Proof Key Code Exchange (PKCE)]: https://datatracker.ietf.org/doc/html/rfc7636
|
||||||
|
|
|
@ -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]
|
[build.environment]
|
||||||
NODE_VERSION = "16.18.1"
|
NODE_VERSION = "16.18.1"
|
||||||
NPM_VERSION = "8.19.2"
|
NPM_VERSION = "8.19.2"
|
||||||
GO_VERSION = "1.19.4"
|
GO_VERSION = "1.19.5"
|
||||||
|
|
||||||
[context.production]
|
[context.production]
|
||||||
command = "pnpm run build"
|
command = "pnpm run build"
|
||||||
|
|
20
go.mod
20
go.mod
|
@ -1,19 +1,19 @@
|
||||||
module github.com/authelia/authelia/v4
|
module github.com/authelia/authelia/v4
|
||||||
|
|
||||||
go 1.19
|
go 1.20
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/Gurpartap/logrus-stack v0.0.0-20170710170904-89c00d8a28f4
|
github.com/Gurpartap/logrus-stack v0.0.0-20170710170904-89c00d8a28f4
|
||||||
github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d
|
github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d
|
||||||
github.com/deckarep/golang-set/v2 v2.1.0
|
github.com/deckarep/golang-set/v2 v2.1.0
|
||||||
github.com/duosecurity/duo_api_golang v0.0.0-20221117185402-091daa09e19d
|
github.com/duosecurity/duo_api_golang v0.0.0-20230203160531-b221c950c2b0
|
||||||
github.com/fasthttp/router v1.4.16
|
github.com/fasthttp/router v1.4.16
|
||||||
github.com/fasthttp/session/v2 v2.4.16
|
github.com/fasthttp/session/v2 v2.4.16
|
||||||
github.com/fsnotify/fsnotify v1.6.0
|
github.com/fsnotify/fsnotify v1.6.0
|
||||||
github.com/go-asn1-ber/asn1-ber v1.5.4
|
github.com/go-asn1-ber/asn1-ber v1.5.4
|
||||||
github.com/go-crypt/crypt v0.2.3
|
github.com/go-crypt/crypt v0.2.5
|
||||||
github.com/go-ldap/ldap/v3 v3.4.4
|
github.com/go-ldap/ldap/v3 v3.4.4
|
||||||
github.com/go-rod/rod v0.112.4
|
github.com/go-rod/rod v0.112.5
|
||||||
github.com/go-sql-driver/mysql v1.7.0
|
github.com/go-sql-driver/mysql v1.7.0
|
||||||
github.com/go-webauthn/webauthn v0.7.0
|
github.com/go-webauthn/webauthn v0.7.0
|
||||||
github.com/golang-jwt/jwt/v4 v4.4.3
|
github.com/golang-jwt/jwt/v4 v4.4.3
|
||||||
|
@ -28,7 +28,7 @@ require (
|
||||||
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826
|
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826
|
||||||
github.com/ory/fosite v0.44.0
|
github.com/ory/fosite v0.44.0
|
||||||
github.com/ory/herodot v0.9.13
|
github.com/ory/herodot v0.9.13
|
||||||
github.com/ory/x v0.0.534
|
github.com/ory/x v0.0.535
|
||||||
github.com/otiai10/copy v1.9.0
|
github.com/otiai10/copy v1.9.0
|
||||||
github.com/pkg/errors v0.9.1
|
github.com/pkg/errors v0.9.1
|
||||||
github.com/pquerna/otp v1.4.0
|
github.com/pquerna/otp v1.4.0
|
||||||
|
@ -40,9 +40,10 @@ require (
|
||||||
github.com/trustelem/zxcvbn v1.0.1
|
github.com/trustelem/zxcvbn v1.0.1
|
||||||
github.com/valyala/fasthttp v1.44.0
|
github.com/valyala/fasthttp v1.44.0
|
||||||
github.com/wneessen/go-mail v0.3.8
|
github.com/wneessen/go-mail v0.3.8
|
||||||
|
golang.org/x/net v0.6.0
|
||||||
golang.org/x/sync v0.1.0
|
golang.org/x/sync v0.1.0
|
||||||
golang.org/x/term v0.4.0
|
golang.org/x/term v0.5.0
|
||||||
golang.org/x/text v0.6.0
|
golang.org/x/text v0.7.0
|
||||||
gopkg.in/square/go-jose.v2 v2.6.0
|
gopkg.in/square/go-jose.v2 v2.6.0
|
||||||
gopkg.in/yaml.v3 v3.0.1
|
gopkg.in/yaml.v3 v3.0.1
|
||||||
)
|
)
|
||||||
|
@ -64,7 +65,7 @@ require (
|
||||||
github.com/ecordell/optgen v0.0.6 // indirect
|
github.com/ecordell/optgen v0.0.6 // indirect
|
||||||
github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 // indirect
|
github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 // indirect
|
||||||
github.com/fxamacker/cbor/v2 v2.4.0 // indirect
|
github.com/fxamacker/cbor/v2 v2.4.0 // indirect
|
||||||
github.com/go-crypt/x v0.1.10 // indirect
|
github.com/go-crypt/x v0.1.12 // indirect
|
||||||
github.com/go-redis/redis/v8 v8.11.5 // indirect
|
github.com/go-redis/redis/v8 v8.11.5 // indirect
|
||||||
github.com/go-webauthn/revoke v0.1.6 // indirect
|
github.com/go-webauthn/revoke v0.1.6 // indirect
|
||||||
github.com/golang/glog v1.0.0 // indirect
|
github.com/golang/glog v1.0.0 // indirect
|
||||||
|
@ -109,9 +110,8 @@ require (
|
||||||
github.com/ysmood/leakless v0.8.0 // indirect
|
github.com/ysmood/leakless v0.8.0 // indirect
|
||||||
golang.org/x/crypto v0.5.0 // indirect
|
golang.org/x/crypto v0.5.0 // indirect
|
||||||
golang.org/x/mod v0.7.0 // indirect
|
golang.org/x/mod v0.7.0 // indirect
|
||||||
golang.org/x/net v0.5.0 // indirect
|
|
||||||
golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783 // indirect
|
golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783 // indirect
|
||||||
golang.org/x/sys v0.4.0 // indirect
|
golang.org/x/sys v0.5.0 // indirect
|
||||||
golang.org/x/tools v0.4.0 // indirect
|
golang.org/x/tools v0.4.0 // indirect
|
||||||
google.golang.org/appengine v1.6.7 // indirect
|
google.golang.org/appengine v1.6.7 // indirect
|
||||||
google.golang.org/genproto v0.0.0-20221025140454-527a21cfbd71 // indirect
|
google.golang.org/genproto v0.0.0-20221025140454-527a21cfbd71 // indirect
|
||||||
|
|
36
go.sum
36
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/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
||||||
github.com/dlclark/regexp2 v1.4.0 h1:F1rxgk7p4uKjwIQxBs9oAXe5CqrXlCduYEJvrF4u93E=
|
github.com/dlclark/regexp2 v1.4.0 h1:F1rxgk7p4uKjwIQxBs9oAXe5CqrXlCduYEJvrF4u93E=
|
||||||
github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
|
github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
|
||||||
github.com/duosecurity/duo_api_golang v0.0.0-20221117185402-091daa09e19d h1:DdF2JKufY7l8IBJuGeanPFR5gVpWJfEh1LWJFM/zDas=
|
github.com/duosecurity/duo_api_golang v0.0.0-20230203160531-b221c950c2b0 h1:+0VqbFomxHYZLIsuLJ7FjAdjhJTQ4P3/o6paTMx5kAY=
|
||||||
github.com/duosecurity/duo_api_golang v0.0.0-20221117185402-091daa09e19d/go.mod h1:jI+QUTOK3wqIOrUl0Cwnwlgc/P6vs6pZOuQY3aKggwg=
|
github.com/duosecurity/duo_api_golang v0.0.0-20230203160531-b221c950c2b0/go.mod h1:jI+QUTOK3wqIOrUl0Cwnwlgc/P6vs6pZOuQY3aKggwg=
|
||||||
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
|
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
|
||||||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||||
github.com/ecordell/optgen v0.0.6 h1:aSknPe6ZUBrjwHGp2+6XfmfCGYGD6W0ZDfCmmsrS7s4=
|
github.com/ecordell/optgen v0.0.6 h1:aSknPe6ZUBrjwHGp2+6XfmfCGYGD6W0ZDfCmmsrS7s4=
|
||||||
|
@ -162,10 +162,10 @@ github.com/fxamacker/cbor/v2 v2.4.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrt
|
||||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||||
github.com/go-asn1-ber/asn1-ber v1.5.4 h1:vXT6d/FNDiELJnLb6hGNa309LMsrCoYFvpwHDF0+Y1A=
|
github.com/go-asn1-ber/asn1-ber v1.5.4 h1:vXT6d/FNDiELJnLb6hGNa309LMsrCoYFvpwHDF0+Y1A=
|
||||||
github.com/go-asn1-ber/asn1-ber v1.5.4/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
|
github.com/go-asn1-ber/asn1-ber v1.5.4/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
|
||||||
github.com/go-crypt/crypt v0.2.3 h1:g9OPe39VmqonsTXP/zo4byEoxrxAAUG+DzBvjzGWvuw=
|
github.com/go-crypt/crypt v0.2.5 h1:QYGV/OkamPz69fME+JbD0wVmPnAL3C1Ooypqb1FHnHk=
|
||||||
github.com/go-crypt/crypt v0.2.3/go.mod h1:mbhOIjybuVuh0Vxveb//7UbGV8OCugJC7UPzqs1awYw=
|
github.com/go-crypt/crypt v0.2.5/go.mod h1:VtajXhpCQlYwf4ekvp1I/6bSFi1YKobq0QInA1AFCQQ=
|
||||||
github.com/go-crypt/x v0.1.10 h1:HN8oQGrWcg5xPtIIGwPDWs9MvdYEUJrP7JeNkC46dvM=
|
github.com/go-crypt/x v0.1.12 h1:UQvK75MBYGdeY7PdP/YbkUqiGxNzJq3BlO/lTVT6yuU=
|
||||||
github.com/go-crypt/x v0.1.10/go.mod h1:OI04rm/Ojti3mrUFZAJnx66nFbnZ0CVPF7qG49mBZgI=
|
github.com/go-crypt/x v0.1.12/go.mod h1:037K8Cyl2IJUzO297LjhDIeYZYxg7K8yzbCco6ZNtV0=
|
||||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||||
|
@ -182,8 +182,8 @@ github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG
|
||||||
github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
|
github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
|
||||||
github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI=
|
github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI=
|
||||||
github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo=
|
github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo=
|
||||||
github.com/go-rod/rod v0.112.4 h1:Ck002nM6rCORdVFtD778WxiadS5oJsmqytjXTG5bqiQ=
|
github.com/go-rod/rod v0.112.5 h1:2mH97UK8We4D2MfX388WqPjG1lDbxx8lLi5MzfvnEo0=
|
||||||
github.com/go-rod/rod v0.112.4/go.mod h1:ElViL9ABbcshNQw93+11FrYRH92RRhMKleuILo6+5V0=
|
github.com/go-rod/rod v0.112.5/go.mod h1:ElViL9ABbcshNQw93+11FrYRH92RRhMKleuILo6+5V0=
|
||||||
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||||
github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc=
|
github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc=
|
||||||
github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
|
github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
|
||||||
|
@ -459,8 +459,8 @@ github.com/ory/go-convenience v0.1.0/go.mod h1:uEY/a60PL5c12nYz4V5cHY03IBmwIAEm8
|
||||||
github.com/ory/herodot v0.9.13 h1:cN/Z4eOkErl/9W7hDIDLb79IO/bfsH+8yscBjRpB4IU=
|
github.com/ory/herodot v0.9.13 h1:cN/Z4eOkErl/9W7hDIDLb79IO/bfsH+8yscBjRpB4IU=
|
||||||
github.com/ory/herodot v0.9.13/go.mod h1:IWDs9kSvFQqw/cQ8zi5ksyYvITiUU4dI7glUrhZcJYo=
|
github.com/ory/herodot v0.9.13/go.mod h1:IWDs9kSvFQqw/cQ8zi5ksyYvITiUU4dI7glUrhZcJYo=
|
||||||
github.com/ory/viper v1.7.5/go.mod h1:ypOuyJmEUb3oENywQZRgeAMwqgOyDqwboO1tj3DjTaM=
|
github.com/ory/viper v1.7.5/go.mod h1:ypOuyJmEUb3oENywQZRgeAMwqgOyDqwboO1tj3DjTaM=
|
||||||
github.com/ory/x v0.0.534 h1:hc49pmcOuHdJ6rbHVGtJJ4/LU88dzDCtEQKfgeo/ecU=
|
github.com/ory/x v0.0.535 h1:muhBRYkAz52J00yEGw6LtwJDF5HhyxM2w0E0V4w5z+o=
|
||||||
github.com/ory/x v0.0.534/go.mod h1:CQopDsCC9t0tQsddE9UlyRFVEFd2xjKBVcw4nLMMMS0=
|
github.com/ory/x v0.0.535/go.mod h1:CQopDsCC9t0tQsddE9UlyRFVEFd2xjKBVcw4nLMMMS0=
|
||||||
github.com/otiai10/copy v1.9.0 h1:7KFNiCgZ91Ru4qW4CWPf/7jqtxLagGRmIxWldPP9VY4=
|
github.com/otiai10/copy v1.9.0 h1:7KFNiCgZ91Ru4qW4CWPf/7jqtxLagGRmIxWldPP9VY4=
|
||||||
github.com/otiai10/copy v1.9.0/go.mod h1:hsfX19wcn0UWIHUQ3/4fHuehhk2UyArQ9dVFAn3FczI=
|
github.com/otiai10/copy v1.9.0/go.mod h1:hsfX19wcn0UWIHUQ3/4fHuehhk2UyArQ9dVFAn3FczI=
|
||||||
github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE=
|
github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE=
|
||||||
|
@ -749,8 +749,8 @@ golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su
|
||||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
golang.org/x/net v0.0.0-20220906165146-f3363e06e74c/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
|
golang.org/x/net v0.0.0-20220906165146-f3363e06e74c/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
|
||||||
golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
|
golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
|
||||||
golang.org/x/net v0.5.0 h1:GyT4nK/YDHSqa1c4753ouYCDajOYKTja9Xb/OHtgvSw=
|
golang.org/x/net v0.6.0 h1:L4ZwwTvKW9gr0ZMS1yrHD9GZhIuVjOBBnaKH+SPQK0Q=
|
||||||
golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws=
|
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
|
@ -854,13 +854,13 @@ golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||||
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18=
|
golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU=
|
||||||
golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA=
|
golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA=
|
||||||
golang.org/x/term v0.4.0 h1:O7UWfv5+A2qiuulQk30kVinPoMtoIPeVaKLEgLpVkvg=
|
golang.org/x/term v0.5.0 h1:n2a8QNdAb0sZNpU9R1ALUXBbY+w51fCQDN+7EdxNBsY=
|
||||||
golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ=
|
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
@ -872,8 +872,8 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
golang.org/x/text v0.6.0 h1:3XmdazWV+ubf7QgHSTWeykHOci5oeekaGJBLkrkaw4k=
|
golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo=
|
||||||
golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
|
|
|
@ -533,21 +533,19 @@ const (
|
||||||
storageMigrateDirectionDown = "down"
|
storageMigrateDirectionDown = "down"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
|
||||||
timeLayoutCertificateNotBefore = "Jan 2 15:04:05 2006"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
cmdFlagNameDirectory = "directory"
|
cmdFlagNameDirectory = "directory"
|
||||||
|
|
||||||
cmdFlagNamePathCA = "path.ca"
|
cmdFlagNamePathCA = "path.ca"
|
||||||
|
cmdFlagNameBundle = "bundle"
|
||||||
|
|
||||||
cmdFlagNameFilePrivateKey = "file.private-key"
|
cmdFlagNameFilePrivateKey = "file.private-key"
|
||||||
cmdFlagNameFilePublicKey = "file.public-key"
|
cmdFlagNameFilePublicKey = "file.public-key"
|
||||||
cmdFlagNameFileCertificate = "file.certificate"
|
cmdFlagNameFileCertificate = "file.certificate"
|
||||||
cmdFlagNameFileCAPrivateKey = "file.ca-private-key"
|
cmdFlagNameFileCertificateBundle = "file.certificate-bundle"
|
||||||
cmdFlagNameFileCACertificate = "file.ca-certificate"
|
cmdFlagNameFileCAPrivateKey = "file.ca-private-key"
|
||||||
cmdFlagNameFileCSR = "file.csr"
|
cmdFlagNameFileCACertificate = "file.ca-certificate"
|
||||||
|
cmdFlagNameFileCSR = "file.csr"
|
||||||
|
|
||||||
cmdFlagNameExtendedUsage = "extended-usage"
|
cmdFlagNameExtendedUsage = "extended-usage"
|
||||||
cmdFlagNameSignature = "signature"
|
cmdFlagNameSignature = "signature"
|
||||||
|
@ -564,6 +562,7 @@ const (
|
||||||
cmdFlagNamePostcode = "postcode"
|
cmdFlagNamePostcode = "postcode"
|
||||||
|
|
||||||
cmdFlagNameNotBefore = "not-before"
|
cmdFlagNameNotBefore = "not-before"
|
||||||
|
cmdFlagNameNotAfter = "not-after"
|
||||||
cmdFlagNameDuration = "duration"
|
cmdFlagNameDuration = "duration"
|
||||||
|
|
||||||
cmdFlagNamePKCS8 = "pkcs8"
|
cmdFlagNamePKCS8 = "pkcs8"
|
||||||
|
@ -749,4 +748,27 @@ Secrets:
|
||||||
way: 'key', 'secret', 'password', 'token'.
|
way: 'key', 'secret', 'password', 'token'.
|
||||||
|
|
||||||
The available options and the specific secret mapping can be found here: https://www.authelia.com/configuration/methods/secrets/`
|
The available options and the specific secret mapping can be found here: https://www.authelia.com/configuration/methods/secrets/`
|
||||||
|
|
||||||
|
helpTopicTimeLayouts = `Several commands take date time inputs which are parsed. These inputs are parsed with
|
||||||
|
specific layouts in mind and these layouts are handled in order.
|
||||||
|
|
||||||
|
Format:
|
||||||
|
|
||||||
|
The layouts use a format where specific sequence of characters are representative of a portion of each timestamp.
|
||||||
|
|
||||||
|
See the go documentation for more information on how these layouts work, however the layouts are fairly self
|
||||||
|
explanatory and you can just use standard unix timestamps if desired.
|
||||||
|
|
||||||
|
Layouts:
|
||||||
|
|
||||||
|
Unix (µs): 1675899060000000
|
||||||
|
Unix (ms): 1675899060000
|
||||||
|
Unix (s): 1675899060
|
||||||
|
Simple: Jan 2 15:04:05 2006
|
||||||
|
Date Time: 2006-01-02 15:04:05
|
||||||
|
RFC3339: 2006-01-02T15:04:05Z07:00
|
||||||
|
RFC1123 with numeric timezone: Mon, 02 Jan 2006 15:04:05 -0700
|
||||||
|
Ruby Date: Mon Jan 02 15:04:05 -0700 2006
|
||||||
|
ANSIC: Mon Jan _2 15:04:05 2006
|
||||||
|
Date: 2006-01-02`
|
||||||
)
|
)
|
||||||
|
|
|
@ -313,7 +313,7 @@ func (ctx *CmdCtx) CryptoCertificateRequestRunE(cmd *cobra.Command, _ []string)
|
||||||
|
|
||||||
b.WriteString(fmt.Sprintf("\n\tSubject Alternative Names: %s\n\n", strings.Join(cryptoSANsToString(template.DNSNames, template.IPAddresses), ", ")))
|
b.WriteString(fmt.Sprintf("\n\tSubject Alternative Names: %s\n\n", strings.Join(cryptoSANsToString(template.DNSNames, template.IPAddresses), ", ")))
|
||||||
|
|
||||||
if privateKeyPath, csrPath, err = cryptoGetWritePathsFromCmd(cmd); err != nil {
|
if _, privateKeyPath, csrPath, err = cryptoGetWritePathsFromCmd(cmd); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -329,15 +329,11 @@ func (ctx *CmdCtx) CryptoCertificateRequestRunE(cmd *cobra.Command, _ []string)
|
||||||
return fmt.Errorf("failed to create certificate request: %w", err)
|
return fmt.Errorf("failed to create certificate request: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if privateKeyPath, csrPath, err = cryptoGetWritePathsFromCmd(cmd); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = utils.WriteKeyToPEM(privateKey, privateKeyPath, false); err != nil {
|
if err = utils.WriteKeyToPEM(privateKey, privateKeyPath, false); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = utils.WriteCertificateBytesToPEM(csr, csrPath, true); err != nil {
|
if err = utils.WriteCertificateBytesToPEM(csrPath, true, csr); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -406,21 +402,23 @@ func (ctx *CmdCtx) CryptoCertificateGenerateRunE(cmd *cobra.Command, _ []string,
|
||||||
b.WriteString(fmt.Sprintf("\n\tSubject Alternative Names: %s\n\n", strings.Join(cryptoSANsToString(template.DNSNames, template.IPAddresses), ", ")))
|
b.WriteString(fmt.Sprintf("\n\tSubject Alternative Names: %s\n\n", strings.Join(cryptoSANsToString(template.DNSNames, template.IPAddresses), ", ")))
|
||||||
|
|
||||||
var (
|
var (
|
||||||
privateKeyPath, certificatePath string
|
dir, privateKeyPath, certificatePath, certificateBundlePath string
|
||||||
certificate []byte
|
|
||||||
|
bundle bool
|
||||||
|
certificate []byte
|
||||||
)
|
)
|
||||||
|
|
||||||
if privateKeyPath, certificatePath, err = cryptoGetWritePathsFromCmd(cmd); err != nil {
|
if dir, privateKeyPath, certificatePath, err = cryptoGetWritePathsFromCmd(cmd); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if bundle, certificateBundlePath, err = cryptoGetCertificateBundleFromCmd(cmd, dir, caCertificate); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
b.WriteString("Output Paths:\n")
|
b.WriteString("Output Paths:\n")
|
||||||
b.WriteString(fmt.Sprintf("\tPrivate Key: %s\n", privateKeyPath))
|
b.WriteString(fmt.Sprintf("\tPrivate Key: %s\n", privateKeyPath))
|
||||||
b.WriteString(fmt.Sprintf("\tCertificate: %s\n\n", certificatePath))
|
b.WriteString(fmt.Sprintf("\tCertificate: %s\n", certificatePath))
|
||||||
|
|
||||||
fmt.Print(b.String())
|
|
||||||
|
|
||||||
b.Reset()
|
|
||||||
|
|
||||||
if certificate, err = x509.CreateCertificate(ctx.providers.Random, template, parent, publicKey, signatureKey); err != nil {
|
if certificate, err = x509.CreateCertificate(ctx.providers.Random, template, parent, publicKey, signatureKey); err != nil {
|
||||||
return fmt.Errorf("failed to create certificate: %w", err)
|
return fmt.Errorf("failed to create certificate: %w", err)
|
||||||
|
@ -430,10 +428,24 @@ func (ctx *CmdCtx) CryptoCertificateGenerateRunE(cmd *cobra.Command, _ []string,
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = utils.WriteCertificateBytesToPEM(certificate, certificatePath, false); err != nil {
|
if err = utils.WriteCertificateBytesToPEM(certificatePath, false, certificate); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if bundle {
|
||||||
|
b.WriteString(fmt.Sprintf("\tCertificate (bundle): %s\n", certificateBundlePath))
|
||||||
|
|
||||||
|
if err = utils.WriteCertificateBytesToPEM(certificateBundlePath, false, certificate, caCertificate.Raw); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
b.WriteString("\n")
|
||||||
|
|
||||||
|
fmt.Print(b.String())
|
||||||
|
|
||||||
|
b.Reset()
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -448,7 +460,7 @@ func (ctx *CmdCtx) CryptoPairGenerateRunE(cmd *cobra.Command, _ []string, privat
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if privateKeyPath, publicKeyPath, err = cryptoGetWritePathsFromCmd(cmd); err != nil {
|
if _, privateKeyPath, publicKeyPath, err = cryptoGetWritePathsFromCmd(cmd); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,8 +32,9 @@ func cmdFlagsCryptoCertificateCommon(cmd *cobra.Command) {
|
||||||
cmd.Flags().StringSliceP(cmdFlagNameStreetAddress, "s", nil, "certificate street address")
|
cmd.Flags().StringSliceP(cmdFlagNameStreetAddress, "s", nil, "certificate street address")
|
||||||
cmd.Flags().StringSliceP(cmdFlagNamePostcode, "p", nil, "certificate postcode")
|
cmd.Flags().StringSliceP(cmdFlagNamePostcode, "p", nil, "certificate postcode")
|
||||||
|
|
||||||
cmd.Flags().String(cmdFlagNameNotBefore, "", fmt.Sprintf("earliest date and time the certificate is considered valid formatted as %s (default is now)", timeLayoutCertificateNotBefore))
|
cmd.Flags().String(cmdFlagNameNotBefore, "", "earliest date and time the certificate is considered valid in various formats (default is now)")
|
||||||
cmd.Flags().Duration(cmdFlagNameDuration, 365*24*time.Hour, "duration of time the certificate is valid for")
|
cmd.Flags().String(cmdFlagNameNotAfter, "", "latest date and time the certificate is considered valid in various formats")
|
||||||
|
cmd.Flags().String(cmdFlagNameDuration, "1y", "duration of time the certificate is valid for")
|
||||||
cmd.Flags().StringSlice(cmdFlagNameSANs, nil, "subject alternative names")
|
cmd.Flags().StringSlice(cmdFlagNameSANs, nil, "subject alternative names")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,6 +43,8 @@ func cmdFlagsCryptoCertificateGenerate(cmd *cobra.Command) {
|
||||||
cmd.Flags().String(cmdFlagNameFileCAPrivateKey, "ca.private.pem", "certificate authority private key to use to signing this certificate")
|
cmd.Flags().String(cmdFlagNameFileCAPrivateKey, "ca.private.pem", "certificate authority private key to use to signing this certificate")
|
||||||
cmd.Flags().String(cmdFlagNameFileCACertificate, "ca.public.crt", "certificate authority certificate to use when signing this certificate")
|
cmd.Flags().String(cmdFlagNameFileCACertificate, "ca.public.crt", "certificate authority certificate to use when signing this certificate")
|
||||||
cmd.Flags().String(cmdFlagNameFileCertificate, "public.crt", "name of the file to export the certificate data to")
|
cmd.Flags().String(cmdFlagNameFileCertificate, "public.crt", "name of the file to export the certificate data to")
|
||||||
|
cmd.Flags().String(cmdFlagNameFileCertificateBundle, "public.bundle.crt", fmt.Sprintf("name of the file to export the certificate bundle data to when the --%s flag is set", cmdFlagNameBundle))
|
||||||
|
cmd.Flags().Bool(cmdFlagNameBundle, false, fmt.Sprintf("enables generating the certificate bundle if the --%s flag is set", cmdFlagNamePathCA))
|
||||||
|
|
||||||
cmd.Flags().StringSlice(cmdFlagNameExtendedUsage, nil, "specify the extended usage types of the certificate")
|
cmd.Flags().StringSlice(cmdFlagNameExtendedUsage, nil, "specify the extended usage types of the certificate")
|
||||||
|
|
||||||
|
@ -91,17 +94,15 @@ func cryptoSANsToString(dnsSANs []string, ipSANs []net.IP) (sans []string) {
|
||||||
return sans
|
return sans
|
||||||
}
|
}
|
||||||
|
|
||||||
func cryptoGetWritePathsFromCmd(cmd *cobra.Command) (privateKey, publicKey string, err error) {
|
func cryptoGetWritePathsFromCmd(cmd *cobra.Command) (dir, privateKey, publicKey string, err error) {
|
||||||
var dir string
|
|
||||||
|
|
||||||
if dir, err = cmd.Flags().GetString(cmdFlagNameDirectory); err != nil {
|
if dir, err = cmd.Flags().GetString(cmdFlagNameDirectory); err != nil {
|
||||||
return "", "", err
|
return "", "", "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
ca, _ := cmd.Flags().GetBool(cmdFlagNameCA)
|
ca, _ := cmd.Flags().GetBool(cmdFlagNameCA)
|
||||||
csr := cmd.Use == cmdUseRequest
|
csr := cmd.Use == cmdUseRequest
|
||||||
|
|
||||||
var private, public string
|
var pathPrivate, pathPublic string
|
||||||
|
|
||||||
var flagPrivate, flagPublic string
|
var flagPrivate, flagPublic string
|
||||||
|
|
||||||
|
@ -118,15 +119,15 @@ func cryptoGetWritePathsFromCmd(cmd *cobra.Command) (privateKey, publicKey strin
|
||||||
flagPrivate, flagPublic = cmdFlagNameFilePrivateKey, cmdFlagNameFileCertificate
|
flagPrivate, flagPublic = cmdFlagNameFilePrivateKey, cmdFlagNameFileCertificate
|
||||||
}
|
}
|
||||||
|
|
||||||
if private, err = cmd.Flags().GetString(flagPrivate); err != nil {
|
if pathPrivate, err = cmd.Flags().GetString(flagPrivate); err != nil {
|
||||||
return "", "", err
|
return "", "", "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
if public, err = cmd.Flags().GetString(flagPublic); err != nil {
|
if pathPublic, err = cmd.Flags().GetString(flagPublic); err != nil {
|
||||||
return "", "", err
|
return "", "", "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
return filepath.Join(dir, private), filepath.Join(dir, public), nil
|
return dir, filepath.Join(dir, pathPrivate), filepath.Join(dir, pathPublic), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ctx *CmdCtx) cryptoGenPrivateKeyFromCmd(cmd *cobra.Command) (privateKey any, err error) {
|
func (ctx *CmdCtx) cryptoGenPrivateKeyFromCmd(cmd *cobra.Command) (privateKey any, err error) {
|
||||||
|
@ -169,6 +170,28 @@ func (ctx *CmdCtx) cryptoGenPrivateKeyFromCmd(cmd *cobra.Command) (privateKey an
|
||||||
return privateKey, nil
|
return privateKey, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func cryptoGetCertificateBundleFromCmd(cmd *cobra.Command, dir string, caCertificate *x509.Certificate) (bundle bool, bundlePath string, err error) {
|
||||||
|
if bundle, err = cmd.Flags().GetBool(cmdFlagNameBundle); err != nil {
|
||||||
|
return false, "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
if !bundle {
|
||||||
|
return bundle, bundlePath, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if caCertificate == nil {
|
||||||
|
return false, "", fmt.Errorf("the --%s flag can't be used with self-signed certificates, you can specify the authority path using the --%s flag", cmdFlagNameBundle, cmdFlagNamePathCA)
|
||||||
|
}
|
||||||
|
|
||||||
|
if bundlePath, err = cmd.Flags().GetString(cmdFlagNameFileCertificateBundle); err != nil {
|
||||||
|
return false, "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
bundlePath = filepath.Join(dir, bundlePath)
|
||||||
|
|
||||||
|
return bundle, bundlePath, err
|
||||||
|
}
|
||||||
|
|
||||||
func cryptoGetCAFromCmd(cmd *cobra.Command) (privateKey any, cert *x509.Certificate, err error) {
|
func cryptoGetCAFromCmd(cmd *cobra.Command) (privateKey any, cert *x509.Certificate, err error) {
|
||||||
if !cmd.Flags().Changed(cmdFlagNamePathCA) {
|
if !cmd.Flags().Changed(cmdFlagNamePathCA) {
|
||||||
return nil, nil, nil
|
return nil, nil, nil
|
||||||
|
@ -337,10 +360,10 @@ func cryptoGetSubjectFromCmd(cmd *cobra.Command) (subject *pkix.Name, err error)
|
||||||
|
|
||||||
func (ctx *CmdCtx) cryptoGetCertificateFromCmd(cmd *cobra.Command) (certificate *x509.Certificate, err error) {
|
func (ctx *CmdCtx) cryptoGetCertificateFromCmd(cmd *cobra.Command) (certificate *x509.Certificate, err error) {
|
||||||
var (
|
var (
|
||||||
ca bool
|
ca bool
|
||||||
subject *pkix.Name
|
subject *pkix.Name
|
||||||
notBeforeStr string
|
|
||||||
duration time.Duration
|
notBefore, notAfter time.Time
|
||||||
)
|
)
|
||||||
|
|
||||||
if ca, err = cmd.Flags().GetBool(cmdFlagNameCA); err != nil {
|
if ca, err = cmd.Flags().GetBool(cmdFlagNameCA); err != nil {
|
||||||
|
@ -351,30 +374,16 @@ func (ctx *CmdCtx) cryptoGetCertificateFromCmd(cmd *cobra.Command) (certificate
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if notBeforeStr, err = cmd.Flags().GetString(cmdFlagNameNotBefore); err != nil {
|
if notBefore, notAfter, err = cryptoCertificateValidityFromCmd(cmd); err != nil {
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if duration, err = cmd.Flags().GetDuration(cmdFlagNameDuration); err != nil {
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
notBefore time.Time
|
|
||||||
serialNumber *big.Int
|
serialNumber *big.Int
|
||||||
dnsSANs, extKeyUsages []string
|
dnsSANs, extKeyUsages []string
|
||||||
ipSANs []net.IP
|
ipSANs []net.IP
|
||||||
)
|
)
|
||||||
|
|
||||||
switch len(notBeforeStr) {
|
|
||||||
case 0:
|
|
||||||
notBefore = time.Now()
|
|
||||||
default:
|
|
||||||
if notBefore, err = time.Parse(timeLayoutCertificateNotBefore, notBeforeStr); err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to parse not before: %w", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
|
serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
|
||||||
|
|
||||||
if serialNumber, err = ctx.providers.Random.IntErr(serialNumberLimit); err != nil {
|
if serialNumber, err = ctx.providers.Random.IntErr(serialNumberLimit); err != nil {
|
||||||
|
@ -396,7 +405,7 @@ func (ctx *CmdCtx) cryptoGetCertificateFromCmd(cmd *cobra.Command) (certificate
|
||||||
Subject: *subject,
|
Subject: *subject,
|
||||||
|
|
||||||
NotBefore: notBefore,
|
NotBefore: notBefore,
|
||||||
NotAfter: notBefore.Add(duration),
|
NotAfter: notAfter,
|
||||||
|
|
||||||
IsCA: ca,
|
IsCA: ca,
|
||||||
|
|
||||||
|
@ -415,6 +424,57 @@ func (ctx *CmdCtx) cryptoGetCertificateFromCmd(cmd *cobra.Command) (certificate
|
||||||
return certificate, nil
|
return certificate, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func cryptoCertificateValidityFromCmd(cmd *cobra.Command) (notBefore, notAfter time.Time, err error) {
|
||||||
|
never := time.UnixMicro(0)
|
||||||
|
|
||||||
|
switch cmd.Flags().Changed(cmdFlagNameNotBefore) {
|
||||||
|
case true:
|
||||||
|
var notBeforeStr string
|
||||||
|
|
||||||
|
if notBeforeStr, err = cmd.Flags().GetString(cmdFlagNameNotBefore); err != nil {
|
||||||
|
return never, never, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if notBefore, err = utils.ParseTimeString(notBeforeStr); err != nil {
|
||||||
|
return never, never, fmt.Errorf("failed to parse not before: %w", err)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
notBefore = time.Now()
|
||||||
|
}
|
||||||
|
|
||||||
|
switch useNotAfter := cmd.Flags().Changed(cmdFlagNameNotAfter); {
|
||||||
|
case useNotAfter && cmd.Flags().Changed(cmdFlagNameDuration):
|
||||||
|
return never, never, fmt.Errorf("failed to determine not after ")
|
||||||
|
case useNotAfter:
|
||||||
|
var notAfterStr string
|
||||||
|
|
||||||
|
if notAfterStr, err = cmd.Flags().GetString(cmdFlagNameNotAfter); err != nil {
|
||||||
|
return never, never, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if notAfter, err = utils.ParseTimeString(notAfterStr); err != nil {
|
||||||
|
return never, never, fmt.Errorf("failed to parse not after: %w", err)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
var (
|
||||||
|
durationStr string
|
||||||
|
duration time.Duration
|
||||||
|
)
|
||||||
|
|
||||||
|
if durationStr, err = cmd.Flags().GetString(cmdFlagNameDuration); err != nil {
|
||||||
|
return never, never, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if duration, err = utils.ParseDurationString(durationStr); err != nil {
|
||||||
|
return never, never, fmt.Errorf("failed to parse duration string: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
notAfter = notBefore.Add(duration)
|
||||||
|
}
|
||||||
|
|
||||||
|
return notBefore, notAfter, nil
|
||||||
|
}
|
||||||
|
|
||||||
func fmtCryptoHashUse(use string) string {
|
func fmtCryptoHashUse(use string) string {
|
||||||
switch use {
|
switch use {
|
||||||
case cmdUseHashArgon2:
|
case cmdUseHashArgon2:
|
||||||
|
|
|
@ -58,6 +58,7 @@ func NewRootCmd() (cmd *cobra.Command) {
|
||||||
|
|
||||||
newHelpTopic("config", "Help for the config file/directory paths", helpTopicConfig),
|
newHelpTopic("config", "Help for the config file/directory paths", helpTopicConfig),
|
||||||
newHelpTopic("filters", "help topic for the config filters", helpTopicConfigFilters),
|
newHelpTopic("filters", "help topic for the config filters", helpTopicConfigFilters),
|
||||||
|
newHelpTopic("time-layouts", "help topic for the various time layouts", helpTopicTimeLayouts),
|
||||||
)
|
)
|
||||||
|
|
||||||
return cmd
|
return cmd
|
||||||
|
|
|
@ -426,7 +426,7 @@ authentication_backend:
|
||||||
## changed once attributed to a user otherwise it would break the configuration for that user. Technically,
|
## changed once attributed to a user otherwise it would break the configuration for that user. Technically,
|
||||||
## non-unique attributes like 'mail' can also be used but we don't recommend using them, we instead advise to use
|
## non-unique attributes like 'mail' can also be used but we don't recommend using them, we instead advise to use
|
||||||
## a filter to perform alternative lookups and the attributes mentioned above (sAMAccountName and uid) to
|
## a filter to perform alternative lookups and the attributes mentioned above (sAMAccountName and uid) to
|
||||||
## follow https://www.ietf.org/rfc/rfc2307.txt.
|
## follow https://datatracker.ietf.org/doc/html/rfc2307.
|
||||||
# username_attribute: uid
|
# username_attribute: uid
|
||||||
|
|
||||||
## The additional_users_dn is prefixed to base_dn and delimited by a comma when searching for users.
|
## The additional_users_dn is prefixed to base_dn and delimited by a comma when searching for users.
|
||||||
|
|
|
@ -105,6 +105,9 @@ func TestShouldValidateConfigurationWithFilters(t *testing.T) {
|
||||||
testSetEnv(t, "JWT_SECRET", "abc")
|
testSetEnv(t, "JWT_SECRET", "abc")
|
||||||
testSetEnv(t, "AUTHENTICATION_BACKEND_LDAP_PASSWORD", "abc")
|
testSetEnv(t, "AUTHENTICATION_BACKEND_LDAP_PASSWORD", "abc")
|
||||||
|
|
||||||
|
t.Setenv("ABC_CLIENT_SECRET", "$plaintext$example-abc")
|
||||||
|
t.Setenv("XYZ_CLIENT_SECRET", "$plaintext$example-xyz")
|
||||||
|
t.Setenv("ANOTHER_CLIENT_SECRET", "$plaintext$example-123")
|
||||||
t.Setenv("SERVICES_SERVER", "10.10.10.10")
|
t.Setenv("SERVICES_SERVER", "10.10.10.10")
|
||||||
t.Setenv("ROOT_DOMAIN", "example.org")
|
t.Setenv("ROOT_DOMAIN", "example.org")
|
||||||
|
|
||||||
|
@ -118,6 +121,11 @@ func TestShouldValidateConfigurationWithFilters(t *testing.T) {
|
||||||
assert.Equal(t, "api-123456789.example.org", config.DuoAPI.Hostname)
|
assert.Equal(t, "api-123456789.example.org", config.DuoAPI.Hostname)
|
||||||
assert.Equal(t, "10.10.10.10", config.Notifier.SMTP.Host)
|
assert.Equal(t, "10.10.10.10", config.Notifier.SMTP.Host)
|
||||||
assert.Equal(t, "10.10.10.10", config.Session.Redis.Host)
|
assert.Equal(t, "10.10.10.10", config.Session.Redis.Host)
|
||||||
|
|
||||||
|
require.Len(t, config.IdentityProviders.OIDC.Clients, 3)
|
||||||
|
assert.Equal(t, "$plaintext$example-abc", config.IdentityProviders.OIDC.Clients[0].Secret.String())
|
||||||
|
assert.Equal(t, "$plaintext$example-xyz", config.IdentityProviders.OIDC.Clients[1].Secret.String())
|
||||||
|
assert.Equal(t, "$plaintext$example-123", config.IdentityProviders.OIDC.Clients[2].Secret.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestShouldNotIgnoreInvalidEnvs(t *testing.T) {
|
func TestShouldNotIgnoreInvalidEnvs(t *testing.T) {
|
||||||
|
|
|
@ -199,6 +199,20 @@ var DefaultLDAPAuthenticationBackendConfigurationImplementationActiveDirectory =
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DefaultLDAPAuthenticationBackendConfigurationImplementationRFC2307bis represents the default LDAP config for the LDAPImplementationRFC2307bis Implementation.
|
||||||
|
var DefaultLDAPAuthenticationBackendConfigurationImplementationRFC2307bis = LDAPAuthenticationBackend{
|
||||||
|
UsersFilter: "(&(|({username_attribute}={input})({mail_attribute}={input}))(|(objectClass=inetOrgPerson)(objectClass=organizationalPerson)))",
|
||||||
|
UsernameAttribute: ldapAttrUserID,
|
||||||
|
MailAttribute: ldapAttrMail,
|
||||||
|
DisplayNameAttribute: ldapAttrDisplayName,
|
||||||
|
GroupsFilter: "(&(|(member={dn})(uniqueMember={dn}))(|(objectClass=groupOfNames)(objectClass=groupOfUniqueNames)(objectClass=groupOfMembers)))",
|
||||||
|
GroupNameAttribute: ldapAttrCommonName,
|
||||||
|
Timeout: time.Second * 5,
|
||||||
|
TLS: &TLSConfig{
|
||||||
|
MinimumVersion: TLSVersion{tls.VersionTLS12},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
// DefaultLDAPAuthenticationBackendConfigurationImplementationFreeIPA represents the default LDAP config for the LDAPImplementationFreeIPA Implementation.
|
// DefaultLDAPAuthenticationBackendConfigurationImplementationFreeIPA represents the default LDAP config for the LDAPImplementationFreeIPA Implementation.
|
||||||
var DefaultLDAPAuthenticationBackendConfigurationImplementationFreeIPA = LDAPAuthenticationBackend{
|
var DefaultLDAPAuthenticationBackendConfigurationImplementationFreeIPA = LDAPAuthenticationBackend{
|
||||||
UsersFilter: "(&(|({username_attribute}={input})({mail_attribute}={input}))(objectClass=person)(!(nsAccountLock=TRUE))(krbPasswordExpiration>={date-time:generalized})(|(!(krbPrincipalExpiration=*))(krbPrincipalExpiration>={date-time:generalized})))",
|
UsersFilter: "(&(|({username_attribute}={input})({mail_attribute}={input}))(objectClass=person)(!(nsAccountLock=TRUE))(krbPasswordExpiration>={date-time:generalized})(|(!(krbPrincipalExpiration=*))(krbPrincipalExpiration>={date-time:generalized})))",
|
||||||
|
|
|
@ -65,6 +65,9 @@ const (
|
||||||
// LDAPImplementationActiveDirectory is the string for the Active Directory LDAP implementation.
|
// LDAPImplementationActiveDirectory is the string for the Active Directory LDAP implementation.
|
||||||
LDAPImplementationActiveDirectory = "activedirectory"
|
LDAPImplementationActiveDirectory = "activedirectory"
|
||||||
|
|
||||||
|
// LDAPImplementationRFC2307bis is the string for the RFC2307bis LDAP implementation.
|
||||||
|
LDAPImplementationRFC2307bis = "rfc2307bis"
|
||||||
|
|
||||||
// LDAPImplementationFreeIPA is the string for the FreeIPA LDAP implementation.
|
// LDAPImplementationFreeIPA is the string for the FreeIPA LDAP implementation.
|
||||||
LDAPImplementationFreeIPA = "freeipa"
|
LDAPImplementationFreeIPA = "freeipa"
|
||||||
|
|
||||||
|
|
|
@ -174,4 +174,21 @@ notifier:
|
||||||
port: 1025
|
port: 1025
|
||||||
sender: 'admin@{{ env "ROOT_DOMAIN" }}'
|
sender: 'admin@{{ env "ROOT_DOMAIN" }}'
|
||||||
disable_require_tls: true
|
disable_require_tls: true
|
||||||
|
|
||||||
|
identity_providers:
|
||||||
|
oidc:
|
||||||
|
cors:
|
||||||
|
allowed_origins:
|
||||||
|
- https://google.com
|
||||||
|
- https://example.com
|
||||||
|
clients:
|
||||||
|
- id: abc
|
||||||
|
secret: '${ABC_CLIENT_SECRET}'
|
||||||
|
consent_mode: explicit
|
||||||
|
- id: xyz
|
||||||
|
secret: '$XYZ_CLIENT_SECRET'
|
||||||
|
consent_mode: explicit
|
||||||
|
- id: '123'
|
||||||
|
secret: $ANOTHER_CLIENT_SECRET
|
||||||
|
consent_mode: explicit
|
||||||
...
|
...
|
||||||
|
|
|
@ -321,49 +321,19 @@ func validateLDAPAuthenticationBackend(config *schema.AuthenticationBackend, val
|
||||||
config.LDAP.Implementation = schema.LDAPImplementationCustom
|
config.LDAP.Implementation = schema.LDAPImplementationCustom
|
||||||
}
|
}
|
||||||
|
|
||||||
var implementation *schema.LDAPAuthenticationBackend
|
defaultTLS := validateLDAPAuthenticationBackendImplementation(config, validator)
|
||||||
|
|
||||||
switch config.LDAP.Implementation {
|
|
||||||
case schema.LDAPImplementationCustom:
|
|
||||||
implementation = &schema.DefaultLDAPAuthenticationBackendConfigurationImplementationCustom
|
|
||||||
case schema.LDAPImplementationActiveDirectory:
|
|
||||||
implementation = &schema.DefaultLDAPAuthenticationBackendConfigurationImplementationActiveDirectory
|
|
||||||
case schema.LDAPImplementationFreeIPA:
|
|
||||||
implementation = &schema.DefaultLDAPAuthenticationBackendConfigurationImplementationFreeIPA
|
|
||||||
case schema.LDAPImplementationLLDAP:
|
|
||||||
implementation = &schema.DefaultLDAPAuthenticationBackendConfigurationImplementationLLDAP
|
|
||||||
case schema.LDAPImplementationGLAuth:
|
|
||||||
implementation = &schema.DefaultLDAPAuthenticationBackendConfigurationImplementationGLAuth
|
|
||||||
default:
|
|
||||||
validator.Push(fmt.Errorf(errFmtLDAPAuthBackendImplementation, config.LDAP.Implementation, strings.Join(validLDAPImplementations, "', '")))
|
|
||||||
}
|
|
||||||
|
|
||||||
configDefaultTLS := &schema.TLSConfig{}
|
|
||||||
|
|
||||||
if implementation != nil {
|
|
||||||
if config.LDAP.Timeout == 0 {
|
|
||||||
config.LDAP.Timeout = implementation.Timeout
|
|
||||||
}
|
|
||||||
|
|
||||||
configDefaultTLS = &schema.TLSConfig{
|
|
||||||
MinimumVersion: implementation.TLS.MinimumVersion,
|
|
||||||
MaximumVersion: implementation.TLS.MaximumVersion,
|
|
||||||
}
|
|
||||||
|
|
||||||
setDefaultImplementationLDAPAuthenticationBackendProfileAttributes(config.LDAP, implementation)
|
|
||||||
}
|
|
||||||
|
|
||||||
if config.LDAP.URL == "" {
|
if config.LDAP.URL == "" {
|
||||||
validator.Push(fmt.Errorf(errFmtLDAPAuthBackendMissingOption, "url"))
|
validator.Push(fmt.Errorf(errFmtLDAPAuthBackendMissingOption, "url"))
|
||||||
} else {
|
} else {
|
||||||
configDefaultTLS.ServerName = validateLDAPAuthenticationBackendURL(config.LDAP, validator)
|
defaultTLS.ServerName = validateLDAPAuthenticationBackendURL(config.LDAP, validator)
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.LDAP.TLS == nil {
|
if config.LDAP.TLS == nil {
|
||||||
config.LDAP.TLS = &schema.TLSConfig{}
|
config.LDAP.TLS = &schema.TLSConfig{}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := ValidateTLSConfig(config.LDAP.TLS, configDefaultTLS); err != nil {
|
if err := ValidateTLSConfig(config.LDAP.TLS, defaultTLS); err != nil {
|
||||||
validator.Push(fmt.Errorf(errFmtLDAPAuthBackendTLSConfigInvalid, err))
|
validator.Push(fmt.Errorf(errFmtLDAPAuthBackendTLSConfigInvalid, err))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -382,6 +352,44 @@ func validateLDAPAuthenticationBackend(config *schema.AuthenticationBackend, val
|
||||||
validateLDAPRequiredParameters(config, validator)
|
validateLDAPRequiredParameters(config, validator)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func validateLDAPAuthenticationBackendImplementation(config *schema.AuthenticationBackend, validator *schema.StructValidator) *schema.TLSConfig {
|
||||||
|
var implementation *schema.LDAPAuthenticationBackend
|
||||||
|
|
||||||
|
switch config.LDAP.Implementation {
|
||||||
|
case schema.LDAPImplementationCustom:
|
||||||
|
implementation = &schema.DefaultLDAPAuthenticationBackendConfigurationImplementationCustom
|
||||||
|
case schema.LDAPImplementationActiveDirectory:
|
||||||
|
implementation = &schema.DefaultLDAPAuthenticationBackendConfigurationImplementationActiveDirectory
|
||||||
|
case schema.LDAPImplementationRFC2307bis:
|
||||||
|
implementation = &schema.DefaultLDAPAuthenticationBackendConfigurationImplementationRFC2307bis
|
||||||
|
case schema.LDAPImplementationFreeIPA:
|
||||||
|
implementation = &schema.DefaultLDAPAuthenticationBackendConfigurationImplementationFreeIPA
|
||||||
|
case schema.LDAPImplementationLLDAP:
|
||||||
|
implementation = &schema.DefaultLDAPAuthenticationBackendConfigurationImplementationLLDAP
|
||||||
|
case schema.LDAPImplementationGLAuth:
|
||||||
|
implementation = &schema.DefaultLDAPAuthenticationBackendConfigurationImplementationGLAuth
|
||||||
|
default:
|
||||||
|
validator.Push(fmt.Errorf(errFmtLDAPAuthBackendImplementation, config.LDAP.Implementation, strings.Join(validLDAPImplementations, "', '")))
|
||||||
|
}
|
||||||
|
|
||||||
|
tlsconfig := &schema.TLSConfig{}
|
||||||
|
|
||||||
|
if implementation != nil {
|
||||||
|
if config.LDAP.Timeout == 0 {
|
||||||
|
config.LDAP.Timeout = implementation.Timeout
|
||||||
|
}
|
||||||
|
|
||||||
|
tlsconfig = &schema.TLSConfig{
|
||||||
|
MinimumVersion: implementation.TLS.MinimumVersion,
|
||||||
|
MaximumVersion: implementation.TLS.MaximumVersion,
|
||||||
|
}
|
||||||
|
|
||||||
|
setDefaultImplementationLDAPAuthenticationBackendProfileAttributes(config.LDAP, implementation)
|
||||||
|
}
|
||||||
|
|
||||||
|
return tlsconfig
|
||||||
|
}
|
||||||
|
|
||||||
func ldapImplementationShouldSetStr(config, implementation string) bool {
|
func ldapImplementationShouldSetStr(config, implementation string) bool {
|
||||||
return config == "" && implementation != ""
|
return config == "" && implementation != ""
|
||||||
}
|
}
|
||||||
|
|
|
@ -609,7 +609,7 @@ func (suite *LDAPAuthenticationBackendSuite) TestShouldRaiseErrorWhenImplementat
|
||||||
suite.Assert().Len(suite.validator.Warnings(), 0)
|
suite.Assert().Len(suite.validator.Warnings(), 0)
|
||||||
suite.Require().Len(suite.validator.Errors(), 1)
|
suite.Require().Len(suite.validator.Errors(), 1)
|
||||||
|
|
||||||
suite.Assert().EqualError(suite.validator.Errors()[0], "authentication_backend: ldap: option 'implementation' is configured as 'masd' but must be one of the following values: 'custom', 'activedirectory', 'freeipa', 'lldap'")
|
suite.Assert().EqualError(suite.validator.Errors()[0], "authentication_backend: ldap: option 'implementation' is configured as 'masd' but must be one of the following values: 'custom', 'activedirectory', 'rfc2307bis', 'freeipa', 'lldap', 'glauth'")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *LDAPAuthenticationBackendSuite) TestShouldRaiseErrorWhenURLNotProvided() {
|
func (suite *LDAPAuthenticationBackendSuite) TestShouldRaiseErrorWhenURLNotProvided() {
|
||||||
|
@ -1002,6 +1002,108 @@ func TestActiveDirectoryAuthenticationBackend(t *testing.T) {
|
||||||
suite.Run(t, new(ActiveDirectoryAuthenticationBackendSuite))
|
suite.Run(t, new(ActiveDirectoryAuthenticationBackendSuite))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type RFC2307bisAuthenticationBackendSuite struct {
|
||||||
|
suite.Suite
|
||||||
|
config schema.AuthenticationBackend
|
||||||
|
validator *schema.StructValidator
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *RFC2307bisAuthenticationBackendSuite) SetupTest() {
|
||||||
|
suite.validator = schema.NewStructValidator()
|
||||||
|
suite.config = schema.AuthenticationBackend{}
|
||||||
|
suite.config.LDAP = &schema.LDAPAuthenticationBackend{}
|
||||||
|
suite.config.LDAP.Implementation = schema.LDAPImplementationRFC2307bis
|
||||||
|
suite.config.LDAP.URL = testLDAPURL
|
||||||
|
suite.config.LDAP.User = testLDAPUser
|
||||||
|
suite.config.LDAP.Password = testLDAPPassword
|
||||||
|
suite.config.LDAP.BaseDN = testLDAPBaseDN
|
||||||
|
suite.config.LDAP.TLS = schema.DefaultLDAPAuthenticationBackendConfigurationImplementationRFC2307bis.TLS
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *RFC2307bisAuthenticationBackendSuite) TestShouldSetDefaults() {
|
||||||
|
ValidateAuthenticationBackend(&suite.config, suite.validator)
|
||||||
|
|
||||||
|
suite.Assert().Len(suite.validator.Warnings(), 0)
|
||||||
|
suite.Assert().Len(suite.validator.Errors(), 0)
|
||||||
|
|
||||||
|
suite.Assert().Equal(
|
||||||
|
schema.DefaultLDAPAuthenticationBackendConfigurationImplementationRFC2307bis.Timeout,
|
||||||
|
suite.config.LDAP.Timeout)
|
||||||
|
suite.Assert().Equal(
|
||||||
|
schema.DefaultLDAPAuthenticationBackendConfigurationImplementationRFC2307bis.AdditionalUsersDN,
|
||||||
|
suite.config.LDAP.AdditionalUsersDN)
|
||||||
|
suite.Assert().Equal(
|
||||||
|
schema.DefaultLDAPAuthenticationBackendConfigurationImplementationRFC2307bis.AdditionalGroupsDN,
|
||||||
|
suite.config.LDAP.AdditionalGroupsDN)
|
||||||
|
suite.Assert().Equal(
|
||||||
|
schema.DefaultLDAPAuthenticationBackendConfigurationImplementationRFC2307bis.UsersFilter,
|
||||||
|
suite.config.LDAP.UsersFilter)
|
||||||
|
suite.Assert().Equal(
|
||||||
|
schema.DefaultLDAPAuthenticationBackendConfigurationImplementationRFC2307bis.UsernameAttribute,
|
||||||
|
suite.config.LDAP.UsernameAttribute)
|
||||||
|
suite.Assert().Equal(
|
||||||
|
schema.DefaultLDAPAuthenticationBackendConfigurationImplementationRFC2307bis.DisplayNameAttribute,
|
||||||
|
suite.config.LDAP.DisplayNameAttribute)
|
||||||
|
suite.Assert().Equal(
|
||||||
|
schema.DefaultLDAPAuthenticationBackendConfigurationImplementationRFC2307bis.MailAttribute,
|
||||||
|
suite.config.LDAP.MailAttribute)
|
||||||
|
suite.Assert().Equal(
|
||||||
|
schema.DefaultLDAPAuthenticationBackendConfigurationImplementationRFC2307bis.GroupsFilter,
|
||||||
|
suite.config.LDAP.GroupsFilter)
|
||||||
|
suite.Assert().Equal(
|
||||||
|
schema.DefaultLDAPAuthenticationBackendConfigurationImplementationRFC2307bis.GroupNameAttribute,
|
||||||
|
suite.config.LDAP.GroupNameAttribute)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *RFC2307bisAuthenticationBackendSuite) TestShouldOnlySetDefaultsIfNotManuallyConfigured() {
|
||||||
|
suite.config.LDAP.Timeout = time.Second * 2
|
||||||
|
suite.config.LDAP.UsersFilter = "(&({username_attribute}={input})(objectClass=Person))"
|
||||||
|
suite.config.LDAP.UsernameAttribute = "o"
|
||||||
|
suite.config.LDAP.MailAttribute = "Email"
|
||||||
|
suite.config.LDAP.DisplayNameAttribute = "Given"
|
||||||
|
suite.config.LDAP.GroupsFilter = "(&(member={dn})(objectClass=posixGroup)(objectClass=top))"
|
||||||
|
suite.config.LDAP.GroupNameAttribute = "gid"
|
||||||
|
suite.config.LDAP.AdditionalUsersDN = "OU=users,OU=OpenLDAP"
|
||||||
|
suite.config.LDAP.AdditionalGroupsDN = "OU=groups,OU=OpenLDAP"
|
||||||
|
|
||||||
|
ValidateAuthenticationBackend(&suite.config, suite.validator)
|
||||||
|
|
||||||
|
suite.Assert().NotEqual(
|
||||||
|
schema.DefaultLDAPAuthenticationBackendConfigurationImplementationRFC2307bis.Timeout,
|
||||||
|
suite.config.LDAP.Timeout)
|
||||||
|
suite.Assert().NotEqual(
|
||||||
|
schema.DefaultLDAPAuthenticationBackendConfigurationImplementationRFC2307bis.AdditionalUsersDN,
|
||||||
|
suite.config.LDAP.AdditionalUsersDN)
|
||||||
|
suite.Assert().NotEqual(
|
||||||
|
schema.DefaultLDAPAuthenticationBackendConfigurationImplementationRFC2307bis.AdditionalGroupsDN,
|
||||||
|
suite.config.LDAP.AdditionalGroupsDN)
|
||||||
|
suite.Assert().NotEqual(
|
||||||
|
schema.DefaultLDAPAuthenticationBackendConfigurationImplementationRFC2307bis.Timeout,
|
||||||
|
suite.config.LDAP.Timeout)
|
||||||
|
suite.Assert().NotEqual(
|
||||||
|
schema.DefaultLDAPAuthenticationBackendConfigurationImplementationRFC2307bis.UsersFilter,
|
||||||
|
suite.config.LDAP.UsersFilter)
|
||||||
|
suite.Assert().NotEqual(
|
||||||
|
schema.DefaultLDAPAuthenticationBackendConfigurationImplementationRFC2307bis.UsernameAttribute,
|
||||||
|
suite.config.LDAP.UsernameAttribute)
|
||||||
|
suite.Assert().NotEqual(
|
||||||
|
schema.DefaultLDAPAuthenticationBackendConfigurationImplementationRFC2307bis.DisplayNameAttribute,
|
||||||
|
suite.config.LDAP.DisplayNameAttribute)
|
||||||
|
suite.Assert().NotEqual(
|
||||||
|
schema.DefaultLDAPAuthenticationBackendConfigurationImplementationRFC2307bis.MailAttribute,
|
||||||
|
suite.config.LDAP.MailAttribute)
|
||||||
|
suite.Assert().NotEqual(
|
||||||
|
schema.DefaultLDAPAuthenticationBackendConfigurationImplementationRFC2307bis.GroupsFilter,
|
||||||
|
suite.config.LDAP.GroupsFilter)
|
||||||
|
suite.Assert().NotEqual(
|
||||||
|
schema.DefaultLDAPAuthenticationBackendConfigurationImplementationRFC2307bis.GroupNameAttribute,
|
||||||
|
suite.config.LDAP.GroupNameAttribute)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRFC2307bisAuthenticationBackend(t *testing.T) {
|
||||||
|
suite.Run(t, new(RFC2307bisAuthenticationBackendSuite))
|
||||||
|
}
|
||||||
|
|
||||||
type FreeIPAAuthenticationBackendSuite struct {
|
type FreeIPAAuthenticationBackendSuite struct {
|
||||||
suite.Suite
|
suite.Suite
|
||||||
config schema.AuthenticationBackend
|
config schema.AuthenticationBackend
|
||||||
|
|
|
@ -160,7 +160,7 @@ func TestShouldRaiseErrorOnInvalidCertificatesDirectory(t *testing.T) {
|
||||||
func TestShouldNotRaiseErrorOnValidCertificatesDirectory(t *testing.T) {
|
func TestShouldNotRaiseErrorOnValidCertificatesDirectory(t *testing.T) {
|
||||||
validator := schema.NewStructValidator()
|
validator := schema.NewStructValidator()
|
||||||
config := newDefaultConfig()
|
config := newDefaultConfig()
|
||||||
config.CertificatesDirectory = "../../suites/common/ssl"
|
config.CertificatesDirectory = "../../suites/common/pki"
|
||||||
|
|
||||||
ValidateConfiguration(&config, validator)
|
ValidateConfiguration(&config, validator)
|
||||||
|
|
||||||
|
|
|
@ -267,7 +267,9 @@ const (
|
||||||
errFmtSessionDomainDuplicateCookieScope = "session: domain config %s: option 'domain' shares the same cookie domain scope as another configured session domain"
|
errFmtSessionDomainDuplicateCookieScope = "session: domain config %s: option 'domain' shares the same cookie domain scope as another configured session domain"
|
||||||
errFmtSessionDomainPortalURLInsecure = "session: domain config %s: option 'authelia_url' does not have a secure scheme with a value of '%s'"
|
errFmtSessionDomainPortalURLInsecure = "session: domain config %s: option 'authelia_url' does not have a secure scheme with a value of '%s'"
|
||||||
errFmtSessionDomainPortalURLNotInCookieScope = "session: domain config %s: option 'authelia_url' does not share a cookie scope with domain '%s' with a value of '%s'"
|
errFmtSessionDomainPortalURLNotInCookieScope = "session: domain config %s: option 'authelia_url' does not share a cookie scope with domain '%s' with a value of '%s'"
|
||||||
errFmtSessionDomainInvalidDomain = "session: domain config %s: option 'domain' is not a valid domain"
|
errFmtSessionDomainInvalidDomain = "session: domain config %s: option 'domain' is not a valid cookie domain"
|
||||||
|
errFmtSessionDomainInvalidDomainNoDots = "session: domain config %s: option 'domain' is not a valid cookie domain: must have at least a single period"
|
||||||
|
errFmtSessionDomainInvalidDomainPublic = "session: domain config %s: option 'domain' is not a valid cookie domain: the domain is part of the special public suffix list"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Regulation Error Consts.
|
// Regulation Error Consts.
|
||||||
|
@ -337,7 +339,14 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
validLDAPImplementations = []string{schema.LDAPImplementationCustom, schema.LDAPImplementationActiveDirectory, schema.LDAPImplementationFreeIPA, schema.LDAPImplementationLLDAP}
|
validLDAPImplementations = []string{
|
||||||
|
schema.LDAPImplementationCustom,
|
||||||
|
schema.LDAPImplementationActiveDirectory,
|
||||||
|
schema.LDAPImplementationRFC2307bis,
|
||||||
|
schema.LDAPImplementationFreeIPA,
|
||||||
|
schema.LDAPImplementationLLDAP,
|
||||||
|
schema.LDAPImplementationGLAuth,
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
|
@ -104,12 +104,22 @@ func validateSessionDomainName(i int, config *schema.SessionConfiguration, valid
|
||||||
switch {
|
switch {
|
||||||
case d.Domain == "":
|
case d.Domain == "":
|
||||||
validator.Push(fmt.Errorf(errFmtSessionDomainRequired, sessionDomainDescriptor(i, d)))
|
validator.Push(fmt.Errorf(errFmtSessionDomainRequired, sessionDomainDescriptor(i, d)))
|
||||||
|
return
|
||||||
case strings.HasPrefix(d.Domain, "*."):
|
case strings.HasPrefix(d.Domain, "*."):
|
||||||
validator.Push(fmt.Errorf(errFmtSessionDomainMustBeRoot, sessionDomainDescriptor(i, d), d.Domain))
|
validator.Push(fmt.Errorf(errFmtSessionDomainMustBeRoot, sessionDomainDescriptor(i, d), d.Domain))
|
||||||
|
return
|
||||||
case strings.HasPrefix(d.Domain, "."):
|
case strings.HasPrefix(d.Domain, "."):
|
||||||
validator.PushWarning(fmt.Errorf(errFmtSessionDomainHasPeriodPrefix, sessionDomainDescriptor(i, d)))
|
validator.PushWarning(fmt.Errorf(errFmtSessionDomainHasPeriodPrefix, sessionDomainDescriptor(i, d)))
|
||||||
|
case !strings.Contains(d.Domain, "."):
|
||||||
|
validator.Push(fmt.Errorf(errFmtSessionDomainInvalidDomainNoDots, sessionDomainDescriptor(i, d)))
|
||||||
|
return
|
||||||
case !reDomainCharacters.MatchString(d.Domain):
|
case !reDomainCharacters.MatchString(d.Domain):
|
||||||
validator.Push(fmt.Errorf(errFmtSessionDomainInvalidDomain, sessionDomainDescriptor(i, d)))
|
validator.Push(fmt.Errorf(errFmtSessionDomainInvalidDomain, sessionDomainDescriptor(i, d)))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if isCookieDomainAPublicSuffix(d.Domain) {
|
||||||
|
validator.Push(fmt.Errorf(errFmtSessionDomainInvalidDomainPublic, sessionDomainDescriptor(i, d)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -586,45 +586,6 @@ func TestShouldRaiseErrorOnBadRedisTLSOptionsMinVerGreaterThanMax(t *testing.T)
|
||||||
assert.EqualError(t, validator.Errors()[0], "session: redis: tls: option combination of 'minimum_version' and 'maximum_version' is invalid: minimum version TLS1.3 is greater than the maximum version TLS1.0")
|
assert.EqualError(t, validator.Errors()[0], "session: redis: tls: option combination of 'minimum_version' and 'maximum_version' is invalid: minimum version TLS1.3 is greater than the maximum version TLS1.0")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestShouldRaiseErrorWhenDomainNotSet(t *testing.T) {
|
|
||||||
validator := schema.NewStructValidator()
|
|
||||||
config := newDefaultSessionConfig()
|
|
||||||
config.Domain = ""
|
|
||||||
config.Cookies = []schema.SessionCookieConfiguration{}
|
|
||||||
|
|
||||||
ValidateSession(&config, validator)
|
|
||||||
|
|
||||||
assert.False(t, validator.HasWarnings())
|
|
||||||
assert.Len(t, validator.Errors(), 1)
|
|
||||||
assert.EqualError(t, validator.Errors()[0], "session: option 'domain' is required")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestShouldRaiseErrorWhenDomainIsWildcard(t *testing.T) {
|
|
||||||
validator := schema.NewStructValidator()
|
|
||||||
config := newDefaultSessionConfig()
|
|
||||||
config.Domain = "*.example.com"
|
|
||||||
|
|
||||||
ValidateSession(&config, validator)
|
|
||||||
|
|
||||||
assert.Len(t, validator.Warnings(), 0)
|
|
||||||
require.Len(t, validator.Errors(), 1)
|
|
||||||
|
|
||||||
assert.EqualError(t, validator.Errors()[0], "session: domain config #1 (domain '*.example.com'): option 'domain' must be the domain you wish to protect not a wildcard domain but it is configured as '*.example.com'")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestShouldRaiseErrorWhenDomainNameIsInvalid(t *testing.T) {
|
|
||||||
validator := schema.NewStructValidator()
|
|
||||||
config := newDefaultSessionConfig()
|
|
||||||
config.Domain = "example!.com"
|
|
||||||
|
|
||||||
ValidateSession(&config, validator)
|
|
||||||
|
|
||||||
assert.Len(t, validator.Warnings(), 0)
|
|
||||||
require.Len(t, validator.Errors(), 1)
|
|
||||||
|
|
||||||
assert.EqualError(t, validator.Errors()[0], "session: domain config #1 (domain 'example!.com'): option 'domain' is not a valid domain")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestShouldRaiseErrorWhenHaveDuplicatedDomainName(t *testing.T) {
|
func TestShouldRaiseErrorWhenHaveDuplicatedDomainName(t *testing.T) {
|
||||||
validator := schema.NewStructValidator()
|
validator := schema.NewStructValidator()
|
||||||
config := newDefaultSessionConfig()
|
config := newDefaultSessionConfig()
|
||||||
|
@ -675,10 +636,18 @@ func TestShouldRaiseErrorWhenDomainIsInvalid(t *testing.T) {
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
name string
|
name string
|
||||||
have string
|
have string
|
||||||
|
warnings []string
|
||||||
expected []string
|
expected []string
|
||||||
}{
|
}{
|
||||||
{"ShouldRaiseErrorOnMissingDomain", "", []string{"session: domain config #1 (domain ''): option 'domain' is required"}},
|
{"ShouldNotRaiseErrorOnValidDomain", exampleDotCom, nil, nil},
|
||||||
{"ShouldNotRaiseErrorOnValidDomain", exampleDotCom, nil},
|
{"ShouldRaiseErrorOnMissingDomain", "", nil, []string{"session: domain config #1 (domain ''): option 'domain' is required"}},
|
||||||
|
{"ShouldRaiseErrorOnDomainWithInvalidChars", "example!.com", nil, []string{"session: domain config #1 (domain 'example!.com'): option 'domain' is not a valid cookie domain"}},
|
||||||
|
{"ShouldRaiseErrorOnDomainWithoutDots", "localhost", nil, []string{"session: domain config #1 (domain 'localhost'): option 'domain' is not a valid cookie domain: must have at least a single period"}},
|
||||||
|
{"ShouldRaiseErrorOnPublicDomainDuckDNS", "duckdns.org", nil, []string{"session: domain config #1 (domain 'duckdns.org'): option 'domain' is not a valid cookie domain: the domain is part of the special public suffix list"}},
|
||||||
|
{"ShouldNotRaiseErrorOnSuffixOfPublicDomainDuckDNS", "example.duckdns.org", nil, nil},
|
||||||
|
{"ShouldRaiseWarningOnDomainWithLeadingDot", ".example.com", []string{"session: domain config #1 (domain '.example.com'): option 'domain' has a prefix of '.' which is not supported or intended behaviour: you can use this at your own risk but we recommend removing it"}, nil},
|
||||||
|
{"ShouldRaiseErrorOnDomainWithLeadingStarDot", "*.example.com", nil, []string{"session: domain config #1 (domain '*.example.com'): option 'domain' must be the domain you wish to protect not a wildcard domain but it is configured as '*.example.com'"}},
|
||||||
|
{"ShouldRaiseErrorOnDomainNotSet", "", nil, []string{"session: domain config #1 (domain ''): option 'domain' is required"}},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
|
@ -692,14 +661,18 @@ func TestShouldRaiseErrorWhenDomainIsInvalid(t *testing.T) {
|
||||||
SessionCookieCommonConfiguration: schema.SessionCookieCommonConfiguration{
|
SessionCookieCommonConfiguration: schema.SessionCookieCommonConfiguration{
|
||||||
Domain: tc.have,
|
Domain: tc.have,
|
||||||
},
|
},
|
||||||
AutheliaURL: MustParseURL("https://auth.example.com")},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
ValidateSession(&config, validator)
|
ValidateSession(&config, validator)
|
||||||
|
|
||||||
assert.Len(t, validator.Warnings(), 0)
|
require.Len(t, validator.Warnings(), len(tc.warnings))
|
||||||
require.Len(t, validator.Errors(), len(tc.expected))
|
require.Len(t, validator.Errors(), len(tc.expected))
|
||||||
|
|
||||||
|
for i, expected := range tc.warnings {
|
||||||
|
assert.EqualError(t, validator.Warnings()[i], expected)
|
||||||
|
}
|
||||||
|
|
||||||
for i, expected := range tc.expected {
|
for i, expected := range tc.expected {
|
||||||
assert.EqualError(t, validator.Errors()[i], expected)
|
assert.EqualError(t, validator.Errors()[i], expected)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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:
|
/* The OPTIONS method should not return a 204 as per the following specifications when read together:
|
||||||
|
|
||||||
RFC7231 (https://www.rfc-editor.org/rfc/rfc7231#section-4.3.7):
|
RFC7231 (https://datatracker.ietf.org/doc/html/rfc7231#section-4.3.7):
|
||||||
A server MUST generate a Content-Length field with a value of "0" if no payload body is to be sent in
|
A server MUST generate a Content-Length field with a value of "0" if no payload body is to be sent in
|
||||||
the response.
|
the response.
|
||||||
|
|
||||||
RFC7230 (https://www.rfc-editor.org/rfc/rfc7230#section-3.3.2):
|
RFC7230 (https://datatracker.ietf.org/doc/html/rfc7230#section-3.3.2):
|
||||||
A server MUST NOT send a Content-Length header field in any response with a status code of 1xx (Informational)
|
A server MUST NOT send a Content-Length header field in any response with a status code of 1xx (Informational)
|
||||||
or 204 (No Content).
|
or 204 (No Content).
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -121,33 +121,48 @@ func (mr *MockRandomMockRecorder) IntErr(arg0 interface{}) *gomock.Call {
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IntErr", reflect.TypeOf((*MockRandom)(nil).IntErr), arg0)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IntErr", reflect.TypeOf((*MockRandom)(nil).IntErr), arg0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Integer mocks base method.
|
// Intn mocks base method.
|
||||||
func (m *MockRandom) Integer(arg0 int) int {
|
func (m *MockRandom) Intn(arg0 int) int {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "Integer", arg0)
|
ret := m.ctrl.Call(m, "Intn", arg0)
|
||||||
ret0, _ := ret[0].(int)
|
ret0, _ := ret[0].(int)
|
||||||
return ret0
|
return ret0
|
||||||
}
|
}
|
||||||
|
|
||||||
// Integer indicates an expected call of Integer.
|
// Intn indicates an expected call of Intn.
|
||||||
func (mr *MockRandomMockRecorder) Integer(arg0 interface{}) *gomock.Call {
|
func (mr *MockRandomMockRecorder) Intn(arg0 interface{}) *gomock.Call {
|
||||||
mr.mock.ctrl.T.Helper()
|
mr.mock.ctrl.T.Helper()
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Integer", reflect.TypeOf((*MockRandom)(nil).Integer), arg0)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Intn", reflect.TypeOf((*MockRandom)(nil).Intn), arg0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// IntegerErr mocks base method.
|
// IntnErr mocks base method.
|
||||||
func (m *MockRandom) IntegerErr(arg0 int) (int, error) {
|
func (m *MockRandom) IntnErr(arg0 int) (int, error) {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "IntegerErr", arg0)
|
ret := m.ctrl.Call(m, "IntnErr", arg0)
|
||||||
ret0, _ := ret[0].(int)
|
ret0, _ := ret[0].(int)
|
||||||
ret1, _ := ret[1].(error)
|
ret1, _ := ret[1].(error)
|
||||||
return ret0, ret1
|
return ret0, ret1
|
||||||
}
|
}
|
||||||
|
|
||||||
// IntegerErr indicates an expected call of IntegerErr.
|
// IntnErr indicates an expected call of IntnErr.
|
||||||
func (mr *MockRandomMockRecorder) IntegerErr(arg0 interface{}) *gomock.Call {
|
func (mr *MockRandomMockRecorder) IntnErr(arg0 interface{}) *gomock.Call {
|
||||||
mr.mock.ctrl.T.Helper()
|
mr.mock.ctrl.T.Helper()
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IntegerErr", reflect.TypeOf((*MockRandom)(nil).IntegerErr), arg0)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IntnErr", reflect.TypeOf((*MockRandom)(nil).IntnErr), arg0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prime mocks base method.
|
||||||
|
func (m *MockRandom) Prime(arg0 int) (*big.Int, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "Prime", arg0)
|
||||||
|
ret0, _ := ret[0].(*big.Int)
|
||||||
|
ret1, _ := ret[1].(error)
|
||||||
|
return ret0, ret1
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prime indicates an expected call of Prime.
|
||||||
|
func (mr *MockRandomMockRecorder) Prime(arg0 interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Prime", reflect.TypeOf((*MockRandom)(nil).Prime), arg0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read mocks base method.
|
// Read mocks base method.
|
||||||
|
|
|
@ -163,8 +163,8 @@ func (n *SMTPNotifier) Send(ctx context.Context, recipient mail.Address, subject
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *SMTPNotifier) setMessageID(msg *gomail.Msg, domain string) {
|
func (n *SMTPNotifier) setMessageID(msg *gomail.Msg, domain string) {
|
||||||
rn := n.random.Integer(100000000)
|
rn := n.random.Intn(100000000)
|
||||||
rm := n.random.Integer(10000)
|
rm := n.random.Intn(10000)
|
||||||
rs := n.random.StringCustom(17, random.CharSetAlphaNumeric)
|
rs := n.random.StringCustom(17, random.CharSetAlphaNumeric)
|
||||||
pid := os.Getpid() + rm
|
pid := os.Getpid() + rm
|
||||||
|
|
||||||
|
|
|
@ -180,7 +180,7 @@ func (s *Store) DeleteAccessTokenSession(ctx context.Context, signature string)
|
||||||
return s.revokeSessionBySignature(ctx, storage.OAuth2SessionTypeAccessToken, signature)
|
return s.revokeSessionBySignature(ctx, storage.OAuth2SessionTypeAccessToken, signature)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RevokeAccessToken revokes an access token as specified in: https://tools.ietf.org/html/rfc7009#section-2.1
|
// RevokeAccessToken revokes an access token as specified in: https://datatracker.ietf.org/doc/html/rfc7009#section-2.1
|
||||||
// If the token passed to the request is an access token, the server MAY revoke the respective refresh token as well.
|
// If the token passed to the request is an access token, the server MAY revoke the respective refresh token as well.
|
||||||
// This implements a portion of oauth2.TokenRevocationStorage.
|
// This implements a portion of oauth2.TokenRevocationStorage.
|
||||||
func (s *Store) RevokeAccessToken(ctx context.Context, requestID string) (err error) {
|
func (s *Store) RevokeAccessToken(ctx context.Context, requestID string) (err error) {
|
||||||
|
@ -205,7 +205,7 @@ func (s *Store) DeleteRefreshTokenSession(ctx context.Context, signature string)
|
||||||
return s.revokeSessionBySignature(ctx, storage.OAuth2SessionTypeRefreshToken, signature)
|
return s.revokeSessionBySignature(ctx, storage.OAuth2SessionTypeRefreshToken, signature)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RevokeRefreshToken revokes a refresh token as specified in: https://tools.ietf.org/html/rfc7009#section-2.1
|
// RevokeRefreshToken revokes a refresh token as specified in: https://datatracker.ietf.org/doc/html/rfc7009#section-2.1
|
||||||
// If the particular token is a refresh token and the authorization server supports the revocation of access tokens,
|
// If the particular token is a refresh token and the authorization server supports the revocation of access tokens,
|
||||||
// then the authorization server SHOULD also invalidate all access tokens based on the same authorization grant (see Implementation Note).
|
// then the authorization server SHOULD also invalidate all access tokens based on the same authorization grant (see Implementation Note).
|
||||||
// This implements a portion of oauth2.TokenRevocationStorage.
|
// This implements a portion of oauth2.TokenRevocationStorage.
|
||||||
|
@ -213,7 +213,7 @@ func (s *Store) RevokeRefreshToken(ctx context.Context, requestID string) (err e
|
||||||
return s.provider.DeactivateOAuth2SessionByRequestID(ctx, storage.OAuth2SessionTypeRefreshToken, requestID)
|
return s.provider.DeactivateOAuth2SessionByRequestID(ctx, storage.OAuth2SessionTypeRefreshToken, requestID)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RevokeRefreshTokenMaybeGracePeriod revokes an access token as specified in: https://tools.ietf.org/html/rfc7009#section-2.1
|
// RevokeRefreshTokenMaybeGracePeriod revokes an access token as specified in: https://datatracker.ietf.org/doc/html/rfc7009#section-2.1
|
||||||
// If the token passed to the request is an access token, the server MAY revoke the respective refresh token as well.
|
// If the token passed to the request is an access token, the server MAY revoke the respective refresh token as well.
|
||||||
// This implements a portion of oauth2.TokenRevocationStorage.
|
// This implements a portion of oauth2.TokenRevocationStorage.
|
||||||
func (s *Store) RevokeRefreshTokenMaybeGracePeriod(ctx context.Context, requestID string, signature string) (err error) {
|
func (s *Store) RevokeRefreshTokenMaybeGracePeriod(ctx context.Context, requestID string, signature string) (err error) {
|
||||||
|
|
|
@ -25,7 +25,7 @@ const (
|
||||||
CharSetSymbolic = "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~"
|
CharSetSymbolic = "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~"
|
||||||
|
|
||||||
// CharSetSymbolicRFC3986Unreserved are RFC3986 unreserved symbol characters.
|
// CharSetSymbolicRFC3986Unreserved are RFC3986 unreserved symbol characters.
|
||||||
// See https://www.rfc-editor.org/rfc/rfc3986#section-2.3.
|
// See https://datatracker.ietf.org/doc/html/rfc3986#section-2.3.
|
||||||
CharSetSymbolicRFC3986Unreserved = "-._~"
|
CharSetSymbolicRFC3986Unreserved = "-._~"
|
||||||
|
|
||||||
// CharSetAlphaNumeric are literally just valid alphanumeric printable ASCII chars.
|
// CharSetAlphaNumeric are literally just valid alphanumeric printable ASCII chars.
|
||||||
|
@ -35,7 +35,7 @@ const (
|
||||||
CharSetASCII = CharSetAlphabetic + CharSetNumeric + CharSetSymbolic
|
CharSetASCII = CharSetAlphabetic + CharSetNumeric + CharSetSymbolic
|
||||||
|
|
||||||
// CharSetRFC3986Unreserved are RFC3986 unreserved characters.
|
// CharSetRFC3986Unreserved are RFC3986 unreserved characters.
|
||||||
// See https://www.rfc-editor.org/rfc/rfc3986#section-2.3.
|
// See https://datatracker.ietf.org/doc/html/rfc3986#section-2.3.
|
||||||
CharSetRFC3986Unreserved = CharSetAlphabetic + CharSetNumeric + CharSetSymbolicRFC3986Unreserved
|
CharSetRFC3986Unreserved = CharSetAlphabetic + CharSetNumeric + CharSetSymbolicRFC3986Unreserved
|
||||||
|
|
||||||
// CharSetUnambiguousUpper are a set of unambiguous uppercase characters.
|
// CharSetUnambiguousUpper are a set of unambiguous uppercase characters.
|
||||||
|
|
|
@ -18,11 +18,7 @@ func (r *Cryptographical) Read(p []byte) (n int, err error) {
|
||||||
// BytesErr returns random data as bytes with the standard random.DefaultN length and can contain any byte values
|
// BytesErr returns random data as bytes with the standard random.DefaultN length and can contain any byte values
|
||||||
// (including unreadable byte values). If an error is returned from the random read this function returns it.
|
// (including unreadable byte values). If an error is returned from the random read this function returns it.
|
||||||
func (r *Cryptographical) BytesErr() (data []byte, err error) {
|
func (r *Cryptographical) BytesErr() (data []byte, err error) {
|
||||||
data = make([]byte, DefaultN)
|
return r.BytesCustomErr(0, nil)
|
||||||
|
|
||||||
_, err = rand.Read(data)
|
|
||||||
|
|
||||||
return data, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bytes returns random data as bytes with the standard random.DefaultN length and can contain any byte values
|
// Bytes returns random data as bytes with the standard random.DefaultN length and can contain any byte values
|
||||||
|
@ -49,8 +45,10 @@ func (r *Cryptographical) BytesCustomErr(n int, charset []byte) (data []byte, er
|
||||||
|
|
||||||
t := len(charset)
|
t := len(charset)
|
||||||
|
|
||||||
for i := 0; i < n; i++ {
|
if t > 0 {
|
||||||
data[i] = charset[data[i]%byte(t)]
|
for i := 0; i < n; i++ {
|
||||||
|
data[i] = charset[data[i]%byte(t)]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return data, nil
|
return data, nil
|
||||||
|
@ -81,6 +79,36 @@ func (r *Cryptographical) StringCustom(n int, characters string) (data string) {
|
||||||
return string(r.BytesCustom(n, []byte(characters)))
|
return string(r.BytesCustom(n, []byte(characters)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IntnErr returns a random int error combination with a maximum of n.
|
||||||
|
func (r *Cryptographical) IntnErr(n int) (value int, err error) {
|
||||||
|
if n <= 0 {
|
||||||
|
return 0, fmt.Errorf("n must be more than 0")
|
||||||
|
}
|
||||||
|
|
||||||
|
max := big.NewInt(int64(n))
|
||||||
|
|
||||||
|
var result *big.Int
|
||||||
|
|
||||||
|
if result, err = r.IntErr(max); err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
value = int(result.Int64())
|
||||||
|
|
||||||
|
if value < 0 {
|
||||||
|
return 0, fmt.Errorf("generated number is too big for int")
|
||||||
|
}
|
||||||
|
|
||||||
|
return value, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Intn returns a random int with a maximum of n.
|
||||||
|
func (r *Cryptographical) Intn(n int) (value int) {
|
||||||
|
value, _ = r.IntnErr(n)
|
||||||
|
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
// IntErr returns a random *big.Int error combination with a maximum of max.
|
// IntErr returns a random *big.Int error combination with a maximum of max.
|
||||||
func (r *Cryptographical) IntErr(max *big.Int) (value *big.Int, err error) {
|
func (r *Cryptographical) IntErr(max *big.Int) (value *big.Int, err error) {
|
||||||
if max == nil {
|
if max == nil {
|
||||||
|
@ -105,32 +133,8 @@ func (r *Cryptographical) Int(max *big.Int) (value *big.Int) {
|
||||||
return value
|
return value
|
||||||
}
|
}
|
||||||
|
|
||||||
// IntegerErr returns a random int error combination with a maximum of n.
|
// Prime returns a number of the given bit length that is prime with high probability. Prime will return error for any
|
||||||
func (r *Cryptographical) IntegerErr(n int) (value int, err error) {
|
// error returned by rand.Read or if bits < 2.
|
||||||
if n <= 0 {
|
func (r *Cryptographical) Prime(bits int) (prime *big.Int, err error) {
|
||||||
return 0, fmt.Errorf("n must be more than 0")
|
return rand.Prime(rand.Reader, bits)
|
||||||
}
|
|
||||||
|
|
||||||
max := big.NewInt(int64(n))
|
|
||||||
|
|
||||||
var result *big.Int
|
|
||||||
|
|
||||||
if result, err = r.IntErr(max); err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
value = int(result.Int64())
|
|
||||||
|
|
||||||
if value < 0 {
|
|
||||||
return 0, fmt.Errorf("generated number is too big for int")
|
|
||||||
}
|
|
||||||
|
|
||||||
return value, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Integer returns a random int with a maximum of n.
|
|
||||||
func (r *Cryptographical) Integer(n int) (value int) {
|
|
||||||
value, _ = r.IntegerErr(n)
|
|
||||||
|
|
||||||
return value
|
|
||||||
}
|
}
|
|
@ -1,26 +1,36 @@
|
||||||
package random
|
package random
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
crand "crypto/rand"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewMathematical runs rand.Seed with the current time and returns a random.Provider, specifically *random.Mathematical.
|
// NewMathematical runs rand.Seed with the current time and returns a random.Provider, specifically *random.Mathematical.
|
||||||
func NewMathematical() *Mathematical {
|
func NewMathematical() *Mathematical {
|
||||||
rand.Seed(time.Now().UnixNano())
|
return &Mathematical{
|
||||||
|
rand: rand.New(rand.NewSource(time.Now().UnixNano())), //nolint:gosec
|
||||||
return &Mathematical{}
|
lock: &sync.Mutex{},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mathematical is the random.Provider which uses math/rand and is COMPLETELY UNSAFE FOR PRODUCTION IN MOST SITUATIONS.
|
// Mathematical is the random.Provider which uses math/rand and is COMPLETELY UNSAFE FOR PRODUCTION IN MOST SITUATIONS.
|
||||||
// Use random.Cryptographical instead.
|
// Use random.Cryptographical instead.
|
||||||
type Mathematical struct{}
|
type Mathematical struct {
|
||||||
|
rand *rand.Rand
|
||||||
|
lock *sync.Mutex
|
||||||
|
}
|
||||||
|
|
||||||
// Read implements the io.Reader interface.
|
// Read implements the io.Reader interface.
|
||||||
func (r *Mathematical) Read(p []byte) (n int, err error) {
|
func (r *Mathematical) Read(p []byte) (n int, err error) {
|
||||||
return rand.Read(p) //nolint:gosec
|
r.lock.Lock()
|
||||||
|
|
||||||
|
defer r.lock.Unlock()
|
||||||
|
|
||||||
|
return r.rand.Read(p)
|
||||||
}
|
}
|
||||||
|
|
||||||
// BytesErr returns random data as bytes with the standard random.DefaultN length and can contain any byte values
|
// BytesErr returns random data as bytes with the standard random.DefaultN length and can contain any byte values
|
||||||
|
@ -28,7 +38,7 @@ func (r *Mathematical) Read(p []byte) (n int, err error) {
|
||||||
func (r *Mathematical) BytesErr() (data []byte, err error) {
|
func (r *Mathematical) BytesErr() (data []byte, err error) {
|
||||||
data = make([]byte, DefaultN)
|
data = make([]byte, DefaultN)
|
||||||
|
|
||||||
if _, err = rand.Read(data); err != nil { //nolint:gosec
|
if _, err = r.Read(data); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,7 +63,7 @@ func (r *Mathematical) BytesCustomErr(n int, charset []byte) (data []byte, err e
|
||||||
|
|
||||||
data = make([]byte, n)
|
data = make([]byte, n)
|
||||||
|
|
||||||
if _, err = rand.Read(data); err != nil { //nolint:gosec
|
if _, err = r.Read(data); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,17 +101,18 @@ func (r *Mathematical) StringCustom(n int, characters string) (data string) {
|
||||||
return string(r.BytesCustom(n, []byte(characters)))
|
return string(r.BytesCustom(n, []byte(characters)))
|
||||||
}
|
}
|
||||||
|
|
||||||
// IntErr returns a random *big.Int error combination with a maximum of max.
|
// Intn returns a random int with a maximum of n.
|
||||||
func (r *Mathematical) IntErr(max *big.Int) (value *big.Int, err error) {
|
func (r *Mathematical) Intn(n int) int {
|
||||||
if max == nil {
|
r.lock.Lock()
|
||||||
return nil, fmt.Errorf("max is required")
|
|
||||||
}
|
|
||||||
|
|
||||||
if max.Sign() <= 0 {
|
defer r.lock.Unlock()
|
||||||
return nil, fmt.Errorf("max must be 1 or more")
|
|
||||||
}
|
|
||||||
|
|
||||||
return big.NewInt(int64(rand.Intn(max.Sign()))), nil //nolint:gosec
|
return r.rand.Intn(n)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IntnErr returns a random int error combination with a maximum of n.
|
||||||
|
func (r *Mathematical) IntnErr(n int) (output int, err error) {
|
||||||
|
return r.Intn(n), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Int returns a random *big.Int with a maximum of max.
|
// Int returns a random *big.Int with a maximum of max.
|
||||||
|
@ -115,12 +126,25 @@ func (r *Mathematical) Int(max *big.Int) (value *big.Int) {
|
||||||
return value
|
return value
|
||||||
}
|
}
|
||||||
|
|
||||||
// IntegerErr returns a random int error combination with a maximum of n.
|
// IntErr returns a random *big.Int error combination with a maximum of max.
|
||||||
func (r *Mathematical) IntegerErr(n int) (output int, err error) {
|
func (r *Mathematical) IntErr(max *big.Int) (value *big.Int, err error) {
|
||||||
return r.Integer(n), nil
|
if max == nil {
|
||||||
|
return nil, fmt.Errorf("max is required")
|
||||||
|
}
|
||||||
|
|
||||||
|
if max.Sign() <= 0 {
|
||||||
|
return nil, fmt.Errorf("max must be 1 or more")
|
||||||
|
}
|
||||||
|
|
||||||
|
r.lock.Lock()
|
||||||
|
|
||||||
|
defer r.lock.Unlock()
|
||||||
|
|
||||||
|
return big.NewInt(int64(r.Intn(max.Sign()))), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Integer returns a random int with a maximum of n.
|
// Prime returns a number of the given bit length that is prime with high probability. Prime will return error for any
|
||||||
func (r *Mathematical) Integer(n int) int {
|
// error returned by rand.Read or if bits < 2.
|
||||||
return rand.Intn(n) //nolint:gosec
|
func (r *Mathematical) Prime(bits int) (prime *big.Int, err error) {
|
||||||
|
return crand.Prime(r, bits)
|
||||||
}
|
}
|
|
@ -32,15 +32,19 @@ type Provider interface {
|
||||||
// StringCustom is an overload of GenerateCustom which takes a characters string and returns a string.
|
// StringCustom is an overload of GenerateCustom which takes a characters string and returns a string.
|
||||||
StringCustom(n int, characters string) (data string)
|
StringCustom(n int, characters string) (data string)
|
||||||
|
|
||||||
|
// Intn returns a random integer with a maximum of n.
|
||||||
|
Intn(n int) (value int)
|
||||||
|
|
||||||
|
// IntnErr returns a random int error combination with a maximum of n.
|
||||||
|
IntnErr(n int) (value int, err error)
|
||||||
|
|
||||||
// IntErr returns a random *big.Int error combination with a maximum of max.
|
// IntErr returns a random *big.Int error combination with a maximum of max.
|
||||||
IntErr(max *big.Int) (value *big.Int, err error)
|
IntErr(max *big.Int) (value *big.Int, err error)
|
||||||
|
|
||||||
// Int returns a random *big.Int with a maximum of max.
|
// Int returns a random *big.Int with a maximum of max.
|
||||||
Int(max *big.Int) (value *big.Int)
|
Int(max *big.Int) (value *big.Int)
|
||||||
|
|
||||||
// IntegerErr returns a random int error combination with a maximum of n.
|
// Prime returns a number of the given bit length that is prime with high probability. Prime will return error for any
|
||||||
IntegerErr(n int) (value int, err error)
|
// error returned by rand.Read or if bits < 2.
|
||||||
|
Prime(bits int) (prime *big.Int, err error)
|
||||||
// Integer returns a random integer with a maximum of n.
|
|
||||||
Integer(n int) (value int)
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,8 +10,8 @@ default_redirection_url: https://home.example.com:8080/
|
||||||
server:
|
server:
|
||||||
port: 9091
|
port: 9091
|
||||||
tls:
|
tls:
|
||||||
certificate: /config/ssl/cert.pem
|
certificate: /pki/public.backend.crt
|
||||||
key: /config/ssl/key.pem
|
key: /pki/private.backend.pem
|
||||||
|
|
||||||
log:
|
log:
|
||||||
level: debug
|
level: debug
|
||||||
|
|
|
@ -4,5 +4,5 @@ services:
|
||||||
authelia-backend:
|
authelia-backend:
|
||||||
volumes:
|
volumes:
|
||||||
- './ActiveDirectory/configuration.yml:/config/configuration.yml:ro'
|
- './ActiveDirectory/configuration.yml:/config/configuration.yml:ro'
|
||||||
- './common/ssl:/config/ssl:ro'
|
- './common/pki:/pki:ro'
|
||||||
...
|
...
|
||||||
|
|
|
@ -6,8 +6,8 @@
|
||||||
server:
|
server:
|
||||||
port: 9091
|
port: 9091
|
||||||
tls:
|
tls:
|
||||||
certificate: /config/ssl/cert.pem
|
certificate: /pki/public.backend.crt
|
||||||
key: /config/ssl/key.pem
|
key: /pki/private.backend.pem
|
||||||
|
|
||||||
log:
|
log:
|
||||||
level: debug
|
level: debug
|
||||||
|
|
|
@ -5,5 +5,5 @@ services:
|
||||||
volumes:
|
volumes:
|
||||||
- './BypassAll/configuration.yml:/config/configuration.yml:ro'
|
- './BypassAll/configuration.yml:/config/configuration.yml:ro'
|
||||||
- './BypassAll/users.yml:/config/users.yml'
|
- './BypassAll/users.yml:/config/users.yml'
|
||||||
- './common/ssl:/config/ssl:ro'
|
- './common/pki:/pki:ro'
|
||||||
...
|
...
|
||||||
|
|
|
@ -6,8 +6,8 @@
|
||||||
server:
|
server:
|
||||||
port: 9091
|
port: 9091
|
||||||
tls:
|
tls:
|
||||||
certificate: /config/ssl/cert.pem
|
certificate: /pki/public.backend.crt
|
||||||
key: /config/ssl/key.pem
|
key: /pki/private.backend.pem
|
||||||
|
|
||||||
log:
|
log:
|
||||||
level: debug
|
level: debug
|
||||||
|
|
|
@ -6,7 +6,7 @@ services:
|
||||||
- './CLI/configuration.yml:/config/configuration.yml:ro'
|
- './CLI/configuration.yml:/config/configuration.yml:ro'
|
||||||
- './CLI/storage.yml:/config/configuration.storage.yml:ro'
|
- './CLI/storage.yml:/config/configuration.storage.yml:ro'
|
||||||
- './CLI/users.yml:/config/users.yml'
|
- './CLI/users.yml:/config/users.yml'
|
||||||
- './common/ssl:/config/ssl:ro'
|
- './common/pki:/pki:ro'
|
||||||
- '/tmp:/tmp'
|
- '/tmp:/tmp'
|
||||||
user: ${USER_ID}:${GROUP_ID}
|
user: ${USER_ID}:${GROUP_ID}
|
||||||
...
|
...
|
||||||
|
|
|
@ -9,8 +9,8 @@ server:
|
||||||
port: 9091
|
port: 9091
|
||||||
asset_path: /config/assets/
|
asset_path: /config/assets/
|
||||||
tls:
|
tls:
|
||||||
certificate: /config/ssl/cert.pem
|
certificate: /pki/public.backend.crt
|
||||||
key: /config/ssl/key.pem
|
key: /pki/private.backend.pem
|
||||||
endpoints:
|
endpoints:
|
||||||
authz:
|
authz:
|
||||||
caddy:
|
caddy:
|
||||||
|
|
|
@ -5,5 +5,5 @@ services:
|
||||||
volumes:
|
volumes:
|
||||||
- './Caddy/configuration.yml:/config/configuration.yml:ro'
|
- './Caddy/configuration.yml:/config/configuration.yml:ro'
|
||||||
- './Caddy/users.yml:/config/users.yml'
|
- './Caddy/users.yml:/config/users.yml'
|
||||||
- './common/ssl:/config/ssl:ro'
|
- './common/pki:/pki:ro'
|
||||||
...
|
...
|
||||||
|
|
|
@ -9,8 +9,8 @@ default_redirection_url: https://home.example.com:8080/
|
||||||
server:
|
server:
|
||||||
port: 9091
|
port: 9091
|
||||||
tls:
|
tls:
|
||||||
certificate: /config/ssl/cert.pem
|
certificate: /pki/public.backend.crt
|
||||||
key: /config/ssl/key.pem
|
key: /pki/private.backend.pem
|
||||||
|
|
||||||
log:
|
log:
|
||||||
level: debug
|
level: debug
|
||||||
|
|
|
@ -5,5 +5,5 @@ services:
|
||||||
volumes:
|
volumes:
|
||||||
- './Docker/configuration.yml:/config/configuration.yml:ro'
|
- './Docker/configuration.yml:/config/configuration.yml:ro'
|
||||||
- './Docker/users.yml:/config/users.yml'
|
- './Docker/users.yml:/config/users.yml'
|
||||||
- './common/ssl:/config/ssl:ro'
|
- './common/pki:/pki:ro'
|
||||||
...
|
...
|
||||||
|
|
|
@ -9,8 +9,8 @@ default_redirection_url: https://home.example.com:8080/
|
||||||
server:
|
server:
|
||||||
port: 9091
|
port: 9091
|
||||||
tls:
|
tls:
|
||||||
certificate: /config/ssl/cert.pem
|
certificate: /pki/public.backend.crt
|
||||||
key: /config/ssl/key.pem
|
key: /pki/private.backend.pem
|
||||||
|
|
||||||
log:
|
log:
|
||||||
level: trace
|
level: trace
|
||||||
|
|
|
@ -5,7 +5,7 @@ services:
|
||||||
volumes:
|
volumes:
|
||||||
- './DuoPush/configuration.yml:/config/configuration.yml:ro'
|
- './DuoPush/configuration.yml:/config/configuration.yml:ro'
|
||||||
- './DuoPush/users.yml:/config/users.yml'
|
- './DuoPush/users.yml:/config/users.yml'
|
||||||
- './common/ssl:/config/ssl:ro'
|
- './common/pki:/pki:ro'
|
||||||
- '/tmp:/tmp'
|
- '/tmp:/tmp'
|
||||||
user: ${USER_ID}:${GROUP_ID}
|
user: ${USER_ID}:${GROUP_ID}
|
||||||
...
|
...
|
||||||
|
|
|
@ -9,8 +9,8 @@ server:
|
||||||
port: 9091
|
port: 9091
|
||||||
asset_path: /config/assets/
|
asset_path: /config/assets/
|
||||||
tls:
|
tls:
|
||||||
certificate: /config/ssl/cert.pem
|
certificate: /pki/public.backend.crt
|
||||||
key: /config/ssl/key.pem
|
key: /pki/private.backend.pem
|
||||||
endpoints:
|
endpoints:
|
||||||
authz:
|
authz:
|
||||||
ext-authz:
|
ext-authz:
|
||||||
|
|
|
@ -5,5 +5,5 @@ services:
|
||||||
volumes:
|
volumes:
|
||||||
- './Envoy/configuration.yml:/config/configuration.yml:ro'
|
- './Envoy/configuration.yml:/config/configuration.yml:ro'
|
||||||
- './Envoy/users.yml:/config/users.yml'
|
- './Envoy/users.yml:/config/users.yml'
|
||||||
- './common/ssl:/config/ssl:ro'
|
- './common/pki:/pki:ro'
|
||||||
...
|
...
|
||||||
|
|
|
@ -8,8 +8,8 @@ jwt_secret: unsecure_secret
|
||||||
server:
|
server:
|
||||||
port: 9091
|
port: 9091
|
||||||
tls:
|
tls:
|
||||||
certificate: /config/ssl/cert.pem
|
certificate: /pki/public.backend.crt
|
||||||
key: /config/ssl/key.pem
|
key: /pki/private.backend.pem
|
||||||
|
|
||||||
log:
|
log:
|
||||||
level: debug
|
level: debug
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue