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

# Conflicts:
#	api/openapi.yml
pull/4806/head
James Elliott 2022-12-17 15:47:34 +11:00
commit a186dca3bf
No known key found for this signature in database
GPG Key ID: 0F1C4A096E857E49
177 changed files with 7196 additions and 3914 deletions

View File

@ -3,7 +3,7 @@
set +u
declare -A BUILDS=(["linux"]="amd64 arm arm64 amd64-musl arm-musl arm64-musl" ["freebsd"]="amd64")
DOCKER_IMAGE=authelia/authelia
DOCKER_IMAGE=authelia:dist
if [[ "${BUILDKITE_LABEL}" == ":hammer_and_wrench: Unit Test" ]]; then
if [[ ! "${BUILDKITE_BRANCH}" =~ ^renovate/ ]]; then
@ -35,4 +35,4 @@ if [[ "${BUILDKITE_LABEL}" =~ ":debian: Build Package" ]]; then
for f in *.deb; do mv "$f" "$(echo "$f" | sed s/${VERSION}-1_//)"; done
fi
sha256sum "authelia_${PACKAGE}.deb" > "authelia_${PACKAGE}.deb.sha256"
fi
fi

View File

@ -17,7 +17,7 @@ if [[ "${BUILDKITE_LABEL}" == ":service_dog: Linting" ]]; then
fi
if [[ "${BUILDKITE_LABEL}" == ":docker: Build Image [coverage]" ]]; then
cp -R /buildkite/.pnpm-store .
cp -R /buildkite/.local .
fi
if [[ "${BUILDKITE_STEP_KEY}" =~ build-deb-package-(arm64|armhf) && "${BUILDKITE_AGENT_NAME}" =~ sauron* ]]; then
@ -30,10 +30,13 @@ fi
if [[ "${BUILDKITE_LABEL}" =~ ":selenium:" ]]; then
DEFAULT_ARCH=coverage
echo "--- :docker: Extract, load and tag build container"
echo "--- :docker: Extract and load build container"
buildkite-agent artifact download "authelia-image-${DEFAULT_ARCH}*" .
zstdcat "authelia-image-${DEFAULT_ARCH}.tar.zst" | docker load
docker tag authelia/authelia authelia:dist
if [[ "${SUITE}" == "Kubernetes" ]]; then
zstd -d authelia-image-coverage.tar.zst --stdout > ./internal/suites/example/kube/authelia-image-${DEFAULT_ARCH}.tar
else
zstdcat "authelia-image-${DEFAULT_ARCH}.tar.zst" | docker load
fi
if [[ "${BUILD_DUO}" == "true" ]] && [[ "${SUITE}" == "DuoPush" ]]; then
CONTAINER="integration-duo"

View File

@ -7,7 +7,11 @@ trim_trailing_whitespace = true
end_of_line = lf
insert_final_newline = true
[{.buildkite/hooks/**,*.sh,*.yml,*.yaml}]
[*.{sh,yml,yaml}]
indent_style = space
indent_size = 2
[.buildkite/hooks/**]
indent_style = space
indent_size = 2

View File

@ -26,6 +26,7 @@ body:
description: What version(s) of Authelia can you reproduce this bug on?
multiple: true
options:
- v4.37.3
- v4.37.2
- v4.37.1
- v4.37.0

39
.gitignore vendored
View File

@ -1,50 +1,27 @@
# IDE user configuration
.idea/
.vscode/
# NodeJs modules
# Nodejs modules
.pnpm-store/
node_modules/
# npm debug logs
npm-debug.log*
# Coverage reports
coverage/
.nyc_output/
coverage.txt
.vscode/
*.swp
*~
# Directory used by example
/notifications/
# VSCode user configuration
.vscode/
# Generated by TypeScript compiler
dist/
.nyc_output/
*.tgz
# Specific files
/configuration.yml
/config.yml
/config.test.yml
internal/suites/example/ldap/private.ldif
Configuration.schema.json
.suite
.kube
.idea
authelia-image-dev.tar
.authelia-interrupt
qemu-*-static
public_html.gen.go
authelia
/authelia
__debug_bin

View File

@ -1,4 +1,5 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [
"config:base",
":semanticCommitTypeAll(build)",
@ -14,12 +15,15 @@
"workarounds:all"
],
"enabledManagers": [
"bundler",
"docker-compose",
"dockerfile",
"gomod",
"kubernetes",
"npm"
],
"kubernetes": {
"fileMatch": ["kube/.+\\.yml$"],
},
"labels": [
"dependencies"
],
@ -47,6 +51,14 @@
"go"
]
},
{
"datasources": [
"kubernetes"
],
"addLabels": [
"kubernetes"
]
},
{
"datasources": [
"npm"

View File

@ -1,6 +1,13 @@
---
extends: default
locale: en_US.UTF-8
yaml-files:
- '*.yaml'
- '*.yml'
- '.yamllint'
ignore: |
docs/pnpm-lock.yaml
internal/configuration/test_resources/config_bad_quoting.yml

View File

@ -2,7 +2,7 @@
Anybody willing to contribute to the project either with code, documentation, security reviews or whatever, are very
welcome to create or review pull requests and take part in discussions in any of our public
[chat rooms](./README.md#contact-options).
[chat rooms](README.md#contact-options).
It's also possible to contribute financially in order to support the community.
@ -42,4 +42,4 @@ Read more about this in the [GitHub docs, Re-requesting a review](https://docs.g
Sometimes the codebase can be a challenge to navigate, especially for a first-time contributor. We don't want you
spending an hour trying to work out something that would take us only a minute to explain.
If you'd like some help getting started we have several [contact options](./README.md#contact-options) available.
If you'd like some help getting started we have several [contact options](README.md#contact-options) available.

View File

@ -5,7 +5,7 @@ FROM node:19-alpine AS builder-frontend
WORKDIR /node/src/app
COPY .pnpm-store /root/.pnpm-store
COPY .local /root/.local
COPY web ./
# Install the dependencies and build
@ -15,7 +15,7 @@ RUN yarn global add pnpm && \
# =======================================
# ===== Build image for the backend =====
# =======================================
FROM golang:1.19.3-alpine AS builder-backend
FROM golang:1.19.4-alpine AS builder-backend
WORKDIR /go/src/app

View File

@ -20,4 +20,4 @@ bootstrap.sh
# Overrides
!.healthcheck.env
!.pnpm-store
!.local

View File

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

View File

@ -184,7 +184,7 @@ Internet (your reverse proxies are) however, it's still the control plane for yo
## Contribute
If you want to contribute to Authelia, please read our [contribution guidelines](./CONTRIBUTING.md).
If you want to contribute to Authelia, please read our [contribution guidelines](CONTRIBUTING.md).
Authelia exists thanks to all the people who contribute so don't be shy, come chat with us on either [Matrix](#matrix)
or [Discord](#discord) and start contributing too.
@ -379,7 +379,7 @@ Companies contributing to Authelia via Open Collective will have a special menti
## License
**Authelia** is **licensed** under the **[Apache 2.0]** license. The terms of the license are detailed in
[LICENSE](./LICENSE).
[LICENSE](LICENSE).
[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fauthelia%2Fauthelia.svg?type=large)](https://app.fossa.com/projects/git%2Bgithub.com%2Fauthelia%2Fauthelia?ref=badge_large)

View File

@ -19,14 +19,14 @@ For more information about [security](https://www.authelia.com/information/secur
## Contact Options
Several [contact options](./README.md#contact-options) exist, it's important to make sure you contact the maintainers
privately which is described in each available contact method. The methods include our [security email](./README.md#security),
[Matrix](./README.md#matrix), and [Discord](./README.md#discord).
Several [contact options](README.md#contact-options) exist, it's important to make sure you contact the maintainers
privately which is described in each available contact method. The methods include our [security email](README.md#security),
[Matrix](README.md#matrix), and [Discord](README.md#discord).
## Credit
Users who report bugs will optionally be credited for the discovery. Both in the [security advisory] and in our
[all contributors](./README.md#contribute) configuration/documentation.
[all contributors](README.md#contribute) configuration/documentation.
## Process

File diff suppressed because it is too large Load Diff

View File

@ -87,12 +87,19 @@ var hostEntries = []HostEntry{
{Domain: "mail.example.com", IP: "192.168.240.100"},
{Domain: "duo.example.com", IP: "192.168.240.100"},
// For Traefik suite.
{Domain: "traefik.example.com", IP: "192.168.240.100"},
// For HAProxy suite.
{Domain: "haproxy.example.com", IP: "192.168.240.100"},
// Kubernetes dashboard.
{Domain: "kubernetes.example.com", IP: "192.168.240.100"},
// OIDC tester app.
{Domain: "oidc.example.com", IP: "192.168.240.100"},
{Domain: "oidc-public.example.com", IP: "192.168.240.100"},
// For Traefik suite.
{Domain: "traefik.example.com", IP: "192.168.240.100"},
// For testing network ACLs.
{Domain: "proxy-client1.example.com", IP: "192.168.240.201"},
{Domain: "proxy-client2.example.com", IP: "192.168.240.202"},
@ -107,12 +114,6 @@ var hostEntries = []HostEntry{
{Domain: "redis-sentinel-0.example.com", IP: "192.168.240.120"},
{Domain: "redis-sentinel-1.example.com", IP: "192.168.240.121"},
{Domain: "redis-sentinel-2.example.com", IP: "192.168.240.122"},
// Kubernetes dashboard.
{Domain: "kubernetes.example.com", IP: "192.168.240.110"},
// OIDC tester app.
{Domain: "oidc.example.com", IP: "192.168.240.100"},
{Domain: "oidc-public.example.com", IP: "192.168.240.100"},
}
func runCommand(cmd string, args ...string) {
@ -151,8 +152,8 @@ func createTemporaryDirectory() {
func createPNPMDirectory() {
home := os.Getenv("HOME")
if home != "" {
bootstrapPrintln("Creating ", home+"/.pnpm-store")
err := os.MkdirAll(home+"/.pnpm-store", 0755)
bootstrapPrintln("Creating ", home+"/.local/share/pnpm/store")
err := os.MkdirAll(home+"/.local/share/pnpm/store", 0755)
if err != nil {
panic(err)
@ -161,7 +162,7 @@ func createPNPMDirectory() {
}
func pnpmInstall() {
bootstrapPrintln("Installing web dependences ")
bootstrapPrintln("Installing web dependencies ")
cwd, err := os.Getwd()
if err != nil {

View File

@ -167,14 +167,14 @@ section [here](../prologue/common.md#tls-configuration).
Sets the base distinguished name container for all LDAP queries. If your LDAP domain is example.com this is usually
`DC=example,DC=com`, however you can fine tune this to be more specific for example to only include objects inside the
authelia OU: `OU=authelia,DC=example,DC=com`. This is prefixed with the [additional_users_dn](#additional_users_dn) for
user searches and [additional_groups_dn](#additional_groups_dn) for groups searches.
authelia OU: `OU=authelia,DC=example,DC=com`. This is prefixed with the [additional_users_dn](#additionalusersdn) for
user searches and [additional_groups_dn](#additionalgroupsdn) for groups searches.
### additional_users_dn
{{< confkey type="string" required="no" >}}
Additional LDAP path to append to the [base_dn](#base_dn) when searching for users. Useful if you want to restrict
Additional LDAP path to append to the [base_dn](#basedn) when searching for users. Useful if you want to restrict
exactly which OU to get users from for either security or performance reasons. For example setting it to
`OU=users,OU=people` with a base_dn set to `DC=example,DC=com` will mean user searches will occur in
`OU=users,OU=people,DC=example,DC=com`.
@ -184,28 +184,31 @@ exactly which OU to get users from for either security or performance reasons. F
{{< confkey type="string" required="situational" >}}
*__Note:__ This option is technically required however the [implementation](#implementation) option can implicitly set a
default negating this requirement. Refer to the [filter defaults](#filter-defaults) for more information.*
default negating this requirement. Refer to the [filter defaults](../../reference/guides/ldap.md#filter-defaults) for
more information.*
The LDAP filter to narrow down which users are valid. This is important to set correctly as to exclude disabled users.
The default value is dependent on the [implementation](#implementation), refer to the
[attribute defaults](#attribute-defaults) for more information.
[attribute defaults](../../reference/guides/ldap.md#attribute-defaults) for more information.
### username_attribute
{{< confkey type="string" required="situational" >}}
*__Note:__ This option is technically required however the [implementation](#implementation) option can implicitly set a
default negating this requirement. Refer to the [attribute defaults](#attribute-defaults) for more information.*
default negating this requirement. Refer to the [attribute defaults](../../reference/guides/ldap.md#attribute-defaults)
for more information.*
The LDAP attribute that maps to the username in *Authelia*. This must contain the `{username_attribute}`
[placeholder](#users-filter-replacements).
[placeholder](../../reference/guides/ldap.md#users-filter-replacements).
### mail_attribute
{{< confkey type="string" required="situational" >}}
*__Note:__ This option is technically required however the [implementation](#implementation) option can implicitly set a
default negating this requirement. Refer to the [attribute defaults](#attribute-defaults) for more information.*
default negating this requirement. Refer to the [attribute defaults](../../reference/guides/ldap.md#attribute-defaults)
for more information.*
The attribute to retrieve which contains the users email addresses. This is important for the device registration and
password reset processes. The user must have an email address in order for Authelia to perform identity verification
@ -294,7 +297,7 @@ characters and the user password is changed to this value.
## Refresh Interval
It's recommended you either use the default [refresh interval](./introduction.md#refresh_interval) or configure this to
It's recommended you either use the default [refresh interval](introduction.md#refreshinterval) or configure this to
a value low enough to refresh the user groups and status (deleted, disabled, etc) to adequately secure your environment.
## Important notes
@ -311,6 +314,6 @@ for your users.
- [LDAP Reference Guide](../../reference/guides/ldap.md)
[username attribute]: #username_attribute
[username attribute]: #usernameattribute
[TechNet wiki]: https://social.technet.microsoft.com/wiki/contents/articles/5392.active-directory-ldap-syntax-filters.aspx
[RFC2307]: https://www.rfc-editor.org/rfc/rfc2307.html

View File

@ -157,8 +157,8 @@ The HMAC secret used to sign the [JWT]'s. The provided string is hashed to a SHA
purpose of meeting the required format.
It's __strongly recommended__ this is a
[Random Alphanumeric String](../../reference/guides/generating-secure-values.md#generating-a-random-alphanumeric-string) with 64 or more
characters.
[Random Alphanumeric String](../../reference/guides/generating-secure-values.md#generating-a-random-alphanumeric-string)
with 64 or more characters.
### issuer_certificate_chain
@ -173,7 +173,7 @@ as per [RFC7517].
[x5c]: https://www.rfc-editor.org/rfc/rfc7517#section-4.7
[x5t]: https://www.rfc-editor.org/rfc/rfc7517#section-4.8
The first certificate in the chain must have the public key for the [issuer_private_key](#issuer_private_key), 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 immediately following it if present.
@ -185,14 +185,15 @@ certificate immediately following it if present.
especially for containerized deployments.*
The private key used to sign/encrypt the [OpenID Connect] issued [JWT]'s. The key must be generated by the administrator
and can be done by following the [Generating an RSA Keypair](../../reference/guides/generating-secure-values.md#generating-an-rsa-keypair) guide.
and can be done by following the
[Generating an RSA Keypair](../../reference/guides/generating-secure-values.md#generating-an-rsa-keypair) guide.
The private key *__MUST__*:
* Be a PEM block encoded in the DER base64 format ([RFC4648]).
* Be an RSA Key.
* Have a key size of at least 2048 bits.
If the [issuer_certificate_chain](#issuer_certificate_chain) is provided the private key must include matching public
If the [issuer_certificate_chain](#issuercertificatechain) is provided the private key must include matching public
key data for the first certificate in the chain.
### access_token_lifespan
@ -302,7 +303,7 @@ you must configure this option manually if you want http endpoints to be permitt
Origins must only have the scheme, hostname and port, they may not have a trailing slash or path.
In addition to an Origin URI, you may specify the wildcard origin in the allowed_origins. It MUST be specified by itself
and the [allowed_origins_from_client_redirect_uris](#allowed_origins_from_client_redirect_uris) MUST NOT be enabled. The
and the [allowed_origins_from_client_redirect_uris](#allowedoriginsfromclientredirecturis) MUST NOT be enabled. The
wildcard origin is denoted as `*`. Examples:
```yaml
@ -422,7 +423,7 @@ Configures the consent mode. The following table describes the different modes:
| 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. |
| pre-configured | Allows the end-user to remember their consent for the [pre_configured_consent_duration]. |
[pre_configured_consent_duration]: #pre_configured_consent_duration
[pre_configured_consent_duration]: #preconfiguredconsentduration
#### pre_configured_consent_duration
@ -439,7 +440,7 @@ The period of time dictates how long a users choice to remember the pre-configur
Pre-configured consents are only valid if the subject, client id are exactly the same and the requested scopes/audience
match exactly with the granted scopes/audience.
[consent_mode]: #consent_mode
[consent_mode]: #consentmode
#### audience

View File

@ -27,7 +27,7 @@ likely result in an error or even worse misconfiguration.
### Kubernetes
Please see the
[Kubernetes Integration: Enable Service Links](../../integration/kubernetes/introduction/index.md#enable-service-links)
[Kubernetes Integration: Enable Service Links](../../integration/kubernetes/introduction.md#enable-service-links)
documentation for specific requirements for using *Authelia* with Kubernetes.
## Mapping

View File

@ -55,15 +55,15 @@ other configuration using the environment but instead of loading a file the valu
{{% table-config-keys secrets="true" %}}
[server.tls.key]: ../miscellaneous/server.md#key
[jwt_secret]: ../miscellaneous/introduction.md#jwt_secret
[duo_api.integration_key]: ../second-factor/duo.md#integration_key
[duo_api.secret_key]: ../second-factor/duo.md#secret_key
[jwt_secret]: ../miscellaneous/introduction.md#jwtsecret
[duo_api.integration_key]: ../second-factor/duo.md#integrationkey
[duo_api.secret_key]: ../second-factor/duo.md#secretkey
[session.secret]: ../session/introduction.md#secret
[session.redis.password]: ../session/redis.md#password
[session.redis.tls.certificate_chain]: ../session/redis.md#tls
[session.redis.tls.private_key]: ../session/redis.md#tls
[session.redis.high_availability.sentinel_password]: ../session/redis.md#sentinel_password
[storage.encryption_key]: ../storage/introduction.md#encryption_key
[session.redis.high_availability.sentinel_password]: ../session/redis.md#sentinelpassword
[storage.encryption_key]: ../storage/introduction.md#encryptionkey
[storage.mysql.password]: ../storage/mysql.md#password
[storage.mysql.tls.certificate_chain]: ../storage/mysql.md#tls
[storage.mysql.tls.private_key]: ../storage/mysql.md#tls
@ -77,9 +77,9 @@ other configuration using the environment but instead of loading a file the valu
[authentication_backend.ldap.password]: ../first-factor/ldap.md#password
[authentication_backend.ldap.tls.certificate_chain]: ../first-factor/ldap.md#tls
[authentication_backend.ldap.tls.private_key]: ../first-factor/ldap.md#tls
[identity_providers.oidc.issuer_certificate_chain]: ../identity-providers/open-id-connect.md#issuer_certificate_chain
[identity_providers.oidc.issuer_private_key]: ../identity-providers/open-id-connect.md#issuer_private_key
[identity_providers.oidc.hmac_secret]: ../identity-providers/open-id-connect.md#hmac_secret
[identity_providers.oidc.issuer_certificate_chain]: ../identity-providers/open-id-connect.md#issuercertificatechain
[identity_providers.oidc.issuer_private_key]: ../identity-providers/open-id-connect.md#issuerprivatekey
[identity_providers.oidc.hmac_secret]: ../identity-providers/open-id-connect.md#hmacsecret
## Secrets in configuration file

View File

@ -73,7 +73,7 @@ default_2fa_method: totp
especially for containerized deployments.*
Defines the secret used to craft JWT tokens leveraged by the identity verification process. This can a random string.
It's strongly recommended this is a [Random Alphanumeric String](../../reference/guides/generating-secure-values.md/#generating-a-random-alphanumeric-string) with
It's strongly recommended this is a [Random Alphanumeric String](../../reference/guides/generating-secure-values.md#generating-a-random-alphanumeric-string) with
64 or more characters.
### theme

View File

@ -68,4 +68,4 @@ Setting this to true will disable the startup check entirely.
Setting this to true will allow Authelia to start and just log an error instead of exiting. The default is that if
Authelia can contact the NTP server successfully, and the time reported by the server is greater than what is configured
in [max_desync](#max_desync) that Authelia fails to start and logs a fatal error.
in [max_desync](#maxdesync) that Authelia fails to start and logs a fatal error.

View File

@ -123,7 +123,7 @@ require an IP address for the host of the backend service but want to verify a s
The key `skip_verify` completely negates validating the certificate of the backend service. This is not recommended,
instead you should tweak the `server_name` option, and the global option
[certificates directory](../miscellaneous/introduction.md#certificates_directory).
[certificates directory](../miscellaneous/introduction.md#certificatesdirectory).
### minimum_version
@ -147,7 +147,7 @@ this value. At the time of this writing `SSL3.0` will always produce errors.
{{< confkey type="string" required="no" >}}
The certificate chain/bundle to be used with the [private_key](#private_key) to perform mutual TLS authentication with
The certificate chain/bundle to be used with the [private_key](#privatekey) to perform mutual TLS authentication with
the server.
The value must be one or more certificates encoded in the DER base64 ([RFC4648]) encoded PEM format.
@ -159,7 +159,7 @@ The value must be one or more certificates encoded in the DER base64 ([RFC4648])
*__Important Note:__ This can also be defined using a [secret](../methods/secrets.md) which is __strongly recommended__
especially for containerized deployments.*
The private key to be used with the [certificate_chain](#certificate_chain) for mutual TLS authentication.
The private key to be used with the [certificate_chain](#certificatechain) for mutual TLS authentication.
The value must be one private key encoded in the DER base64 ([RFC4648]) encoded PEM format.

View File

@ -73,7 +73,7 @@ environment variable or other environment variables set. This also applies to ot
*__Please Note:__ if you're using Authelia with Kubernetes and are not using the provided
[helm chart](https://charts.authelia.com) you will be required to
[configure the enableServiceLinks](../../integration/kubernetes/introduction/index.md#enable-service-links) option.*
[configure the enableServiceLinks](../../integration/kubernetes/introduction.md#enable-service-links) option.*
### 4.25.0
@ -99,7 +99,7 @@ The following changes occurred in 4.7.0:
| logs_level | log_level |
| logs_file | log_file |
*__Please Note:__ The new keys also changed in [4.30.0](#4.30.0) so you will need to update them to the new values if you
are using [4.30.0](#4.30.0) or newer instead of the new keys listed here.*
*__Please Note:__ The new keys also changed in [4.30.0](#4300) so you will need to update them to the new values if you
are using [4.30.0](#4300) or newer instead of the new keys listed here.*
[YAML]: https://yaml.org/

View File

@ -61,10 +61,12 @@ by Authelia from others.
*__Important Note:__ Many TOTP applications do not support this option. It is strongly advised you find out which
applications your users use and test them before changing this option. It is insufficient to test that the application
can add the key, it must also authenticate with Authelia as some applications silently ignore these options. Bitwarden
can add the key, it must also authenticate with Authelia as some applications silently ignore these options. [Bitwarden]
is the only one that has been tested at this time. If you'd like to contribute to documenting support for this option
please see [Issue 2650](https://github.com/authelia/authelia/issues/2650).*
[Bitwarden]: https://bitwarden.com/
The algorithm used for the TOTP key.
Possible Values (case-insensitive):
@ -82,7 +84,7 @@ information.
*__Important Note:__ Some TOTP applications do not support this option. It is strongly advised you find out which
applications your users use and test them before changing this option. It is insufficient to test that the application
can add the key, it must also authenticate with Authelia as some applications silently ignore these options. Bitwarden
can add the key, it must also authenticate with Authelia as some applications silently ignore these options. [Bitwarden]
is the only one that has been tested at this time. If you'd like to contribute to documenting support for this option
please see [Issue 2650](https://github.com/authelia/authelia/issues/2650).*
@ -137,7 +139,7 @@ validations.
This means if the configuration options are changed, users will not need to regenerate their keys. This functionality
takes effect from 4.33.0 onwards, previously the effect was the keys would just fail to validate. If you'd like to force
users to register a new device, you can delete the old device for a particular user by using the
`authelia storage totp delete <username>` command regardless of if you change the settings or not.
`authelia storage user totp delete <username>` command regardless of if you change the settings or not.
## Input Validation
@ -160,7 +162,7 @@ check the clients.
## Encryption
The TOTP secret is [encrypted](../storage/introduction.md#encryption_key) in the database in version 4.33.0 and above.
The TOTP secret is [encrypted](../storage/introduction.md#encryptionkey) in the database in version 4.33.0 and above.
This is so a user having access to only the database cannot easily compromise your two-factor authentication method.
This may be inconvenient for some users who wish to export TOTP keys from Authelia to other services. As such there is
@ -170,19 +172,19 @@ at least a minimal configuration that has the storage backend connection details
Export in [Key URI Format](https://github.com/google/google-authenticator/wiki/Key-Uri-Format):
```bash
authelia storage totp export --format uri
authelia storage user totp export --format uri
```
Export as CSV:
```bash
authelia storage totp export --format csv
authelia storage user totp export --format csv
```
Help:
```bash
authelia storage totp export --help
authelia storage user totp export --help
```
[RFC4226]: https://www.rfc-editor.org/rfc/rfc4226.html

View File

@ -198,7 +198,7 @@ When used in conjunction with [domain] the rule will match when either the [doma
In addition to standard regex patterns this criteria can match some [Named Regex Groups].
[domain_regex]: #domain_regex
[domain_regex]: #domainregex
##### Examples
@ -339,7 +339,7 @@ access_control:
{{< confkey type="list(string)" required="no" >}}
This criteria is a list of values which can be an IP Address, network address range in CIDR notation, or an alias from
the [global](#networks-global) section. It matches against the first address in the `X-Forwarded-For` header, or if there
the [global](#networks--global-) section. It matches against the first address in the `X-Forwarded-For` header, or if there
are none it will fall back to the IP address of the packet TCP source IP address. For this reason it's important for you
to configure the proxy server correctly in order to accurately match requests with this criteria. *__Note:__ you may
combine CIDR networks with the alias rules as you please.*
@ -360,7 +360,7 @@ for administrators to tune the security to their specific needs if desired.
##### Examples
*Require [two_factor](#two_factor) for all clients other than internal clients and `112.134.145.167`. The first two
*Require [two_factor](#twofactor) for all clients other than internal clients and `112.134.145.167`. The first two
rules in this list are effectively the same rule just expressed in different ways.*
```yaml
@ -485,7 +485,7 @@ access_control:
## Policies
The policy of the first matching rule in the configured list decides the policy applied to the request, if no rule
matches the request the [default_policy](#default_policy) is applied.
matches the request the [default_policy](#defaultpolicy) is applied.
[policies]: #policies
@ -510,14 +510,14 @@ about the subject is [one_factor]. See [Rule Matching Concept 2] for more inform
This policy requires the user at minimum complete 1FA successfully (username and password). This means if they have
performed 2FA then they will be allowed to access the resource.
[one_factor]: #one_factor
[one_factor]: #onefactor
### two_factor
This policy requires the user to complete 2FA successfully. This is currently the highest level of authentication
policy available.
[two_factor]: #two_factor
[two_factor]: #twofactor
## Rule Matching
@ -554,7 +554,7 @@ a match for that request.
policy: two_factor
```
[Rule Matching Concept 1]: #rule-matching-concept-1-sequential-order
[Rule Matching Concept 1]: #rule-matching-concept-1--sequential-order
### Rule Matching Concept 2: Subject Criteria Requires Authentication
@ -569,7 +569,7 @@ for authentication if no prior rules match the request per [Rule Matching Concep
identical rules, and one of them has a subject based reliant criteria, and the other one is a [bypass] rule then the
[bypass] rule should generally come first.
[Rule Matching Concept 2]: #rule-matching-concept-2-subject-criteria-requires-authentication
[Rule Matching Concept 2]: #rule-matching-concept-2--subject-criteria-requires-authentication
## Named Regex Groups

View File

@ -40,7 +40,7 @@ There are currently two providers for session storage (three if you count Redis
* Memory (default, stateful, no additional configuration)
* [Redis](redis.md) (stateless).
* [Redis Sentinel](redis.md#high_availability) (stateless, highly available).
* [Redis Sentinel](redis.md#highavailability) (stateless, highly available).
### Kubernetes or High Availability
@ -99,7 +99,7 @@ characters.
the [common options](../prologue/common.md#duration-notation-format) documentation for information on this format.*
The period of time before the cookie expires and the session is destroyed. This is overriden by
[remember_me_duration](#remember_me_duration) when the remember me box is checked.
[remember_me_duration](#remembermeduration) when the remember me box is checked.
### inactivity

View File

@ -32,7 +32,7 @@ storage:
username: authelia
password: mypassword
tls:
server_name: psotgres.example.com
server_name: postgres.example.com
skip_verify: false
minimum_version: TLS1.2
maximum_version: TLS1.3

View File

@ -35,7 +35,7 @@ storage:
### encryption_key
See the [encryption_key docs](introduction.md#encryption_key).
See the [encryption_key docs](introduction.md#encryptionkey).
### path

View File

@ -13,7 +13,7 @@ toc: true
---
*Authelia* allows collecting telemetry for the purpose of monitoring it. At the present time we only allow collecting
[metrics](./metrics.md). These [metrics](./metrics.md) are stored in memory and must be scraped manually by the
[metrics](metrics.md). These [metrics](metrics.md) are stored in memory and must be scraped manually by the
administrator.
No metrics or telemetry are reported from an *Authelia* binary to any location the administrator doesn't explicitly

View File

@ -24,7 +24,7 @@ was not prompted by any bug bounty program as we do not have one, but we hope to
Potential usage for the money, ranked in order of priority:
1. Put Authelia through a comprehensive [Security Audit](../../../information/security.md#help-wanted).
1. Put Authelia through a comprehensive [Security Audit](../../policies/security.md#help-wanted).
1. Audit of Code Security via Analysis.
2. Audit via Penetration Testing.
2. Bug Bounty Program.
@ -38,11 +38,11 @@ Please visit [Open Collective] in order to financially contribute to Authelia.
Authelia is sponsored by several companies via indirect means. These companies deserve a special mention since their
contributions are very important to us but not easily visible.
If you feel you have a product or service that Authelia could benefit from please feel free to [contact](../../../information/contact.md) us.
If you feel you have a product or service that Authelia could benefit from please feel free to [contact](../../information/contact.md) us.
We are currently directly looking for someone to sponsor:
* [Security Audit](../../../information/security.md#help-wanted)
* [Security Audit](../../policies/security.md#help-wanted)
### Balto

View File

@ -29,7 +29,7 @@ If the language you wish to translate is not on [Crowdin] then you have a few op
## Overrides
Users can override translations easily locally using the
[assets](../../configuration/miscellaneous/server.md#asset_path) directory. This is useful if you wish to perform a
[assets](../../configuration/miscellaneous/server.md#assetpath) directory. This is useful if you wish to perform a
translation and see if it looks correct in the browser.
[Crowdin]: https://translate.authelia.com

View File

@ -11,8 +11,8 @@ aliases:
## Security
If you believe you have identified a security related bug with Authelia please visit the [security policy](security.md)
documentation.
If you believe you have identified a security related bug with Authelia please visit the
[security policy](../policies/security.md) documentation.
## GitHub

View File

@ -42,10 +42,10 @@ It expects the following:
* The file `data/authelia/config/configuration.yml` is present and the configuration file.
* The directory `data/authelia/secrets/` exists and contain the relevant [secret](../../configuration/methods/secrets.md) files:
* A file named `JWT_SECRET` for the [jwt_secret](../../configuration/miscellaneous/introduction.md#jwt_secret)
* A file named `JWT_SECRET` for the [jwt_secret](../../configuration/miscellaneous/introduction.md#jwtsecret)
* A file named `SESSION_SECRET` for the [session secret](../../configuration/session/introduction.md#secret)
* A file named `STORAGE_PASSWORD` for the [PostgreSQL password secret](../../configuration/storage/postgres.md#password)
* A file named `STORAGE_ENCRYPTION_KEY` for the [storage encryption_key secret](../../configuration/storage/introduction.md#encryption_key)
* A file named `STORAGE_ENCRYPTION_KEY` for the [storage encryption_key secret](../../configuration/storage/introduction.md#encryptionkey)
* You're using PostgreSQL.
* You have an external network named `net` which is in bridge mode.

View File

@ -15,7 +15,7 @@ toc: true
There are three main methods to deploy *Authelia*.
1. [Docker](docker.md)
2. [Kubernetes](../kubernetes/introduction/index.md)
2. [Kubernetes](../kubernetes/introduction.md)
3. [Bare-Metal](bare-metal.md)
## Get Started

View File

@ -15,4 +15,4 @@ search:
index: false
---
Please see the dedicated [Kubernetes Documentation](../kubernetes/introduction/index.md).
Please see the dedicated [Kubernetes Documentation](../kubernetes/introduction.md).

View File

@ -30,7 +30,7 @@ Users are welcome to reach out directly by using any of our various [contact opt
## Get Started
It's __*strongly recommended*__ that users setting up *Authelia* for the first time take a look at our
[Get Started](../../prologue/get-started) guide. This takes you through various steps which are essential to
[Get Started](../prologue/get-started.md) guide. This takes you through various steps which are essential to
bootstrapping *Authelia*.
## Important Notes
@ -70,7 +70,7 @@ spec:
If using file-based authentication, the argon2id provider will by default use 1GB of RAM for password generation. This
means you should allow for at least this amount in your deployment/daemonset spec and have this much available on your
node, alternatively you can
[tweak the providers settings](../../../configuration/first-factor/file.md#memory). Otherwise,
[tweak the providers settings](../../configuration/first-factor/file.md#memory). Otherwise,
your Authelia may OOM during login. See [here](https://github.com/authelia/authelia/issues/1234#issuecomment-663910799)
for more info.

View File

@ -86,7 +86,7 @@ metadata:
name: app
namespace: default
annotations:
traefik.ingress.kubernetes.io/router.entrypoints: websecure
traefik.ingress.kubernetes.io/router.entryPoints: websecure
traefik.ingress.kubernetes.io/router.middlewares: default-forwardauth-authelia@kubernetescrd
traefik.ingress.kubernetes.io/router.tls: "true"
spec:

View File

@ -111,7 +111,7 @@ Below is a list of the potential values we place in the [Claim] and their meanin
## User Information Signing Algorithm
The following table describes the response from the [UserInfo] endpoint depending on the
[userinfo_signing_algorithm](../../configuration/identity-providers/open-id-connect.md#userinfo_signing_algorithm).
[userinfo_signing_algorithm](../../configuration/identity-providers/open-id-connect.md#userinfosigningalgorithm).
| Signing Algorithm | Encoding | Content Type |
|:-----------------:|:------------:|:-----------------------------------:|

View File

@ -38,9 +38,9 @@ used as a basis for configuration.
The important sections to consider in initial configuration are as follows:
1. [jwt_secret](../../configuration/miscellaneous/introduction.md#jwt_secret) which is used to sign identity
1. [jwt_secret](../../configuration/miscellaneous/introduction.md#jwtsecret) which is used to sign identity
verification emails
2. [default_redirection_url](../../configuration/miscellaneous/introduction.md#default_redirection_url) which is the
2. [default_redirection_url](../../configuration/miscellaneous/introduction.md#defaultredirectionurl) which is the
default URL users will be redirected to when visiting *Authelia* directly
3. [authentication_backend](../../configuration/first-factor/introduction.md) which you must pick between
[LDAP](../../configuration/first-factor/ldap.md) and a [YAML File](../../configuration/first-factor/file.md) and is
@ -76,8 +76,8 @@ There are several methods of deploying *Authelia* and we recommend reading the
The default method of utilizing *Authelia* is via the [Proxy Integrations](../proxies/introduction.md). It's
recommended that you read the relevant [Proxy Integration Documentation](../proxies/introduction.md).
*__Important Note:__ When your [Deployment](#deployment) is on [Kubernetes](../kubernetes/introduction/index.md) we
recommend viewing the dedicated [Kubernetes Documentation](../kubernetes/introduction/index.md) prior to viewing the
*__Important Note:__ When your [Deployment](#deployment) is on [Kubernetes](../kubernetes/introduction.md) we
recommend viewing the dedicated [Kubernetes Documentation](../kubernetes/introduction.md) prior to viewing the
[Proxy Integration Documentation](../proxies/introduction.md).*
## Moving to Production

View File

@ -24,12 +24,12 @@ throughout this documentation and in the [See Also](#see-also) section.*
## Get Started
It's __*strongly recommended*__ that users setting up *Authelia* for the first time take a look at our
[Get Started](../prologue/get-started.md) guide. This takes you through various steps which are essential to
[Get Started](../../prologue/get-started.md) guide. This takes you through various steps which are essential to
bootstrapping *Authelia*.
## Requirements
[NGINX Proxy Manager] supports the required [NGINX](nginx.md#requirements) requirements for __Authelia__ out-of-the-box.
[NGINX Proxy Manager] supports the required [NGINX](../nginx.md#requirements) requirements for __Authelia__ out-of-the-box.
## Trusted Proxies
@ -37,7 +37,7 @@ bootstrapping *Authelia*.
Especially if you have never read it before.*
To configure trusted proxies for [NGINX Proxy Manager] see the [NGINX] section on
[Trusted Proxies](nginx.md#trusted-proxies). Adapting this to [NGINX Proxy Manager] is beyond the scope of
[Trusted Proxies](../nginx.md#trusted-proxies). Adapting this to [NGINX Proxy Manager] is beyond the scope of
this documentation.
## Docker Compose
@ -137,9 +137,9 @@ either most likely require an adjustment, or may require an adjustment if you're
### Snippets
The examples assume you've mounted a volume containing the relevant
[NGINX Snippets](nginx.md#supporting-configuration-snippets) from the [NGINX Integration Guide](nginx.md). The suggested
snippets are the `proxy.conf`, `authelia-location.conf`, and `authelia-authrequest.conf`. It may be fine to substitute
the standard variant of the `proxy.conf` for the headers only variant but this is untested.
[NGINX Snippets](../nginx.md#supporting-configuration-snippets) from the [NGINX Integration Guide](../nginx.md). The
suggested snippets are the `proxy.conf`, `authelia-location.conf`, and `authelia-authrequest.conf`. It may be fine to
substitute the standard variant of the `proxy.conf` for the headers only variant but this is untested.
These snippets make the addition of a protected proxy host substantially easier.

View File

@ -62,7 +62,7 @@ required modules including the `http_set_misc` module.
It also includes the [nginx-proxy-confs](https://github.com/linuxserver/docker-mods/tree/nginx-proxy-confs) mod where
they have several configuration examples in the `/config/nginx/proxy-confs` directory. This can be omitted if desired.
If you're looking for a more complete solution [linuxserver.io] also have an nginx container called [SWAG](./swag.md)
If you're looking for a more complete solution [linuxserver.io] also have an nginx container called [SWAG](swag.md)
which includes ACME and various other useful utilities.
{{< details "docker-compose.yaml" >}}

View File

@ -76,7 +76,7 @@ For example the nginx ngx_http_auth_request_module does not seem to support this
Authelia detects the upstream request method using the X-Forwarded-Method header. Some proxies set this out of the box,
some require you to configure this manually. At the present time all proxies that have
[Standard Support](#standard-support) do support this.
[Standard Support](#standard) do support this.
## Specific proxy notes

View File

@ -77,7 +77,7 @@ required modules including the `http_set_misc` module.
It also includes the [nginx-proxy-confs](https://github.com/linuxserver/docker-mods/tree/nginx-proxy-confs) mod where
they have several configuration examples in the `/config/nginx/proxy-confs` directory. This can be omitted if desired.
If you're looking for a more complete solution [linuxserver.io] also have an nginx container called [SWAG](./swag.md)
If you're looking for a more complete solution [linuxserver.io] also have an nginx container called [SWAG](swag.md)
which includes ACME and various other useful utilities.
{{< details "docker-compose.yaml" >}}

View File

@ -25,8 +25,8 @@ unreliable and simple usernames and passwords are not sufficient for security.
__Authelia__ enables primarily two-factor authentication. These methods offered come in two forms:
* 1FA or first-factor authentication which is handled by a username and password. This falls into the *something you know*
categorization.
* 1FA or first-factor authentication which is handled by a username and password. This falls into the
*something you know* categorization.
* 2FA or second-factor authentication which is handled by several methods including one-time passwords, authentication
keys, etc. This falls into the *something you have* categorization.

View File

@ -28,14 +28,7 @@ the user must match the name of the user in Authelia, or must have an alias that
Then, in Duo interface, click on *Applications* and *Protect an Application*. Select the option *Partner Auth API*. This
will generate an integration key, a secret key and a hostname. You can set the name of the application to __Authelia__
and then you must add the generated information to Authelia [configuration](../../deployment/index.md) as shown below:
```yaml
duo_api:
hostname: api-123456789.example.com
integration_key: ABCDEF
secret_key: 1234567890abcdefghifjkl
```
and then you must add the generated information to Authelia [configuration](../../../configuration/second-factor/duo.md).
See the [configuration documentation](../../../configuration/second-factor/duo.md) for more details.

View File

@ -1,7 +1,7 @@
---
title: "OpenID Connect 1.0"
description: "OpenID Connect 1.0 is a authorization identity framework supported by Authelia."
date: 2022-06-15T17:51:47+10:00
date: 2022-11-27T16:07:08+11:00
draft: false
images: []
menu:

View File

@ -2,7 +2,7 @@
title: "Trusted Headers SSO"
description: "Trusted Headers SSO is a simple header authorization framework supported by Authelia."
lead: "Trusted Headers is a simple header authorization framework supported by Authelia."
date: 2022-06-15T17:51:47+10:00
date: 2022-11-27T16:07:08+11:00
draft: false
images: []
menu:

View File

@ -53,6 +53,6 @@ Authelia only works for websites served over HTTPS because the session cookie ca
connections. Please note that it has been decided that we won't support websites served over HTTP in order to avoid any
risk due to misconfiguration (see [#590](https://github.com/authelia/authelia/issues/590)).
If a self-signed certificate is required, the
[Generating an RSA Self-Signed Certificate](../../../reference/guides/generating-secure-values.md#generating-an-rsa-self-signed-certificate)
guide should be followed.
If a self-signed certificate is required, the [Generating an RSA Self-Signed Certificate] guide should be followed.
[Generating an RSA Self-Signed Certificate]: ../../../reference/guides/generating-secure-values.md#generating-an-rsa-self-signed-certificate

View File

@ -73,7 +73,7 @@ attacker obtains the file, each password has to be brute forced individually.
Lastly Authelia's implementation of Argon2id is highly tunable. You can tune the key length, salt used, iterations
(time), parallelism, and memory usage. To read more about this please read how to
[configure](../configuration/authentication/file.md) file authentication.
[configure](../../configuration/first-factor/file.md) file authentication.
## User profile and group membership always kept up-to-date (LDAP authentication provider)
@ -147,7 +147,7 @@ If you wish to change your encryption key for any reason you can do so using the
## Notifier security measures (SMTP)
The SMTP Notifier implementation does not allow connections that are not secure without changing default configuration
The SMTP Notifier implementation does not allow connections that are not secure without changing default configuration
values.
As such all SMTP connections require the following:
@ -158,59 +158,60 @@ As such all SMTP connections require the following:
There is an option to disable both of these security measures however they are __not recommended__.
The following configuration options exist to configure the security level in order of most preferable to least
The following configuration options exist to configure the security level in order of most preferable to least
preferable:
### Configuration Option: certificates_directory
You can [configure a directory](../../configuration/miscellaneous/introduction.md#certificates_directory) of
certificates for Authelia
to trust. These certificates can either be CA's or individual public certificates that should be trusted. These
are added in addition to the environments PKI trusted certificates if available. This is useful for trusting a
certificate that is self-signed without drastically reducing security. This is the most recommended workaround to not
having a valid PKI trusted certificate as it gives you complete control over which ones are trusted without disabling
critically needed validation of the identity of the target service.
You can configure a [certificates_directory] option which contains certificates for Authelia to trust. These certificates
can either be CA's or individual public certificates that should be trusted. These are added in addition to the
environments PKI trusted certificates if available. This is useful for trusting a certificate that is self-signed without
drastically reducing security. This is the most recommended workaround to not having a valid PKI trusted certificate as
it gives you complete control over which ones are trusted without disabling critically needed validation of the identity
of the target service.
Read more in the [documentation](../../configuration/miscellaneous/introduction.md#certificates_directory) for this
option.
Read more in the [certificates_directory] documentation for this option.
[certificates_directory]: ../../configuration/miscellaneous/introduction.md#certificatesdirectory
[certificates directory]: #configuration-option--certificatesdirectory
### Configuration Option: tls.skip_verify
The [tls.skip_verify](../../configuration/notifications/smtp.md#tls) option allows you to skip verifying the certificate
entirely which is why [certificates_directory](#configuration-option-certificates_directory) is preferred over this.
This will effectively mean you cannot be sure the certificate is valid which means an attacker via DNS poisoning or MITM
attacks could intercept emails from Authelia compromising a user's security without their knowledge.
entirely which is why [certificates directory] is preferred over this. This will effectively mean you cannot be sure the
certificate is valid which means an attacker via DNS poisoning or MITM attacks could intercept emails from Authelia
compromising a user's security without their knowledge.
### Configuration Option: disable_require_tls
Authelia by default ensures that the SMTP server connection is secured via TLS prior to sending sensitive information.
The [disable_require_tls](../../configuration/notifications/smtp.md#disable_require_tls) option disables this
requirement which means the emails may be sent in cleartext. This is the least secure option as it effectively removes
The [disable_require_tls](../../configuration/notifications/smtp.md#disablerequiretls) option disables this
requirement which means the emails may be sent in cleartext. This is the least secure option as it effectively removes
the validation of SMTP certificates and makes using an encrypted connection with TLS optional.
This means not only can the vulnerabilities of the [skip_verify](#configuration-option-tlsskip_verify) option be
exploited, but any router or switch along the route of the email which receives the packets could be used to silently
This means not only can the vulnerabilities of the [skip_verify](#configuration-option--tlsskipverify) option be
exploited, but any router or switch along the route of the email which receives the packets could be used to silently
exploit the cleartext nature of the connection to manipulate the email in transit.
This is only usable currently with authentication disabled (_comment out the password_), and as such is only an option
This is only usable currently with authentication disabled (_comment out the password_), and as such is only an option
for SMTP servers that allow unauthenticated relaying (bad practice).
### SMTP Ports
All SMTP connections begin as [cleartext], and then negotiate to upgrade to a secure TLS connection via STARTTLS.
The [`submissions` service][service-submissions] (_typically port 465_) is an exception to this rule, where the
connection begins immediately secured with TLS (_similar to HTTPS_). When the configured [port for
SMTP][docs-config-smtp-port] is set to `465`, Authelia will initiate TLS connections without requiring STARTTLS
The [`submissions` service][service-submissions] (_typically port 465_) is an exception to this rule, where the
connection begins immediately secured with TLS (_similar to HTTPS_). When the configured [port for
SMTP][docs-config-smtp-port] is set to `465`, Authelia will initiate TLS connections without requiring STARTTLS
negotiation.
When the `submissions` service port is available, it [should be preferred][port-465] over any STARTTLS port for
When the `submissions` service port is available, it [should be preferred][port-465] over any STARTTLS port for
submitting mail.
**NOTE:** Prior to 2018, port 465 was previously assigned for a similar purpose known as [`smtps`][port-465] (_A TLS
**NOTE:** Prior to 2018, port 465 was previously assigned for a similar purpose known as [`smtps`][port-465] (_A TLS
only equivalent of the `smtp` port 25_), which it had been deprecated for. Port 465 has since been re-assigned for only
supporting mail submission (_which unlike SMTP transfers via port 25, [requires authentication][smtp-auth]_), similar
supporting mail submission (_which unlike SMTP transfers via port 25, [requires authentication][smtp-auth]_), similar
to port 587 (_the `submission` port, a common alternative that uses STARTTLS instead_).
[docs-config-smtp-port]: ../../configuration/notifications/smtp.md#port
@ -237,7 +238,7 @@ would not even be able to create a TCP connection. This measure is recommended i
configured some kind of ACLs specifically allowing the communication between proxies and Authelia instances like in a
service mesh or some kind of network overlay.
To configure mutual TLS, please refer to [this document](../../configuration/miscellaneous/server.md#client_certificates)
To configure mutual TLS, please refer to [this document](../../configuration/miscellaneous/server.md#clientcertificates)
## Additional security
@ -255,7 +256,7 @@ database. The value of this option should be long and as random as possible. See
[documentation](../../configuration/session/introduction.md#secret) for this option.
The validity period of session is highly configurable. For example in a highly security conscious domain you could
set the session [remember_me_duration](../../configuration/session/introduction.md#remember_me_duration) to 0 to disable this
set the session [remember_me_duration](../../configuration/session/introduction.md#remembermeduration) to 0 to disable this
feature, and set the [expiration](../../configuration/session/introduction.md#expiration) to 2 hours and the
[inactivity](../../configuration/session/introduction.md#inactivity) of 10 minutes. Configuring the session security in this
manner would mean if the cookie age was more than 2 hours or if the user was inactive for more than 10 minutes the

View File

@ -37,11 +37,11 @@ This is the preferred method of reporting.
### Chat
If you wish to chat directly instead of sending an email please use one of the [chat options](../information/contact.md#chat) but it
is vital that when you do that you only do so privately with one of the maintainers. In order to start a private
discussion you should ask to have a private discussion with a team member without mentioning the reason why you wish to
have a private discussion so that provided the bug is confirmed we can coordinate the release of fixes and information
responsibly.
If you wish to chat directly instead of sending an email please use one of the
[chat options](../information/contact.md#chat) but it is vital that when you do that you only do so privately with one
of the maintainers. In order to start a private discussion you should ask to have a private discussion with a team
member without mentioning the reason why you wish to have a private discussion so that provided the bug is confirmed we
can coordinate the release of fixes and information responsibly.
## Credit

View File

@ -20,12 +20,12 @@ modifications that are in harmony with the following rules which are not intende
only intended to preserve the Authelia branding identity:
1. They do not unreasonably alter the quality of the branding:
- Image size changes should be done only when the size is appropriate for the intended display scenario.
- Compression should not be applied overly aggressively for the intended display scenario.
- Image size changes should be done only when the size is appropriate for the intended display scenario.
- Compression should not be applied overly aggressively for the intended display scenario.
2. The changes do not unreasonably alter the design of the branding and should fit one or more of the following
categories:
- Layout
- Format
- Layout
- Format
Examples of changes which fit these categories include:
@ -48,7 +48,7 @@ The logo is just the Authelia circle logo without any text.
#### Logo Files
[PSD](https://www.authelia.com/images/branding/logo.psd) | [SVG](https://www.authelia.com/images/branding/logo.svg) | [PNG](https://www.authelia.com/images/branding/logo.png)
[PSD](https://www.authelia.com/images/branding/logo.psd) | [AI](https://www.authelia.com/images/branding/logo.ai) | [SVG](https://www.authelia.com/images/branding/logo.svg) | [PNG](https://www.authelia.com/images/branding/logo.png)
#### Logo Example
@ -60,7 +60,7 @@ The logo is the same as the standard logo without padding.
#### Logo (Cropped) Files
[PSD](https://www.authelia.com/images/branding/logo-cropped.psd) | [SVG](https://www.authelia.com/images/branding/logo-cropped.svg) | [PNG](https://www.authelia.com/images/branding/logo-cropped.png)
[PSD](https://www.authelia.com/images/branding/logo-cropped.psd) | [AI](https://www.authelia.com/images/branding/logo-cropped.ai) | [SVG](https://www.authelia.com/images/branding/logo-cropped.svg) | [PNG](https://www.authelia.com/images/branding/logo-cropped.png)
#### Logo (Cropped) Example
@ -72,7 +72,7 @@ The title is the Authelia circle logo with the `authelia` branded text.
#### Title Files
[PSD](https://www.authelia.com/images/branding/title.psd) | [SVG](https://www.authelia.com/images/branding/title.svg) | [PNG](https://www.authelia.com/images/branding/title.png)
[PSD](https://www.authelia.com/images/branding/title.psd) | [AI](https://www.authelia.com/images/branding/title.ai) | [SVG](https://www.authelia.com/images/branding/title.svg) | [PNG](https://www.authelia.com/images/branding/title.png)
#### Title Example

View File

@ -22,7 +22,7 @@ The most insecure method is unauthenticated binds. They are generally considered
at all ensures anyone with any level of network access can easily obtain objects and their attributes.
Authelia does support unauthenticated binds but it is not by default, you must configure the
[permit_unauthenticated_bind](../../configuration/first-factor/ldap.md#permit_unauthenticated_bind) configuration
[permit_unauthenticated_bind](../../configuration/first-factor/ldap.md#permitunauthenticatedbind) configuration
option.
### End-User Binding
@ -94,17 +94,18 @@ accounts. The active directory example has two attribute filters that accomplish
be appreciated). The userAccountControl filter checks that the account is not disabled and the pwdLastSet makes sure that
value is not 0 which means the password requires changing at the next login.
| Implementation | Users Filter | Groups Filter |
|:---------------:|:---------------------------------------------------------------------------------------------------------------------------------------------------------------:|:------------------------------------------:|
| custom | N/A | N/A |
| activedirectory | (&(&#124;({username_attribute}={input})({mail_attribute}={input}))(sAMAccountType=805306368)(!(userAccountControl:1.2.840.113556.1.4.803:=2))(!(pwdLastSet=0))) | (&(member={dn})(sAMAccountType=268435456)) |
| Implementation | Users Filter | Groups Filter |
|:---------------:|:---------------------------------------------------------------------------------------------------------------------------------------------------------------:|:----------------------------------------------------------------------------:|
| custom | N/A | N/A |
| activedirectory | (&(&#124;({username_attribute}={input})({mail_attribute}={input}))(sAMAccountType=805306368)(!(userAccountControl:1.2.840.113556.1.4.803:=2))(!(pwdLastSet=0))) | (&(member={dn})(&#124;(sAMAccountType=268435456)(sAMAccountType=536870912))) |
##### Microsoft Active Directory sAMAccountType
| Account Type Value | Description | Equivalent Filter |
|:------------------:|:--------------------------:|:----------------------------------------------:|
| 268435456 | Normal Group Objects | N/A |
| 805306368 | Normal User Accounts | `(&(objectCategory=person)(objectClass=user))` |
| Account Type Value | Description | Equivalent Filter |
|:------------------:|:---------------------------------------:|:----------------------------------------------:|
| 268435456 | Global/Universal Security Group Objects | N/A |
| 536870912 | Domain Local Security Group Objects | N/A |
| 805306368 | Normal User Accounts | `(&(objectCategory=person)(objectClass=user))` |
*__References:__*
- Account Type Values: [Microsoft Learn](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-samr/e742be45-665d-4576-b872-0bc99d1e1fbe).

View File

@ -16,7 +16,7 @@ Authelia uses templates to generate the HTML and plaintext emails sent via the n
two extensions; `.html` for HTML templates, and `.txt` for plaintext templates.
This guide effectively documents the usage of the
[template_path](../../configuration/notifications/introduction.md#template_path) notification configuration option.
[template_path](../../configuration/notifications/introduction.md#templatepath) notification configuration option.
## Important Notes
@ -37,7 +37,7 @@ This guide effectively documents the usage of the
| PasswordReset | Used to render notifications sent when password has successfully been reset |
For example, to modify the `IdentityVerification` HTML template, if your
[template_path](../../configuration/notifications/introduction.md#template_path) was configured as
[template_path](../../configuration/notifications/introduction.md#templatepath) was configured as
`/config/email_templates`, you would create the `/config/email_templates/IdentityVerification.html` file to override the
HTML `IdentityVerification` template.

View File

@ -156,7 +156,7 @@ See the [Crypt (C) Wiki page](https://en.wikipedia.org/wiki/Crypt_(C)) for more
#### Tuning
The configuration variables are unique to the file authentication provider, thus they all exist in a key under the file
authentication configuration key called [password](../../configuration/first-factor/file.md#password). The defaults are
authentication configuration key called [password](../../configuration/first-factor/file.md#password-options). The defaults are
considered as sane for a reasonable system however we still recommend taking time to figure out the best values to
adequately determine the [cost](#cost).

View File

@ -26,10 +26,10 @@ This guide effectively documents the usage of the
## Assets
| Asset | File Name | Directory | Notes |
|:-------------------:|:-----------:|:---------:|:-------------:|
| Favicon | favicon.ico | No | N/A |
| Logo | logo.png | No | N/A |
| Asset | File Name | Directory | Notes |
|:-------------------:|:-----------:|:---------:|:-----------------------:|
| Favicon | favicon.ico | No | N/A |
| Logo | logo.png | No | N/A |
| Translation Locales | locales | Yes | see [locales](#locales) |
## locales

View File

@ -12,7 +12,6 @@ weight: 220
toc: true
aliases:
- /r/sanitize
- /reference/guides/domain-sanitizaiton
---
Some users may wish to hide their domain in files provided during troubleshooting. While this is discouraged, if a user

View File

@ -0,0 +1,40 @@
---
title: "Cache Integrations"
description: "A cache integration reference guide"
lead: "This section contains a cache integration reference guide for Authelia."
date: 2022-11-19T16:47:09+11:00
draft: false
images: []
menu:
reference:
parent: "integrations"
weight: 320
toc: true
---
We currently only support [Redis Standalone] and [Redis Sentinel] for cached information like sessions
(other than in-memory).
## Redis
The following is guidance on versions of [Redis] supported.
### Standalone
When it comes to [Redis Standalone] we support the versions supported by [Redis] themselves which can be found in the
[Redis release cycle](https://redis.io/docs/about/releases/) documentation. This is typically the latest available
version.
### Sentinel
When it comes to [Redis Sentinel] we support the versions supported by [Redis] themselves which can be found in the
[Redis release cycle](https://redis.io/docs/about/releases/) documentation. This is typically the latest available
version.
_**Note:** Currently we only support [Redis Sentinel] version 6.x due to a breaking change to [Redis Sentinel] in
version 7.x. This will be resolved in the near future._
[Redis]: https://redis.io/
[Redis Standalone]: https://redis.io/docs/getting-started/
[Redis Sentinel]: https://redis.io/docs/management/sentinel/

View File

@ -15,16 +15,29 @@ toc: true
We generally recommend using [PostgreSQL] for a database. If high availability is not a consideration we also support
[SQLite3].
It is also a general recommendation that if you're using [PostgreSQL], [MySQL], or [MariaDB]; that you do not
automatically upgrade the major/minor version of these databases, and pin the image tag so at most the patch version
is updated. For example for database version `x.y.z` only the `z` should change, `x` and `y` should remain the same.
It is also generally recommended that you do not rely on automatic update tools to perform this action
unless you are sure they shut down the container properly (i.e. with a graceful stop).
While this guide exists and it contains some guidance on managing the database being used, it is by no means exhaustive
or intended as such and users should refer to the database vendors documentation.
## PostgreSQL
The only current support criteria for [PostgreSQL] at present is that the version you're using is supported by the
[PostgreSQL] developers. See their [Versioning Policy](https://www.postgresql.org/support/versioning/) for more
information.
[PostgreSQL] developers. See [Vendor Supported Versions](#vendor-supported-versions) more information.
We generally perform integration testing against the latest supported version of [PostgreSQL] and that is generally the
recommended version for new installations.
### Vendor Supported Versions
See the [PostgreSQL Versioning Policy](https://www.postgresql.org/support/versioning/) for information on the versions
and platforms that are currently supported by this vendor.
## MySQL
[MySQL] and [MariaDB] are both supported as part of the [MySQL] implementation. This is generally discouraged as
@ -40,8 +53,8 @@ party.
4. Must support maximum index size of no less than 2048 bytes. The default maximum index size for the InnoDB engine is
3072 bytes on:
1. [MySQL] [8.0](https://dev.mysql.com/doc/refman/8.0/en/innodb-limits.html) or later.
2. [MySQL] [5.7](https://dev.mysql.com/doc/refman/5.7/en/innodb-limits.html) provided
[innodb_large_prefix](#innodb-large-prefixes) or later.
2. [MySQL] [5.7](https://dev.mysql.com/doc/refman/5.7/en/innodb-limits.html) or later provided:
1. The [innodb_large_prefix](#innodb-large-prefixes) option is **_ON_**.
3. [MariaDB] [10.3](https://mariadb.com/kb/en/innodb-system-variables/#innodb_large_prefix) or later.
5. Must support ANSI standard time behaviours. See [ANSI standard time behaviours](#ansi-standard-time-behaviours).
@ -52,8 +65,8 @@ supported version of [MariaDB] is generally the recommended version for new inst
#### InnoDB Large Prefixes
This can be configured in the [MySQL] configuration file by setting the `innodb_large_prefix` value to on.
According to the Oracle documentation this is the default behaviour in
This can be configured in the [MySQL] configuration file by setting the `innodb_large_prefix` option to on.
According to the [Oracle] documentation this is the default behaviour in
[MySQL] [5.7](https://dev.mysql.com/doc/refman/5.7/en/innodb-parameters.html#sysvar_innodb_large_prefix) and it can't be
turned off in [MySQL] [8.0](https://dev.mysql.com/doc/refman/8.0/en/innodb-limits.html) or in [MariaDB] 10.3 and later.
@ -65,7 +78,7 @@ innodb_large_prefix = ON
#### ANSI standard time behaviours
This can be configured in the [MySQL] configuration file by setting the `explicit_defaults_for_timestamp` value to on.
According to the Oracle documentation this is the default behaviour in
According to the [Oracle] documentation this is the default behaviour in
[MySQL] [5.7](https://dev.mysql.com/doc/refman/5.7/en/server-system-variables.html#sysvar_explicit_defaults_for_timestamp)
and [MySQL] [8.0](https://dev.mysql.com/doc/refman/8.0/en/server-system-variables.html#sysvar_explicit_defaults_for_timestamp).
This is however not the default behaviour in
@ -76,19 +89,43 @@ This is however not the default behaviour in
explicit_defaults_for_timestamp = ON
```
#### Upgrades
[MySQL] and [MariaDB] have several standard but important system databases named `mysql`, `sys`, and
`performance_schema`. These databases are outside the scope and not intended for individual applications to manage as
they are system databases used by [MySQL] and [MariaDB] internally.
These servers/engines may successfully start when these databases are incompatible with your particular [MySQL] or
[MariaDB] version, but may raise errors when you attempt to use particular features of the database. This may lead a
user to believe the server/engine is functioning correctly when it is in fact running with a potentially badly corrupted
schema.
The risk here is that the database may run for an extended period of time unnoticed and may be getting more and more
corrupt with no visible signs until it's no longer recoverable. This makes it critically important users do not neglect
this operation or ensure it's happening.
While some [MySQL] or [MariaDB] containers will do this automatically or give users an option to perform this
automatically, it is strongly recommended that this process is manually done and only done **_after_** doing a backup of
all databases on the server as is the recommendation from both [MySQL] and [MariaDB].
It is your responsibility to ensure these tables are upgraded as per the
[mysql_upgrade](https://dev.mysql.com/doc/refman/8.0/en/mysql-upgrade.html) and
[mariadb_upgrade](https://mariadb.com/kb/en/mysql_upgrade/) documentation.
### Vendor Supported Versions
#### MariaDB Vendor Supported Versions
See the [MariaDB Server Releases](https://mariadb.com/kb/en/mariadb-server-release-dates/) for more information.
See the [MariaDB Server Releases](https://mariadb.com/kb/en/mariadb-server-release-dates/) for information on the
versions and platforms that are currently supported by this vendor.
#### MySQL Vendor Supported Versions
See the [MySQL Supported Platforms](https://www.mysql.com/support/supportedplatforms/database.html) for information on
which versions and platforms they support.
the versions and platforms that are currently supported by this vendor.
[PostgreSQL]: https://www.postgresql.org/
[MySQL]: https://www.mysql.com/
[MariaDB]: https://mariadb.org/
[SQLite3]: https://www.sqlite.org/index.html
[Oracle]: https://www.oracle.com/

View File

@ -3,20 +3,21 @@
functions = "functions"
[build.environment]
NODE_VERSION = "16.16.0"
NPM_VERSION = "8.11.0"
NODE_VERSION = "16.18.1"
NPM_VERSION = "8.19.2"
GO_VERSION = "1.19.4"
[context.production]
command = "npm run build"
command = "pnpm run build"
[context.deploy-preview]
command = "npm run build -- -b $DEPLOY_PRIME_URL"
command = "pnpm run build --baseURL $DEPLOY_URL"
[context.branch-deploy]
command = "npm run build -- -b $DEPLOY_PRIME_URL"
command = "pnpm run build --baseURL $DEPLOY_URL"
[context.next]
command = "npm run build"
command = "pnpm run build"
[context.next.environment]
HUGO_ENV = "next"

View File

@ -3,7 +3,7 @@
"description": "Doks theme",
"version": "0.5.0",
"engines": {
"node": ">=16.16.0"
"node": ">=16.18.1"
},
"browserslist": [
"defaults"
@ -39,7 +39,7 @@
},
"devDependencies": {
"@babel/cli": "7.19.3",
"@babel/core": "7.20.2",
"@babel/core": "7.20.5",
"@babel/preset-env": "7.20.2",
"@fullhuman/postcss-purgecss": "5.0.0",
"@hyas/images": "0.3.2",
@ -49,25 +49,25 @@
"bootstrap": "5.2.3",
"bootstrap-icons": "1.10.2",
"clipboard": "2.0.11",
"eslint": "8.28.0",
"eslint": "8.29.0",
"exec-bin": "1.0.0",
"flexsearch": "0.7.31",
"highlight.js": "11.7.0",
"hugo-installer": "4.0.1",
"instant.page": "5.1.1",
"katex": "0.16.3",
"katex": "0.16.4",
"lazysizes": "5.3.2",
"markdownlint-cli2": "0.5.1",
"netlify-plugin-submit-sitemap": "0.4.0",
"node-fetch": "3.3.0",
"postcss": "8.4.19",
"postcss-cli": "10.0.0",
"postcss-cli": "10.1.0",
"purgecss-whitelister": "2.4.0",
"shx": "0.3.4",
"stylelint": "14.15.0",
"stylelint": "14.16.0",
"stylelint-config-standard-scss": "6.1.0"
},
"otherDependencies": {
"hugo": "0.107.0"
"hugo": "0.108.0"
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

File diff suppressed because one or more lines are too long

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

File diff suppressed because one or more lines are too long

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 56 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

@ -45,7 +45,7 @@ services:
- TZ=Australia/Melbourne
traefik:
image: traefik:v2.9.5
image: traefik:v2.9.6
container_name: traefik
volumes:
- ./traefik:/etc/traefik

View File

@ -32,7 +32,7 @@ services:
- TZ=Australia/Melbourne
traefik:
image: traefik:v2.9.5
image: traefik:v2.9.6
container_name: traefik
volumes:
- ./traefik:/etc/traefik

20
go.mod
View File

@ -11,27 +11,27 @@ require (
github.com/fasthttp/session/v2 v2.4.13
github.com/fsnotify/fsnotify v1.6.0
github.com/go-asn1-ber/asn1-ber v1.5.4
github.com/go-crypt/crypt v0.1.14
github.com/go-crypt/crypt v0.2.3
github.com/go-ldap/ldap/v3 v3.4.4
github.com/go-rod/rod v0.112.2
github.com/go-sql-driver/mysql v1.6.0
github.com/go-sql-driver/mysql v1.7.0
github.com/go-webauthn/webauthn v0.5.0
github.com/golang-jwt/jwt/v4 v4.4.3
github.com/golang/mock v1.6.0
github.com/google/uuid v1.3.0
github.com/hashicorp/go-retryablehttp v0.7.1
github.com/jackc/pgx/v5 v5.1.1
github.com/jackc/pgx/v5 v5.2.0
github.com/jmoiron/sqlx v1.3.5
github.com/knadh/koanf v1.4.4
github.com/mattn/go-sqlite3 v1.14.16
github.com/mitchellh/mapstructure v1.5.0
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826
github.com/ory/fosite v0.43.0
github.com/ory/fosite v0.44.0
github.com/ory/herodot v0.9.13
github.com/ory/x v0.0.517
github.com/ory/x v0.0.520
github.com/otiai10/copy v1.9.0
github.com/pkg/errors v0.9.1
github.com/pquerna/otp v1.3.0
github.com/pquerna/otp v1.4.0
github.com/prometheus/client_golang v1.14.0
github.com/sirupsen/logrus v1.9.0
github.com/spf13/cobra v1.6.1
@ -40,8 +40,8 @@ require (
github.com/trustelem/zxcvbn v1.0.1
github.com/valyala/fasthttp v1.43.0
golang.org/x/sync v0.1.0
golang.org/x/term v0.2.0
golang.org/x/text v0.4.0
golang.org/x/term v0.3.0
golang.org/x/text v0.5.0
gopkg.in/square/go-jose.v2 v2.6.0
gopkg.in/yaml.v3 v3.0.1
)
@ -63,7 +63,7 @@ require (
github.com/ecordell/optgen v0.0.6 // indirect
github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 // indirect
github.com/fxamacker/cbor/v2 v2.4.0 // indirect
github.com/go-crypt/x v0.1.3 // indirect
github.com/go-crypt/x v0.1.10 // indirect
github.com/go-redis/redis/v8 v8.11.5 // indirect
github.com/go-webauthn/revoke v0.1.6 // indirect
github.com/golang/glog v1.0.0 // indirect
@ -110,7 +110,7 @@ require (
golang.org/x/mod v0.6.0 // indirect
golang.org/x/net v0.1.0 // indirect
golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b // indirect
golang.org/x/sys v0.2.0 // indirect
golang.org/x/sys v0.3.0 // indirect
golang.org/x/tools v0.2.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20221025140454-527a21cfbd71 // indirect

39
go.sum
View File

@ -162,10 +162,10 @@ github.com/fxamacker/cbor/v2 v2.4.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrt
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-asn1-ber/asn1-ber v1.5.4 h1:vXT6d/FNDiELJnLb6hGNa309LMsrCoYFvpwHDF0+Y1A=
github.com/go-asn1-ber/asn1-ber v1.5.4/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
github.com/go-crypt/crypt v0.1.14 h1:Pd8iBYlbwDXJNi0lz8CS/qYvpvxCfP0XO/f5PYvVQ4o=
github.com/go-crypt/crypt v0.1.14/go.mod h1:VNLdWMD0go46arq5WVZB2MV/9Vw02FOWhKDORXl7K2c=
github.com/go-crypt/x v0.1.3 h1:3YSlHqOZsw4gcPzfqrcc5kg4GIhTKmkjl/ZVqJ3CbbU=
github.com/go-crypt/x v0.1.3/go.mod h1:/6X1DjQki055ajXV/7pCHZM0OmMR1+csiXFkxK73Kc8=
github.com/go-crypt/crypt v0.2.3 h1:g9OPe39VmqonsTXP/zo4byEoxrxAAUG+DzBvjzGWvuw=
github.com/go-crypt/crypt v0.2.3/go.mod h1:mbhOIjybuVuh0Vxveb//7UbGV8OCugJC7UPzqs1awYw=
github.com/go-crypt/x v0.1.10 h1:HN8oQGrWcg5xPtIIGwPDWs9MvdYEUJrP7JeNkC46dvM=
github.com/go-crypt/x v0.1.10/go.mod h1:OI04rm/Ojti3mrUFZAJnx66nFbnZ0CVPF7qG49mBZgI=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
@ -184,8 +184,9 @@ github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC
github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo=
github.com/go-rod/rod v0.112.2 h1:dwauKYC/H2em8/BcGk3gC0LTzZHf5MIDKf2DVM4z9gU=
github.com/go-rod/rod v0.112.2/go.mod h1:ElViL9ABbcshNQw93+11FrYRH92RRhMKleuILo6+5V0=
github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc=
github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
github.com/go-test/deep v1.0.2-0.20181118220953-042da051cf31/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
@ -338,8 +339,8 @@ github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsI
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b h1:C8S2+VttkHFdOOCXJe+YGfa4vHYwlt4Zx+IVXQ97jYg=
github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E=
github.com/jackc/pgx/v5 v5.1.1 h1:pZD79K1SYv8wc2HmCQA6VdmRQi7/OtCfv9bM3WAXUYA=
github.com/jackc/pgx/v5 v5.1.1/go.mod h1:Ptn7zmohNsWEsdxRawMzk3gaKma2obW+NWTnKa0S4nk=
github.com/jackc/pgx/v5 v5.2.0 h1:NdPpngX0Y6z6XDFKqmFQaE+bCtkqzvQIOt1wvBlAqs8=
github.com/jackc/pgx/v5 v5.2.0/go.mod h1:Ptn7zmohNsWEsdxRawMzk3gaKma2obW+NWTnKa0S4nk=
github.com/jandelgado/gcov2lcov v1.0.5 h1:rkBt40h0CVK4oCb8Dps950gvfd1rYvQ8+cWa346lVU0=
github.com/jandelgado/gcov2lcov v1.0.5/go.mod h1:NnSxK6TMlg1oGDBfGelGbjgorT5/L3cchlbtgFYZSss=
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
@ -449,8 +450,8 @@ github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1y
github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE=
github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs=
github.com/ory/fosite v0.43.0 h1:9H1O3I7CFxS2Y6j9FDAx2W3I5uAyEubc9hECS0UTOgI=
github.com/ory/fosite v0.43.0/go.mod h1:BTd8+oG1mRtezZbQq0S4D2HBc815bedZHjjs2KRs39Y=
github.com/ory/fosite v0.44.0 h1:Z3UjyO11/wlIoa3BotOqcTkfm7kUNA8F7dd8mOMfx0o=
github.com/ory/fosite v0.44.0/go.mod h1:o/G4kAeNn65l6MCod2+KmFfU6JQBSojS7eXys6lKGzM=
github.com/ory/go-acc v0.2.6/go.mod h1:4Kb/UnPcT8qRAk3IAxta+hvVapdxTLWtrr7bFLlEgpw=
github.com/ory/go-acc v0.2.8 h1:rOHHAPQjf0u7eHFGWpiXK+gIu/e0GRSJNr9pDukdNC4=
github.com/ory/go-acc v0.2.8/go.mod h1:iCRZUdGb/7nqvSn8xWZkhfVrtXRZ9Wru2E5rabCjFPI=
@ -460,8 +461,8 @@ 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/viper v1.7.5 h1:+xVdq7SU3e1vNaCsk/ixsfxE4zylk1TJUiJrY647jUE=
github.com/ory/viper v1.7.5/go.mod h1:ypOuyJmEUb3oENywQZRgeAMwqgOyDqwboO1tj3DjTaM=
github.com/ory/x v0.0.517 h1:20FrwHie18q78WGaHcaH0+XoPNdE88zqSXCQNPNlYUs=
github.com/ory/x v0.0.517/go.mod h1:xUtRpoiRARyJNPVk/fcCNKzyp25Foxt9GPlj8pd7egY=
github.com/ory/x v0.0.520 h1:ryfKHQEViUBv/UdlZhePOG52RpPAooZtK/I7+x58lBI=
github.com/ory/x v0.0.520/go.mod h1:7f32P5XMBLCy6aVT+fUYq3WPcMVpzsjC0C+FovlMNqY=
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/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE=
@ -493,8 +494,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s=
github.com/pquerna/otp v1.3.0 h1:oJV/SkzR33anKXwQU3Of42rL4wbrffP4uvUf1SvS5Xs=
github.com/pquerna/otp v1.3.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg=
github.com/pquerna/otp v1.4.0 h1:wZvl1TIVxKRThZIBiwOOHOGP/1+nZyWBil9Y2XNEDzg=
github.com/pquerna/otp v1.4.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
@ -846,12 +847,12 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/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.2.0 h1:ljd4t30dBnAvMZaQCevtY0xLLD0A+bRZXbgLMLU1F/A=
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ=
golang.org/x/sys v0.3.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-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.2.0 h1:z85xZCsEl7bi/KwbNADeBYoOP0++7W1ipu+aGnpwzRM=
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
golang.org/x/term v0.3.0 h1:qoo4akIqOcDME5bhc/NgxUdovd6BSS2uMsVjB56q1xI=
golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA=
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.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@ -862,8 +863,8 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
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.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg=
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.5.0 h1:OLmvp0KP+FVG99Ct/qFiL/Fhk4zp4QQnZ7b2U+5piUM=
golang.org/x/text v0.5.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-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=

View File

@ -8,7 +8,12 @@ import (
"sync"
"time"
"github.com/go-crypt/crypt"
"github.com/go-crypt/crypt/algorithm"
"github.com/go-crypt/crypt/algorithm/argon2"
"github.com/go-crypt/crypt/algorithm/bcrypt"
"github.com/go-crypt/crypt/algorithm/pbkdf2"
"github.com/go-crypt/crypt/algorithm/scrypt"
"github.com/go-crypt/crypt/algorithm/shacrypt"
"github.com/authelia/authelia/v4/internal/configuration/schema"
"github.com/authelia/authelia/v4/internal/logging"
@ -17,7 +22,7 @@ import (
// FileUserProvider is a provider reading details from a file.
type FileUserProvider struct {
config *schema.FileAuthenticationBackend
hash crypt.Hash
hash algorithm.Hash
database *FileUserDatabase
mutex *sync.Mutex
timeoutReload time.Time
@ -145,39 +150,50 @@ func (p *FileUserProvider) setTimeoutReload(now time.Time) {
}
// NewFileCryptoHashFromConfig returns a crypt.Hash given a valid configuration.
func NewFileCryptoHashFromConfig(config schema.Password) (hash crypt.Hash, err error) {
func NewFileCryptoHashFromConfig(config schema.Password) (hash algorithm.Hash, err error) {
switch config.Algorithm {
case hashArgon2, "":
hash = crypt.NewArgon2Hash().
WithVariant(crypt.NewArgon2Variant(config.Argon2.Variant)).
WithT(config.Argon2.Iterations).
WithM(config.Argon2.Memory).
WithP(config.Argon2.Parallelism).
WithK(config.Argon2.KeyLength).
WithS(config.Argon2.SaltLength)
hash, err = argon2.New(
argon2.WithVariantName(config.Argon2.Variant),
argon2.WithT(config.Argon2.Iterations),
argon2.WithM(uint32(config.Argon2.Memory)),
argon2.WithP(config.Argon2.Parallelism),
argon2.WithK(config.Argon2.KeyLength),
argon2.WithS(config.Argon2.SaltLength),
)
case hashSHA2Crypt:
hash = crypt.NewSHA2CryptHash().
WithVariant(crypt.NewSHA2CryptVariant(config.SHA2Crypt.Variant)).
WithRounds(config.SHA2Crypt.Iterations).
WithSaltLength(config.SHA2Crypt.SaltLength)
hash, err = shacrypt.New(
shacrypt.WithVariantName(config.SHA2Crypt.Variant),
shacrypt.WithIterations(config.SHA2Crypt.Iterations),
shacrypt.WithSaltLength(config.SHA2Crypt.SaltLength),
)
case hashPBKDF2:
hash = crypt.NewPBKDF2Hash().
WithVariant(crypt.NewPBKDF2Variant(config.PBKDF2.Variant)).
WithIterations(config.PBKDF2.Iterations).
WithSaltLength(config.PBKDF2.SaltLength)
hash, err = pbkdf2.New(
pbkdf2.WithVariantName(config.PBKDF2.Variant),
pbkdf2.WithIterations(config.PBKDF2.Iterations),
pbkdf2.WithSaltLength(config.PBKDF2.SaltLength),
)
case hashSCrypt:
hash = crypt.NewScryptHash().
WithLN(config.SCrypt.Iterations).
WithP(config.SCrypt.Parallelism).
WithR(config.SCrypt.BlockSize)
hash, err = scrypt.New(
scrypt.WithLN(config.SCrypt.Iterations),
scrypt.WithP(config.SCrypt.Parallelism),
scrypt.WithR(config.SCrypt.BlockSize),
scrypt.WithKeyLength(config.SCrypt.KeyLength),
scrypt.WithSaltLength(config.SCrypt.SaltLength),
)
case hashBCrypt:
hash = crypt.NewBcryptHash().
WithVariant(crypt.NewBcryptVariant(config.BCrypt.Variant)).
WithCost(config.BCrypt.Cost)
hash, err = bcrypt.New(
bcrypt.WithVariantName(config.BCrypt.Variant),
bcrypt.WithIterations(config.BCrypt.Cost),
)
default:
return nil, fmt.Errorf("algorithm '%s' is unknown", config.Algorithm)
}
if err != nil {
return nil, fmt.Errorf("failed to initialize hash settings: %w", err)
}
if err = hash.Validate(); err != nil {
return nil, fmt.Errorf("failed to validate hash settings: %w", err)
}

View File

@ -8,6 +8,7 @@ import (
"github.com/asaskevich/govalidator"
"github.com/go-crypt/crypt"
"github.com/go-crypt/crypt/algorithm"
"gopkg.in/yaml.v3"
)
@ -203,7 +204,7 @@ func (m *FileUserDatabase) ToDatabaseModel() (model *DatabaseModel) {
// DatabaseUserDetails is the model of user details in the file database.
type DatabaseUserDetails struct {
Username string
Digest crypt.Digest
Digest algorithm.Digest
Disabled bool
DisplayName string
Email string
@ -308,7 +309,7 @@ type UserDetailsModel struct {
// ToDatabaseUserDetailsModel converts a UserDetailsModel into a *DatabaseUserDetails.
func (m UserDetailsModel) ToDatabaseUserDetailsModel(username string) (model *DatabaseUserDetails, err error) {
var d crypt.Digest
var d algorithm.Digest
if d, err = crypt.Decode(m.HashedPassword); err != nil {
return nil, err

View File

@ -252,7 +252,7 @@ func TestShouldRaiseWhenLoadingDatabaseWithBadSHA512HashesForTheFirstTime(t *tes
provider := NewFileUserProvider(&config)
assert.EqualError(t, provider.StartupCheck(), "error decoding the authentication database: failed to parse hash for user 'john': sha2crypt decode error: provided encoded hash has an invalid option: option 'rounds00000' is invalid")
assert.EqualError(t, provider.StartupCheck(), "error decoding the authentication database: failed to parse hash for user 'john': shacrypt decode error: parameter pair 'rounds00000' is not properly encoded: does not contain kv separator '='")
})
}
@ -263,7 +263,7 @@ func TestShouldRaiseWhenLoadingDatabaseWithBadArgon2idHashSettingsForTheFirstTim
provider := NewFileUserProvider(&config)
assert.EqualError(t, provider.StartupCheck(), "error decoding the authentication database: failed to parse hash for user 'john': argon2 decode error: provided encoded hash has an invalid option: option 'm65536' is invalid")
assert.EqualError(t, provider.StartupCheck(), "error decoding the authentication database: failed to parse hash for user 'john': argon2 decode error: parameter pair 'm65536' is not properly encoded: does not contain kv separator '='")
})
}

View File

@ -5,6 +5,7 @@ import (
"strings"
"github.com/go-crypt/crypt"
"github.com/go-crypt/crypt/algorithm"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
@ -272,8 +273,8 @@ func newCryptoHashValidateCmd() (cmd *cobra.Command) {
func cmdCryptoHashGenerateFinish(cmd *cobra.Command, args []string, flagsMap map[string]string) (err error) {
var (
algorithm string
configs []string
algName string
configs []string
c schema.Password
)
@ -294,25 +295,25 @@ func cmdCryptoHashGenerateFinish(cmd *cobra.Command, args []string, flagsMap map
break
case legacy:
if sha512, _ := cmd.Flags().GetBool(cmdFlagNameSHA512); sha512 {
algorithm = cmdUseHashSHA2Crypt
algName = cmdUseHashSHA2Crypt
} else {
algorithm = cmdUseHashArgon2
algName = cmdUseHashArgon2
}
default:
algorithm = cmd.Use
algName = cmd.Use
}
if c, err = cmdCryptoHashGetConfig(algorithm, configs, cmd.Flags(), flagsMap); err != nil {
if c, err = cmdCryptoHashGetConfig(algName, configs, cmd.Flags(), flagsMap); err != nil {
return err
}
if legacy && algorithm == cmdUseHashArgon2 && cmd.Flags().Changed(cmdFlagNameMemory) {
if legacy && algName == cmdUseHashArgon2 && cmd.Flags().Changed(cmdFlagNameMemory) {
c.Argon2.Memory *= 1024
}
var (
hash crypt.Hash
digest crypt.Digest
hash algorithm.Hash
digest algorithm.Digest
password string
random bool
)

View File

@ -12,7 +12,7 @@ import (
"strings"
"time"
"github.com/go-crypt/crypt"
"github.com/go-crypt/crypt/algorithm/plaintext"
"github.com/mitchellh/mapstructure"
"github.com/authelia/authelia/v4/internal/configuration/schema"
@ -486,7 +486,7 @@ func StringToPrivateKeyHookFunc() mapstructure.DecodeHookFuncType {
}
// StringToPasswordDigestHookFunc decodes a string into a crypt.Digest.
func StringToPasswordDigestHookFunc(plaintext bool) mapstructure.DecodeHookFuncType {
func StringToPasswordDigestHookFunc() mapstructure.DecodeHookFuncType {
return func(f reflect.Type, t reflect.Type, data interface{}) (value interface{}, err error) {
var ptr bool
@ -514,11 +514,11 @@ func StringToPasswordDigestHookFunc(plaintext bool) mapstructure.DecodeHookFuncT
var result *schema.PasswordDigest
if !strings.HasPrefix(dataStr, "$") {
dataStr = fmt.Sprintf(crypt.StorageFormatSimple, crypt.AlgorithmPrefixPlainText, dataStr)
dataStr = fmt.Sprintf(plaintext.EncodingFmt, plaintext.AlgIdentifierPlainText, dataStr)
}
if dataStr != "" {
if result, err = schema.NewPasswordDigest(dataStr, plaintext); err != nil {
if result, err = schema.DecodePasswordDigest(dataStr); err != nil {
return nil, fmt.Errorf(errFmtDecodeHookCouldNotParse, dataStr, prefixType, expectedType.String(), err)
}
}

View File

@ -2,7 +2,6 @@ package configuration
import (
"fmt"
"os"
"path/filepath"
"runtime"
"testing"
@ -58,8 +57,7 @@ func TestKoanfSecretCallbackWithValidSecrets(t *testing.T) {
"AUTHELIA__STORAGE_MYSQL_FAKE_PASSWORD": "storage.mysql.fake_password",
}
dir, err := os.MkdirTemp("", "authelia-test-callbacks")
assert.NoError(t, err)
dir := t.TempDir()
secretOne := filepath.Join(dir, "secert_one")
secretTwo := filepath.Join(dir, "secret_two")
@ -108,8 +106,7 @@ func TestKoanfSecretCallbackShouldErrorOnFSError(t *testing.T) {
"AUTHELIA_THEME": "theme",
}
dir, err := os.MkdirTemp("", "authelia-test-callbacks")
assert.NoError(t, err)
dir := t.TempDir()
secret := filepath.Join(dir, "inaccessible")

View File

@ -66,7 +66,7 @@ func unmarshal(ko *koanf.Koanf, val *schema.StructValidator, path string, o any)
StringToPrivateKeyHookFunc(),
StringToCryptoPrivateKeyHookFunc(),
StringToTLSVersionHookFunc(),
StringToPasswordDigestHookFunc(true),
StringToPasswordDigestHookFunc(),
ToTimeDurationHookFunc(),
),
Metadata: nil,

View File

@ -19,8 +19,7 @@ import (
func TestShouldErrorSecretNotExist(t *testing.T) {
testReset()
dir, err := os.MkdirTemp("", "authelia-test-secret-not-exist")
assert.NoError(t, err)
dir := t.TempDir()
testSetEnv(t, "JWT_SECRET_FILE", filepath.Join(dir, "jwt"))
testSetEnv(t, "DUO_API_SECRET_KEY_FILE", filepath.Join(dir, "duo"))
@ -36,7 +35,7 @@ func TestShouldErrorSecretNotExist(t *testing.T) {
testSetEnv(t, "IDENTITY_PROVIDERS_OIDC_HMAC_SECRET_FILE", filepath.Join(dir, "oidc-hmac"))
val := schema.NewStructValidator()
_, _, err = Load(val, NewEnvironmentSource(DefaultEnvPrefix, DefaultEnvDelimiter), NewSecretsSource(DefaultEnvPrefix, DefaultEnvDelimiter))
_, _, err := Load(val, NewEnvironmentSource(DefaultEnvPrefix, DefaultEnvDelimiter), NewSecretsSource(DefaultEnvPrefix, DefaultEnvDelimiter))
assert.NoError(t, err)
assert.Len(t, val.Warnings(), 0)
@ -162,15 +161,14 @@ func TestShouldRaiseIOErrOnUnreadableFile(t *testing.T) {
testReset()
dir, err := os.MkdirTemp("", "authelia-conf")
assert.NoError(t, err)
dir := t.TempDir()
assert.NoError(t, os.WriteFile(filepath.Join(dir, "myconf.yml"), []byte("server:\n port: 9091\n"), 0000))
cfg := filepath.Join(dir, "myconf.yml")
val := schema.NewStructValidator()
_, _, err = Load(val, NewYAMLFileSource(cfg))
_, _, err := Load(val, NewYAMLFileSource(cfg))
assert.NoError(t, err)
require.Len(t, val.Errors(), 1)
@ -390,14 +388,13 @@ func TestShouldNotReadConfigurationOnFSAccessDenied(t *testing.T) {
testReset()
dir, err := os.MkdirTemp("", "authelia-config")
assert.NoError(t, err)
dir := t.TempDir()
cfg := filepath.Join(dir, "config.yml")
assert.NoError(t, testCreateFile(filepath.Join(dir, "config.yml"), "port: 9091\n", 0000))
val := schema.NewStructValidator()
_, _, err = Load(val, NewYAMLFileSource(cfg))
_, _, err := Load(val, NewYAMLFileSource(cfg))
assert.NoError(t, err)
require.Len(t, val.Errors(), 1)
@ -408,11 +405,10 @@ func TestShouldNotReadConfigurationOnFSAccessDenied(t *testing.T) {
func TestShouldNotLoadDirectoryConfiguration(t *testing.T) {
testReset()
dir, err := os.MkdirTemp("", "authelia-config")
assert.NoError(t, err)
dir := t.TempDir()
val := schema.NewStructValidator()
_, _, err = Load(val, NewYAMLFileSource(dir))
_, _, err := Load(val, NewYAMLFileSource(dir))
assert.NoError(t, err)
require.Len(t, val.Errors(), 1)

View File

@ -191,7 +191,7 @@ var DefaultLDAPAuthenticationBackendConfigurationImplementationActiveDirectory =
UsernameAttribute: "sAMAccountName",
MailAttribute: "mail",
DisplayNameAttribute: "displayName",
GroupsFilter: "(&(member={dn})(sAMAccountType=268435456))",
GroupsFilter: "(&(member={dn})(|(sAMAccountType=268435456)(sAMAccountType=536870912)))",
GroupNameAttribute: "cn",
Timeout: time.Second * 5,
TLS: &TLSConfig{

View File

@ -16,6 +16,8 @@ import (
"time"
"github.com/go-crypt/crypt"
"github.com/go-crypt/crypt/algorithm"
"github.com/go-crypt/crypt/algorithm/plaintext"
)
// NewAddressFromString returns an *Address and error depending on the ability to parse the string as an Address.
@ -110,27 +112,32 @@ func (a Address) Listener() (net.Listener, error) {
return net.Listen(a.Scheme, a.HostPort())
}
// NewPasswordDigest returns a new PasswordDigest.
func NewPasswordDigest(value string, plaintext bool) (digest *PasswordDigest, err error) {
var d crypt.Digest
var cdecoder algorithm.DecoderRegister
switch {
case plaintext:
d, err = crypt.DecodeWithPlainText(value)
default:
d, err = crypt.Decode(value)
// DecodePasswordDigest returns a new PasswordDigest if it can be decoded.
func DecodePasswordDigest(encodedDigest string) (digest *PasswordDigest, err error) {
if cdecoder == nil {
if cdecoder, err = crypt.NewDefaultDecoder(); err != nil {
return nil, fmt.Errorf("failed to initialize decoder: %w", err)
}
if err = plaintext.RegisterDecoderPlainText(cdecoder); err != nil {
return nil, fmt.Errorf("failed to initialize decoder: could not register the plaintext decoder: %w", err)
}
}
if err != nil {
var d algorithm.Digest
if d, err = cdecoder.Decode(encodedDigest); err != nil {
return nil, err
}
return &PasswordDigest{d}, err
return &PasswordDigest{Digest: d}, nil
}
// PasswordDigest is a configuration type for the crypt.Digest.
type PasswordDigest struct {
crypt.Digest
algorithm.Digest
}
// NewX509CertificateChain creates a new *X509CertificateChain from a given string, parsing each PEM block one by one.

View File

@ -13,8 +13,7 @@ import (
)
func TestShouldGenerateConfiguration(t *testing.T) {
dir, err := os.MkdirTemp("", "authelia-config")
assert.NoError(t, err)
dir := t.TempDir()
cfg := filepath.Join(dir, "config.yml")
@ -31,8 +30,7 @@ func TestShouldNotGenerateConfigurationOnFSAccessDenied(t *testing.T) {
t.Skip("skipping test due to being on windows")
}
dir, err := os.MkdirTemp("", "authelia-config")
assert.NoError(t, err)
dir := t.TempDir()
assert.NoError(t, os.Mkdir(filepath.Join(dir, "zero"), 0000))
@ -44,8 +42,7 @@ func TestShouldNotGenerateConfigurationOnFSAccessDenied(t *testing.T) {
}
func TestShouldNotGenerateConfiguration(t *testing.T) {
dir, err := os.MkdirTemp("", "authelia-config")
assert.NoError(t, err)
dir := t.TempDir()
cfg := filepath.Join(dir, "..", "not-a-dir", "config.yml")

View File

@ -5,7 +5,11 @@ import (
"net/url"
"strings"
"github.com/go-crypt/crypt"
"github.com/go-crypt/crypt/algorithm/argon2"
"github.com/go-crypt/crypt/algorithm/bcrypt"
"github.com/go-crypt/crypt/algorithm/pbkdf2"
"github.com/go-crypt/crypt/algorithm/scrypt"
"github.com/go-crypt/crypt/algorithm/shacrypt"
"github.com/authelia/authelia/v4/internal/configuration/schema"
"github.com/authelia/authelia/v4/internal/utils"
@ -91,46 +95,48 @@ func validateFileAuthenticationBackendPasswordConfigArgon2(config *schema.Passwo
switch {
case config.Argon2.Iterations == 0:
config.Argon2.Iterations = schema.DefaultPasswordConfig.Argon2.Iterations
case config.Argon2.Iterations < crypt.Argon2IterationsMin:
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooSmall, hashArgon2, "iterations", config.Argon2.Iterations, crypt.Argon2IterationsMin))
case config.Argon2.Iterations > crypt.Argon2IterationsMax:
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooLarge, hashArgon2, "iterations", config.Argon2.Iterations, crypt.Argon2IterationsMax))
case config.Argon2.Iterations < argon2.IterationsMin:
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooSmall, hashArgon2, "iterations", config.Argon2.Iterations, argon2.IterationsMin))
case config.Argon2.Iterations > argon2.IterationsMax:
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooLarge, hashArgon2, "iterations", config.Argon2.Iterations, argon2.IterationsMax))
}
switch {
case config.Argon2.Parallelism == 0:
config.Argon2.Parallelism = schema.DefaultPasswordConfig.Argon2.Parallelism
case config.Argon2.Parallelism < crypt.Argon2ParallelismMin:
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooSmall, hashArgon2, "parallelism", config.Argon2.Parallelism, crypt.Argon2ParallelismMin))
case config.Argon2.Parallelism > crypt.Argon2ParallelismMax:
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooLarge, hashArgon2, "parallelism", config.Argon2.Parallelism, crypt.Argon2ParallelismMax))
case config.Argon2.Parallelism < argon2.ParallelismMin:
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooSmall, hashArgon2, "parallelism", config.Argon2.Parallelism, argon2.ParallelismMin))
case config.Argon2.Parallelism > argon2.ParallelismMax:
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooLarge, hashArgon2, "parallelism", config.Argon2.Parallelism, argon2.ParallelismMax))
}
switch {
case config.Argon2.Memory == 0:
config.Argon2.Memory = schema.DefaultPasswordConfig.Argon2.Memory
case config.Argon2.Memory < 0:
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooSmall, hashArgon2, "memory", config.Argon2.Parallelism, 1))
case config.Argon2.Memory < (crypt.Argon2MemoryMinParallelismMultiplier * config.Argon2.Parallelism):
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordArgon2MemoryTooLow, config.Argon2.Memory, config.Argon2.Parallelism*crypt.Argon2MemoryMinParallelismMultiplier, config.Argon2.Parallelism, crypt.Argon2MemoryMinParallelismMultiplier))
case config.Argon2.Memory < argon2.MemoryMin:
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooSmall, hashArgon2, "memory", config.Argon2.Memory, argon2.MemoryMin))
case uint64(config.Argon2.Memory) > uint64(argon2.MemoryMax):
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooLarge, hashArgon2, "memory", config.Argon2.Memory, argon2.MemoryMax))
case config.Argon2.Memory < (config.Argon2.Parallelism * argon2.MemoryMinParallelismMultiplier):
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordArgon2MemoryTooLow, config.Argon2.Memory, config.Argon2.Parallelism*argon2.MemoryMinParallelismMultiplier, config.Argon2.Parallelism, argon2.MemoryMinParallelismMultiplier))
}
switch {
case config.Argon2.KeyLength == 0:
config.Argon2.KeyLength = schema.DefaultPasswordConfig.Argon2.KeyLength
case config.Argon2.KeyLength < crypt.Argon2KeySizeMin:
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooSmall, hashArgon2, "key_length", config.Argon2.KeyLength, crypt.Argon2KeySizeMin))
case config.Argon2.KeyLength > crypt.Argon2KeySizeMax:
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooLarge, hashArgon2, "key_length", config.Argon2.KeyLength, crypt.Argon2KeySizeMax))
case config.Argon2.KeyLength < argon2.KeyLengthMin:
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooSmall, hashArgon2, "key_length", config.Argon2.KeyLength, argon2.KeyLengthMin))
case config.Argon2.KeyLength > argon2.KeyLengthMax:
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooLarge, hashArgon2, "key_length", config.Argon2.KeyLength, argon2.KeyLengthMax))
}
switch {
case config.Argon2.SaltLength == 0:
config.Argon2.SaltLength = schema.DefaultPasswordConfig.Argon2.SaltLength
case config.Argon2.SaltLength < crypt.Argon2SaltSizeMin:
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooSmall, hashArgon2, "salt_length", config.Argon2.SaltLength, crypt.Argon2SaltSizeMin))
case config.Argon2.SaltLength > crypt.Argon2SaltSizeMax:
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooLarge, hashArgon2, "salt_length", config.Argon2.SaltLength, crypt.Argon2SaltSizeMax))
case config.Argon2.SaltLength < argon2.SaltLengthMin:
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooSmall, hashArgon2, "salt_length", config.Argon2.SaltLength, argon2.SaltLengthMin))
case config.Argon2.SaltLength > argon2.SaltLengthMax:
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooLarge, hashArgon2, "salt_length", config.Argon2.SaltLength, argon2.SaltLengthMax))
}
}
@ -147,19 +153,19 @@ func validateFileAuthenticationBackendPasswordConfigSHA2Crypt(config *schema.Pas
switch {
case config.SHA2Crypt.Iterations == 0:
config.SHA2Crypt.Iterations = schema.DefaultPasswordConfig.SHA2Crypt.Iterations
case config.SHA2Crypt.Iterations < crypt.SHA2CryptIterationsMin:
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooSmall, hashSHA2Crypt, "iterations", config.SHA2Crypt.Iterations, crypt.SHA2CryptIterationsMin))
case config.SHA2Crypt.Iterations > crypt.SHA2CryptIterationsMax:
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooLarge, hashSHA2Crypt, "iterations", config.SHA2Crypt.Iterations, crypt.SHA2CryptIterationsMax))
case config.SHA2Crypt.Iterations < shacrypt.IterationsMin:
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooSmall, hashSHA2Crypt, "iterations", config.SHA2Crypt.Iterations, shacrypt.IterationsMin))
case config.SHA2Crypt.Iterations > shacrypt.IterationsMax:
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooLarge, hashSHA2Crypt, "iterations", config.SHA2Crypt.Iterations, shacrypt.IterationsMax))
}
switch {
case config.SHA2Crypt.SaltLength == 0:
config.SHA2Crypt.SaltLength = schema.DefaultPasswordConfig.SHA2Crypt.SaltLength
case config.SHA2Crypt.SaltLength < crypt.SHA2CryptSaltSizeMin:
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooSmall, hashSHA2Crypt, "salt_length", config.SHA2Crypt.SaltLength, crypt.SHA2CryptSaltSizeMin))
case config.SHA2Crypt.SaltLength > crypt.SHA2CryptSaltSizeMax:
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooLarge, hashSHA2Crypt, "salt_length", config.SHA2Crypt.SaltLength, crypt.SHA2CryptSaltSizeMax))
case config.SHA2Crypt.SaltLength < shacrypt.SaltLengthMin:
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooSmall, hashSHA2Crypt, "salt_length", config.SHA2Crypt.SaltLength, shacrypt.SaltLengthMin))
case config.SHA2Crypt.SaltLength > shacrypt.SaltLengthMax:
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooLarge, hashSHA2Crypt, "salt_length", config.SHA2Crypt.SaltLength, shacrypt.SaltLengthMax))
}
}
@ -176,19 +182,19 @@ func validateFileAuthenticationBackendPasswordConfigPBKDF2(config *schema.Passwo
switch {
case config.PBKDF2.Iterations == 0:
config.PBKDF2.Iterations = schema.DefaultPasswordConfig.PBKDF2.Iterations
case config.PBKDF2.Iterations < crypt.PBKDF2IterationsMin:
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooSmall, hashPBKDF2, "iterations", config.PBKDF2.Iterations, crypt.PBKDF2IterationsMin))
case config.PBKDF2.Iterations > crypt.PBKDF2IterationsMax:
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooLarge, hashPBKDF2, "iterations", config.PBKDF2.Iterations, crypt.PBKDF2IterationsMax))
case config.PBKDF2.Iterations < pbkdf2.IterationsMin:
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooSmall, hashPBKDF2, "iterations", config.PBKDF2.Iterations, pbkdf2.IterationsMin))
case config.PBKDF2.Iterations > pbkdf2.IterationsMax:
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooLarge, hashPBKDF2, "iterations", config.PBKDF2.Iterations, pbkdf2.IterationsMax))
}
switch {
case config.PBKDF2.SaltLength == 0:
config.PBKDF2.SaltLength = schema.DefaultPasswordConfig.PBKDF2.SaltLength
case config.PBKDF2.SaltLength < crypt.PBKDF2SaltSizeMin:
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooSmall, hashPBKDF2, "salt_length", config.PBKDF2.SaltLength, crypt.PBKDF2SaltSizeMin))
case config.PBKDF2.SaltLength > crypt.PBKDF2SaltSizeMax:
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooLarge, hashPBKDF2, "salt_length", config.PBKDF2.SaltLength, crypt.PBKDF2SaltSizeMax))
case config.PBKDF2.SaltLength < pbkdf2.SaltLengthMin:
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooSmall, hashPBKDF2, "salt_length", config.PBKDF2.SaltLength, pbkdf2.SaltLengthMin))
case config.PBKDF2.SaltLength > pbkdf2.SaltLengthMax:
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooLarge, hashPBKDF2, "salt_length", config.PBKDF2.SaltLength, pbkdf2.SaltLengthMax))
}
}
@ -205,53 +211,58 @@ func validateFileAuthenticationBackendPasswordConfigBCrypt(config *schema.Passwo
switch {
case config.BCrypt.Cost == 0:
config.BCrypt.Cost = schema.DefaultPasswordConfig.BCrypt.Cost
case config.BCrypt.Cost < crypt.BcryptCostMin:
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooSmall, hashBCrypt, "cost", config.BCrypt.Cost, crypt.BcryptCostMin))
case config.BCrypt.Cost > crypt.BcryptCostMax:
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooLarge, hashBCrypt, "cost", config.BCrypt.Cost, crypt.BcryptCostMax))
case config.BCrypt.Cost < bcrypt.IterationsMin:
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooSmall, hashBCrypt, "cost", config.BCrypt.Cost, bcrypt.IterationsMin))
case config.BCrypt.Cost > bcrypt.IterationsMax:
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooLarge, hashBCrypt, "cost", config.BCrypt.Cost, bcrypt.IterationsMax))
}
}
//nolint:gocyclo
func validateFileAuthenticationBackendPasswordConfigSCrypt(config *schema.Password, validator *schema.StructValidator) {
switch {
case config.SCrypt.Iterations == 0:
config.SCrypt.Iterations = schema.DefaultPasswordConfig.SCrypt.Iterations
case config.SCrypt.Iterations < crypt.ScryptIterationsMin:
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooSmall, hashSCrypt, "iterations", config.SCrypt.Iterations, crypt.ScryptIterationsMin))
case config.SCrypt.Iterations < scrypt.IterationsMin:
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooSmall, hashSCrypt, "iterations", config.SCrypt.Iterations, scrypt.IterationsMin))
case config.SCrypt.Iterations > scrypt.IterationsMax:
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooLarge, hashSCrypt, "iterations", config.SCrypt.Iterations, scrypt.IterationsMax))
}
switch {
case config.SCrypt.BlockSize == 0:
config.SCrypt.BlockSize = schema.DefaultPasswordConfig.SCrypt.BlockSize
case config.SCrypt.BlockSize < crypt.ScryptBlockSizeMin:
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooSmall, hashSCrypt, "block_size", config.SCrypt.BlockSize, crypt.ScryptBlockSizeMin))
case config.SCrypt.BlockSize > crypt.ScryptBlockSizeMax:
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooLarge, hashSCrypt, "block_size", config.SCrypt.BlockSize, crypt.ScryptBlockSizeMax))
case config.SCrypt.BlockSize < scrypt.BlockSizeMin:
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooSmall, hashSCrypt, "block_size", config.SCrypt.BlockSize, scrypt.BlockSizeMin))
case config.SCrypt.BlockSize > scrypt.BlockSizeMax:
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooLarge, hashSCrypt, "block_size", config.SCrypt.BlockSize, scrypt.BlockSizeMax))
}
switch {
case config.SCrypt.Parallelism == 0:
config.SCrypt.Parallelism = schema.DefaultPasswordConfig.SCrypt.Parallelism
case config.SCrypt.Parallelism < crypt.ScryptParallelismMin:
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooSmall, hashSCrypt, "parallelism", config.SCrypt.Parallelism, crypt.ScryptParallelismMin))
case config.SCrypt.Parallelism < scrypt.ParallelismMin:
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooSmall, hashSCrypt, "parallelism", config.SCrypt.Parallelism, scrypt.ParallelismMin))
case config.SCrypt.Parallelism > scrypt.ParallelismMax:
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooLarge, hashSCrypt, "parallelism", config.SCrypt.Parallelism, scrypt.ParallelismMax))
}
switch {
case config.SCrypt.KeyLength == 0:
config.SCrypt.KeyLength = schema.DefaultPasswordConfig.SCrypt.KeyLength
case config.SCrypt.KeyLength < crypt.ScryptKeySizeMin:
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooSmall, hashSCrypt, "key_length", config.SCrypt.KeyLength, crypt.ScryptKeySizeMin))
case config.SCrypt.KeyLength > crypt.ScryptKeySizeMax:
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooLarge, hashSCrypt, "key_length", config.SCrypt.KeyLength, crypt.ScryptKeySizeMax))
case config.SCrypt.KeyLength < scrypt.KeyLengthMin:
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooSmall, hashSCrypt, "key_length", config.SCrypt.KeyLength, scrypt.KeyLengthMin))
case config.SCrypt.KeyLength > scrypt.KeyLengthMax:
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooLarge, hashSCrypt, "key_length", config.SCrypt.KeyLength, scrypt.KeyLengthMax))
}
switch {
case config.SCrypt.SaltLength == 0:
config.SCrypt.SaltLength = schema.DefaultPasswordConfig.SCrypt.SaltLength
case config.SCrypt.SaltLength < crypt.ScryptSaltSizeMin:
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooSmall, hashSCrypt, "salt_length", config.SCrypt.SaltLength, crypt.ScryptSaltSizeMin))
case config.SCrypt.SaltLength > crypt.ScryptSaltSizeMax:
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooLarge, hashSCrypt, "salt_length", config.SCrypt.SaltLength, crypt.ScryptSaltSizeMax))
case config.SCrypt.SaltLength < scrypt.SaltLengthMin:
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooSmall, hashSCrypt, "salt_length", config.SCrypt.SaltLength, scrypt.SaltLengthMin))
case config.SCrypt.SaltLength > scrypt.SaltLengthMax:
validator.Push(fmt.Errorf(errFmtFileAuthBackendPasswordOptionTooLarge, hashSCrypt, "salt_length", config.SCrypt.SaltLength, scrypt.SaltLengthMax))
}
}

View File

@ -409,18 +409,22 @@ func (suite *FileBasedAuthenticationBackend) TestShouldRaiseErrorWhenSCryptOptio
}
func (suite *FileBasedAuthenticationBackend) TestShouldRaiseErrorWhenSCryptOptionsTooHigh() {
suite.config.File.Password.SCrypt.Iterations = 59
suite.config.File.Password.SCrypt.BlockSize = 360287970189639672
suite.config.File.Password.SCrypt.Parallelism = 1073741825
suite.config.File.Password.SCrypt.KeyLength = 1374389534409
suite.config.File.Password.SCrypt.SaltLength = 2147483647
ValidateAuthenticationBackend(&suite.config, suite.validator)
suite.Assert().Len(suite.validator.Warnings(), 0)
suite.Require().Len(suite.validator.Errors(), 3)
suite.Require().Len(suite.validator.Errors(), 5)
suite.Assert().EqualError(suite.validator.Errors()[0], "authentication_backend: file: password: scrypt: option 'block_size' is configured as '360287970189639672' but must be less than or equal to '36028797018963967'")
suite.Assert().EqualError(suite.validator.Errors()[1], "authentication_backend: file: password: scrypt: option 'key_length' is configured as '1374389534409' but must be less than or equal to '137438953440'")
suite.Assert().EqualError(suite.validator.Errors()[2], "authentication_backend: file: password: scrypt: option 'salt_length' is configured as '2147483647' but must be less than or equal to '1024'")
suite.Assert().EqualError(suite.validator.Errors()[0], "authentication_backend: file: password: scrypt: option 'iterations' is configured as '59' but must be less than or equal to '58'")
suite.Assert().EqualError(suite.validator.Errors()[1], "authentication_backend: file: password: scrypt: option 'block_size' is configured as '360287970189639672' but must be less than or equal to '36028797018963967'")
suite.Assert().EqualError(suite.validator.Errors()[2], "authentication_backend: file: password: scrypt: option 'parallelism' is configured as '1073741825' but must be less than or equal to '1073741823'")
suite.Assert().EqualError(suite.validator.Errors()[3], "authentication_backend: file: password: scrypt: option 'key_length' is configured as '1374389534409' but must be less than or equal to '137438953440'")
suite.Assert().EqualError(suite.validator.Errors()[4], "authentication_backend: file: password: scrypt: option 'salt_length' is configured as '2147483647' but must be less than or equal to '1024'")
}
func (suite *FileBasedAuthenticationBackend) TestShouldRaiseErrorWhenArgon2OptionsTooLow() {
@ -437,13 +441,14 @@ func (suite *FileBasedAuthenticationBackend) TestShouldRaiseErrorWhenArgon2Optio
suite.Assert().EqualError(suite.validator.Errors()[0], "authentication_backend: file: password: argon2: option 'iterations' is configured as '-1' but must be greater than or equal to '1'")
suite.Assert().EqualError(suite.validator.Errors()[1], "authentication_backend: file: password: argon2: option 'parallelism' is configured as '-1' but must be greater than or equal to '1'")
suite.Assert().EqualError(suite.validator.Errors()[2], "authentication_backend: file: password: argon2: option 'memory' is configured as '-1' but must be greater than or equal to '1'")
suite.Assert().EqualError(suite.validator.Errors()[2], "authentication_backend: file: password: argon2: option 'memory' is configured as '-1' but must be greater than or equal to '8'")
suite.Assert().EqualError(suite.validator.Errors()[3], "authentication_backend: file: password: argon2: option 'key_length' is configured as '1' but must be greater than or equal to '4'")
suite.Assert().EqualError(suite.validator.Errors()[4], "authentication_backend: file: password: argon2: option 'salt_length' is configured as '-1' but must be greater than or equal to '1'")
}
func (suite *FileBasedAuthenticationBackend) TestShouldRaiseErrorWhenArgon2OptionsTooHigh() {
suite.config.File.Password.Argon2.Iterations = 9999999999
suite.config.File.Password.Argon2.Memory = 4294967296
suite.config.File.Password.Argon2.Parallelism = 16777216
suite.config.File.Password.Argon2.KeyLength = 9999999998
suite.config.File.Password.Argon2.SaltLength = 9999999997
@ -455,6 +460,7 @@ func (suite *FileBasedAuthenticationBackend) TestShouldRaiseErrorWhenArgon2Optio
suite.Assert().EqualError(suite.validator.Errors()[0], "authentication_backend: file: password: argon2: option 'iterations' is configured as '9999999999' but must be less than or equal to '2147483647'")
suite.Assert().EqualError(suite.validator.Errors()[1], "authentication_backend: file: password: argon2: option 'parallelism' is configured as '16777216' but must be less than or equal to '16777215'")
suite.Assert().EqualError(suite.validator.Errors()[2], "authentication_backend: file: password: argon2: option 'memory' is configured as '4294967296' but must be less than or equal to '4294967295'")
suite.Assert().EqualError(suite.validator.Errors()[3], "authentication_backend: file: password: argon2: option 'key_length' is configured as '9999999998' but must be less than or equal to '2147483647'")
suite.Assert().EqualError(suite.validator.Errors()[4], "authentication_backend: file: password: argon2: option 'salt_length' is configured as '9999999997' but must be less than or equal to '2147483647'")
}
@ -468,7 +474,19 @@ func (suite *FileBasedAuthenticationBackend) TestShouldRaiseErrorWhenArgon2Memor
suite.Assert().Len(suite.validator.Warnings(), 0)
suite.Require().Len(suite.validator.Errors(), 1)
suite.Assert().EqualError(suite.validator.Errors()[0], "authentication_backend: file: password: argon2: option 'memory' is configured as '4' but must be greater than or equal to '32' or '4' (the value of 'parallelism) multiplied by '8'")
suite.Assert().EqualError(suite.validator.Errors()[0], "authentication_backend: file: password: argon2: option 'memory' is configured as '4' but must be greater than or equal to '8'")
}
func (suite *FileBasedAuthenticationBackend) TestShouldRaiseErrorWhenArgon2MemoryTooLowMultiplier() {
suite.config.File.Password.Argon2.Memory = 8
suite.config.File.Password.Argon2.Parallelism = 4
ValidateAuthenticationBackend(&suite.config, suite.validator)
suite.Assert().Len(suite.validator.Warnings(), 0)
suite.Require().Len(suite.validator.Errors(), 1)
suite.Assert().EqualError(suite.validator.Errors()[0], "authentication_backend: file: password: argon2: option 'memory' is configured as '8' but must be greater than or equal to '32' or '4' (the value of 'parallelism) multiplied by '8'")
}
func (suite *FileBasedAuthenticationBackend) TestShouldRaiseErrorWhenBadAlgorithmDefined() {

View File

@ -838,7 +838,7 @@ func TestValidateOIDCClientRedirectURIsSupportingPrivateUseURISchemes(t *testing
}
func MustDecodeSecret(value string) *schema.PasswordDigest {
if secret, err := schema.NewPasswordDigest(value, true); err != nil {
if secret, err := schema.DecodePasswordDigest(value); err != nil {
panic(err)
} else {
return secret

View File

@ -52,13 +52,7 @@ func OpenIDConnectAuthorization(ctx *middlewares.AutheliaCtx, rw http.ResponseWr
return
}
if issuer, err = ctx.IssuerURL(); err != nil {
ctx.Logger.Errorf("Authorization Request with id '%s' on client with id '%s' could not be processed: error occurred determining issuer: %+v", requester.GetID(), clientID, err)
ctx.Providers.OpenIDConnect.WriteAuthorizeError(ctx, rw, requester, oidc.ErrIssuerCouldNotDerive)
return
}
issuer = ctx.RootURL()
userSession := ctx.GetSession()

View File

@ -130,12 +130,7 @@ func OpenIDConnectConsentPOST(ctx *middlewares.AutheliaCtx) {
query url.Values
)
if redirectURI, err = ctx.IssuerURL(); err != nil {
ctx.Logger.Errorf("Failed to parse the consent redirect URL: %+v", err)
ctx.SetJSONError(messageOperationFailed)
return
}
redirectURI = ctx.RootURL()
if query, err = url.ParseQuery(consent.Form); err != nil {
ctx.Logger.Errorf("Failed to parse the consent form values: %+v", err)

View File

@ -20,13 +20,7 @@ func OpenIDConnectConfigurationWellKnownGET(ctx *middlewares.AutheliaCtx) {
err error
)
if issuer, err = ctx.IssuerURL(); err != nil {
ctx.Logger.Errorf("Error occurred determining OpenID Connect issuer details: %+v", err)
ctx.ReplyStatusCode(fasthttp.StatusBadRequest)
return
}
issuer = ctx.RootURL()
wellKnown := ctx.Providers.OpenIDConnect.GetOpenIDConnectWellKnownConfiguration(issuer.String())
@ -52,13 +46,7 @@ func OAuthAuthorizationServerWellKnownGET(ctx *middlewares.AutheliaCtx) {
err error
)
if issuer, err = ctx.IssuerURL(); err != nil {
ctx.Logger.Errorf("Error occurred determining OpenID Connect issuer details: %+v", err)
ctx.ReplyStatusCode(fasthttp.StatusBadRequest)
return
}
issuer = ctx.RootURL()
wellKnown := ctx.Providers.OpenIDConnect.GetOAuth2WellKnownConfiguration(issuer.String())

View File

@ -144,11 +144,7 @@ func handleOIDCWorkflowResponseWithTargetURL(ctx *middlewares.AutheliaCtx, targe
return
}
if issuerURL, err = ctx.IssuerURL(); err != nil {
ctx.Error(fmt.Errorf("unable to get issuer for redirection: %w", err), messageAuthenticationFailed)
return
}
issuerURL = ctx.RootURL()
if targetURL.Host != issuerURL.Host {
ctx.Error(fmt.Errorf("unable to redirect to '%s': target host '%s' does not match expected issuer host '%s'", targetURL, targetURL.Host, issuerURL.Host), messageAuthenticationFailed)
@ -221,11 +217,7 @@ func handleOIDCWorkflowResponseWithID(ctx *middlewares.AutheliaCtx, id string) {
form url.Values
)
if targetURL, err = ctx.IssuerURL(); err != nil {
ctx.Error(fmt.Errorf("unable to get issuer for redirection: %w", err), messageAuthenticationFailed)
return
}
targetURL = ctx.RootURL()
if form, err = consent.GetForm(); err != nil {
ctx.Error(fmt.Errorf("unable to get authorization form values from consent session with challenge id '%s': %w", consent.ChallengeID, err), messageAuthenticationFailed)

View File

@ -3,7 +3,6 @@ package logging
import (
"fmt"
"io"
"log"
"os"
"runtime"
"testing"
@ -16,15 +15,10 @@ import (
)
func TestShouldWriteLogsToFile(t *testing.T) {
dir, err := os.MkdirTemp("/tmp", "logs-dir")
if err != nil {
log.Fatal(err)
}
defer os.RemoveAll(dir)
dir := t.TempDir()
path := fmt.Sprintf("%s/authelia.log", dir)
err = InitializeLogger(schema.LogConfiguration{Format: "text", FilePath: path, KeepStdout: false}, false)
err := InitializeLogger(schema.LogConfiguration{Format: "text", FilePath: path, KeepStdout: false}, false)
require.NoError(t, err)
Logger().Info("This is a test")
@ -39,15 +33,10 @@ func TestShouldWriteLogsToFile(t *testing.T) {
}
func TestShouldWriteLogsToFileAndStdout(t *testing.T) {
dir, err := os.MkdirTemp("/tmp", "logs-dir")
if err != nil {
log.Fatal(err)
}
defer os.RemoveAll(dir)
dir := t.TempDir()
path := fmt.Sprintf("%s/authelia.log", dir)
err = InitializeLogger(schema.LogConfiguration{Format: "text", FilePath: path, KeepStdout: true}, false)
err := InitializeLogger(schema.LogConfiguration{Format: "text", FilePath: path, KeepStdout: true}, false)
require.NoError(t, err)
Logger().Info("This is a test")
@ -62,15 +51,10 @@ func TestShouldWriteLogsToFileAndStdout(t *testing.T) {
}
func TestShouldFormatLogsAsJSON(t *testing.T) {
dir, err := os.MkdirTemp("/tmp", "logs-dir")
if err != nil {
log.Fatal(err)
}
defer os.RemoveAll(dir)
dir := t.TempDir()
path := fmt.Sprintf("%s/authelia.log", dir)
err = InitializeLogger(schema.LogConfiguration{Format: "json", FilePath: path, KeepStdout: false}, false)
err := InitializeLogger(schema.LogConfiguration{Format: "json", FilePath: path, KeepStdout: false}, false)
require.NoError(t, err)
Logger().Info("This is a test")

View File

@ -5,7 +5,6 @@ import (
"fmt"
"net"
"net/url"
"path"
"strings"
"github.com/asaskevich/govalidator"
@ -81,7 +80,7 @@ func (ctx *AutheliaCtx) ReplyError(err error, message string) {
ctx.Logger.Error(marshalErr)
}
ctx.SetContentTypeBytes(contentTypeApplicationJSON)
ctx.SetContentTypeApplicationJSON()
ctx.SetBody(b)
ctx.Logger.Debug(err)
}
@ -90,7 +89,7 @@ func (ctx *AutheliaCtx) ReplyError(err error, message string) {
func (ctx *AutheliaCtx) ReplyStatusCode(statusCode int) {
ctx.Response.Reset()
ctx.SetStatusCode(statusCode)
ctx.SetContentTypeBytes(contentTypeTextPlain)
ctx.SetContentTypeTextPlain()
ctx.SetBodyString(fmt.Sprintf("%d %s", statusCode, fasthttp.StatusMessage(statusCode)))
}
@ -108,7 +107,7 @@ func (ctx *AutheliaCtx) ReplyJSON(data any, statusCode int) (err error) {
ctx.SetStatusCode(statusCode)
}
ctx.SetContentTypeBytes(contentTypeApplicationJSON)
ctx.SetContentTypeApplicationJSON()
ctx.SetBody(body)
return nil
@ -145,7 +144,7 @@ func (ctx *AutheliaCtx) XForwardedProto() (proto []byte) {
}
// XForwardedMethod return the content of the X-Forwarded-Method header.
func (ctx *AutheliaCtx) XForwardedMethod() (method []byte) {
func (ctx *AutheliaCtx) XForwardedMethod() []byte {
return ctx.RequestCtx.Request.Header.PeekBytes(headerXForwardedMethod)
}
@ -171,79 +170,61 @@ func (ctx *AutheliaCtx) XForwardedURI() (uri []byte) {
return uri
}
// XAutheliaURL return the content of the X-Authelia-URL header.
func (ctx *AutheliaCtx) XAutheliaURL() (autheliaURL []byte) {
// XOriginalURL returns the content of the X-Original-URL header.
func (ctx *AutheliaCtx) XOriginalURL() []byte {
return ctx.RequestCtx.Request.Header.PeekBytes(headerXOriginalURL)
}
// XOriginalMethod return the content of the X-Original-Method header.
func (ctx *AutheliaCtx) XOriginalMethod() []byte {
return ctx.RequestCtx.Request.Header.PeekBytes(headerXOriginalMethod)
}
// XAutheliaURL return the content of the X-Authelia-URL header which is used to communicate the location of the
// portal when using proxies like Envoy.
func (ctx *AutheliaCtx) XAutheliaURL() []byte {
return ctx.RequestCtx.Request.Header.PeekBytes(headerXAutheliaURL)
}
// QueryArgRedirect return the content of the rd query argument.
func (ctx *AutheliaCtx) QueryArgRedirect() (val []byte) {
return ctx.RequestCtx.QueryArgs().PeekBytes(queryArgRedirect)
func (ctx *AutheliaCtx) QueryArgRedirect() []byte {
return ctx.RequestCtx.QueryArgs().PeekBytes(qryArgRedirect)
}
// BasePath returns the base_url as per the path visited by the client.
func (ctx *AutheliaCtx) BasePath() (base string) {
func (ctx *AutheliaCtx) BasePath() string {
if baseURL := ctx.UserValueBytes(UserValueKeyBaseURL); baseURL != nil {
return baseURL.(string)
}
return base
return ""
}
// ExternalRootURL gets the X-Forwarded-Proto, X-Forwarded-Host headers and the BasePath and forms them into a URL.
func (ctx *AutheliaCtx) ExternalRootURL() (string, error) {
protocol := ctx.XForwardedProto()
if protocol == nil {
return "", errMissingXForwardedProto
// BasePathSlash is the same as BasePath but returns a final slash as well.
func (ctx *AutheliaCtx) BasePathSlash() string {
if baseURL := ctx.UserValueBytes(UserValueKeyBaseURL); baseURL != nil {
return baseURL.(string) + strSlash
}
host := ctx.XForwardedHost()
if host == nil {
return "", errMissingXForwardedHost
}
externalRootURL := fmt.Sprintf("%s://%s", protocol, host)
if base := ctx.BasePath(); base != "" {
externalBaseURL, err := url.ParseRequestURI(externalRootURL)
if err != nil {
return "", err
}
externalBaseURL.Path = path.Join(externalBaseURL.Path, base)
return externalBaseURL.String(), nil
}
return externalRootURL, nil
return strSlash
}
// IssuerURL returns the expected Issuer.
func (ctx *AutheliaCtx) IssuerURL() (issuerURL *url.URL, err error) {
issuerURL = &url.URL{
Scheme: "https",
// RootURL returns the Root URL.
func (ctx *AutheliaCtx) RootURL() (issuerURL *url.URL) {
return &url.URL{
Scheme: string(ctx.XForwardedProto()),
Host: string(ctx.XForwardedHost()),
Path: ctx.BasePath(),
}
if scheme := ctx.XForwardedProto(); scheme != nil {
issuerURL.Scheme = string(scheme)
}
if host := ctx.XForwardedHost(); len(host) != 0 {
issuerURL.Host = string(host)
} else {
return nil, errMissingXForwardedHost
}
if base := ctx.BasePath(); base != "" {
issuerURL.Path = path.Join(issuerURL.Path, base)
}
return issuerURL, nil
}
// XOriginalURL return the content of the X-Original-URL header.
func (ctx *AutheliaCtx) XOriginalURL() []byte {
return ctx.RequestCtx.Request.Header.PeekBytes(headerXOriginalURL)
// RootURLSlash is the same as RootURL but includes a final slash as well.
func (ctx *AutheliaCtx) RootURLSlash() (issuerURL *url.URL) {
return &url.URL{
Scheme: string(ctx.XForwardedProto()),
Host: string(ctx.XForwardedHost()),
Path: ctx.BasePathSlash(),
}
}
// GetSession return the user session. Any update will be saved in cache.
@ -264,7 +245,7 @@ func (ctx *AutheliaCtx) SaveSession(userSession session.UserSession) error {
// ReplyOK is a helper method to reply ok.
func (ctx *AutheliaCtx) ReplyOK() {
ctx.SetContentTypeBytes(contentTypeApplicationJSON)
ctx.SetContentTypeApplicationJSON()
ctx.SetBody(okMessageBytes)
}
@ -377,7 +358,7 @@ func (ctx *AutheliaCtx) SpecialRedirect(uri string, statusCode int) {
statusCode = fasthttp.StatusFound
}
ctx.SetContentTypeBytes(contentTypeTextHTML)
ctx.SetContentTypeTextHTML()
ctx.SetStatusCode(statusCode)
u := fasthttp.AcquireURI()
@ -400,3 +381,18 @@ func (ctx *AutheliaCtx) RecordAuthentication(success, regulated bool, method str
ctx.Providers.Metrics.RecordAuthentication(success, regulated, method)
}
// SetContentTypeTextPlain efficiently sets the Content-Type header to 'text/plain; charset=utf-8'.
func (ctx *AutheliaCtx) SetContentTypeTextPlain() {
ctx.SetContentTypeBytes(contentTypeTextPlain)
}
// SetContentTypeTextHTML efficiently sets the Content-Type header to 'text/html; charset=utf-8'.
func (ctx *AutheliaCtx) SetContentTypeTextHTML() {
ctx.SetContentTypeBytes(contentTypeTextHTML)
}
// SetContentTypeApplicationJSON efficiently sets the Content-Type header to 'application/json; charset=utf-8'.
func (ctx *AutheliaCtx) SetContentTypeApplicationJSON() {
ctx.SetContentTypeBytes(contentTypeApplicationJSON)
}

View File

@ -21,7 +21,6 @@ func TestIssuerURL(t *testing.T) {
name string
proto, host, base string
expected string
err string
}{
{
name: "Standard",
@ -36,7 +35,7 @@ func TestIssuerURL(t *testing.T) {
{
name: "NoHost",
proto: "https", host: "", base: "",
err: "Missing header X-Forwarded-Host",
expected: "https:",
},
}
@ -52,21 +51,14 @@ func TestIssuerURL(t *testing.T) {
mock.Ctx.SetUserValue("base_url", tc.base)
}
actual, err := mock.Ctx.IssuerURL()
actual := mock.Ctx.RootURL()
switch tc.err {
case "":
assert.NoError(t, err)
require.NotNil(t, actual)
require.NotNil(t, actual)
assert.Equal(t, tc.expected, actual.String())
assert.Equal(t, tc.proto, actual.Scheme)
assert.Equal(t, tc.host, actual.Host)
assert.Equal(t, tc.base, actual.Path)
default:
assert.EqualError(t, err, tc.err)
assert.Nil(t, actual)
}
assert.Equal(t, tc.expected, actual.String())
assert.Equal(t, tc.proto, actual.Scheme)
assert.Equal(t, tc.host, actual.Host)
assert.Equal(t, tc.base, actual.Path)
})
}
}

View File

@ -20,6 +20,7 @@ var (
headerXForwardedURI = []byte("X-Forwarded-URI")
headerXOriginalURL = []byte("X-Original-URL")
headerXOriginalMethod = []byte("X-Original-Method")
headerXForwardedMethod = []byte("X-Forwarded-Method")
headerVary = []byte(fasthttp.HeaderVary)
@ -67,13 +68,17 @@ var (
const (
strProtoHTTPS = "https"
strProtoHTTP = "http"
strSlash = "/"
queryArgRedirect = "rd"
queryArgToken = "token"
)
var (
protoHTTPS = []byte(strProtoHTTPS)
protoHTTP = []byte(strProtoHTTP)
queryArgRedirect = []byte("rd")
qryArgRedirect = []byte(queryArgRedirect)
// UserValueKeyBaseURL is the User Value key where we store the Base URL.
UserValueKeyBaseURL = []byte("base_url")

View File

@ -5,6 +5,7 @@ import (
"encoding/json"
"fmt"
"net/mail"
"path"
"time"
"github.com/golang-jwt/jwt/v4"
@ -62,7 +63,7 @@ func IdentityVerificationStart(args IdentityVerificationStartArgs, delayFunc Tim
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
ss, err := token.SignedString([]byte(ctx.Configuration.JWTSecret))
signedToken, err := token.SignedString([]byte(ctx.Configuration.JWTSecret))
if err != nil {
ctx.Error(err, messageOperationFailed)
return
@ -73,23 +74,23 @@ func IdentityVerificationStart(args IdentityVerificationStartArgs, delayFunc Tim
return
}
var (
uri string
)
if uri, err = ctx.ExternalRootURL(); err != nil {
ctx.Error(err, messageOperationFailed)
return
}
disableHTML := false
if ctx.Configuration.Notifier.SMTP != nil {
disableHTML = ctx.Configuration.Notifier.SMTP.DisableHTMLEmails
}
linkURL := ctx.RootURL()
query := linkURL.Query()
query.Set(queryArgToken, signedToken)
linkURL.Path = path.Join(linkURL.Path, args.TargetEndpoint)
linkURL.RawQuery = query.Encode()
values := templates.EmailIdentityVerificationValues{
Title: args.MailTitle,
LinkURL: fmt.Sprintf("%s%s?token=%s", uri, args.TargetEndpoint, ss),
LinkURL: linkURL.String(),
LinkText: args.MailButtonContent,
DisplayName: identity.DisplayName,
RemoteIP: ctx.RemoteIP().String(),

Some files were not shown because too many files have changed in this diff Show More