providers/proxy: add setting to intercept authorization header (#4457)

* add setting to intercept authorization header

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* rename to intercept_header_auth

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
This commit is contained in:
Jens L 2023-01-17 18:56:48 +01:00 committed by GitHub
parent c73fce4f58
commit 23c69c456a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 70 additions and 9 deletions

View file

@ -88,6 +88,7 @@ class ProxyProviderSerializer(ProviderSerializer):
"basic_auth_password_attribute",
"basic_auth_user_attribute",
"mode",
"intercept_header_auth",
"redirect_uris",
"cookie_domain",
"jwks_sources",
@ -171,6 +172,7 @@ class ProxyOutpostConfigSerializer(ModelSerializer):
"mode",
"cookie_domain",
"token_validity",
"intercept_header_auth",
"scopes_to_request",
"assigned_application_slug",
"assigned_application_name",

View file

@ -0,0 +1,21 @@
# Generated by Django 4.1.5 on 2023-01-17 10:28
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("authentik_providers_proxy", "0001_squashed_0014_proxy_v2"),
]
operations = [
migrations.AddField(
model_name="proxyprovider",
name="intercept_header_auth",
field=models.BooleanField(
default=True,
help_text="When enabled, this provider will intercept the authorization header and authenticate requests based on its value.",
),
),
]

View file

@ -74,6 +74,13 @@ class ProxyProvider(OutpostModel, OAuth2Provider):
),
)
intercept_header_auth = models.BooleanField(
default=True,
help_text=_(
"When enabled, this provider will intercept the authorization header and authenticate "
"requests based on its value."
),
)
basic_auth_enabled = models.BooleanField(
default=False,
verbose_name=_("Set HTTP-Basic Authentication"),

View file

@ -1,7 +1,6 @@
package application
import (
"fmt"
"net/http"
"net/url"
"path"
@ -35,12 +34,11 @@ func (a *Application) redirectToStart(rw http.ResponseWriter, r *http.Request) {
if err != nil {
a.log.WithError(err).Warning("failed to decode session")
}
if r.Header.Get(constants.HeaderNoRedirect) != "" ||
r.URL.Query().Get(strings.ToLower(constants.HeaderNoRedirect)) != "" {
if r.Header.Get(constants.HeaderAuthorization) != "" && *a.proxyConfig.InterceptHeaderAuth {
rw.WriteHeader(401)
er := a.errorTemplates.Execute(rw, ErrorPageData{
Title: "Unauthenticated",
Message: fmt.Sprintf("Due to '%s' being set, no redirect is performed.", constants.HeaderNoRedirect),
Message: "Due to 'Receive header authentication' being set, no redirect is performed.",
ProxyPrefix: "/outpost.goauthentik.io",
})
if er != nil {

View file

@ -8,6 +8,5 @@ const SessionClaims = "claims"
const SessionRedirect = "redirect"
const HeaderAuthorization = "Authorization"
const HeaderNoRedirect = "X-Authentik-No-Redirect"
const AuthBearer = "Bearer "

View file

@ -34363,6 +34363,10 @@ components:
- $ref: '#/components/schemas/ProxyMode'
description: Enable support for forwardAuth in traefik and nginx auth_request.
Exclusive with internal_host.
intercept_header_auth:
type: boolean
description: When enabled, this provider will intercept the authorization
header and authenticate requests based on its value.
cookie_domain:
type: string
jwks_sources:
@ -35681,6 +35685,10 @@ components:
format: double
nullable: true
readOnly: true
intercept_header_auth:
type: boolean
description: When enabled, this provider will intercept the authorization
header and authenticate requests based on its value.
scopes_to_request:
type: array
items:
@ -35782,6 +35790,10 @@ components:
- $ref: '#/components/schemas/ProxyMode'
description: Enable support for forwardAuth in traefik and nginx auth_request.
Exclusive with internal_host.
intercept_header_auth:
type: boolean
description: When enabled, this provider will intercept the authorization
header and authenticate requests based on its value.
redirect_uris:
type: string
readOnly: true
@ -35872,6 +35884,10 @@ components:
- $ref: '#/components/schemas/ProxyMode'
description: Enable support for forwardAuth in traefik and nginx auth_request.
Exclusive with internal_host.
intercept_header_auth:
type: boolean
description: When enabled, this provider will intercept the authorization
header and authenticate requests based on its value.
cookie_domain:
type: string
jwks_sources:

View file

@ -449,6 +449,26 @@ ${this.instance?.skipPathRegex}</textarea
<ak-form-group>
<span slot="header">${t`Authentication settings`}</span>
<div slot="body" class="pf-c-form">
<ak-form-element-horizontal name="interceptHeaderAuth">
<label class="pf-c-switch">
<input
class="pf-c-switch__input"
type="checkbox"
?checked=${first(this.instance?.interceptHeaderAuth, true)}
/>
<span class="pf-c-switch__toggle">
<span class="pf-c-switch__toggle-icon">
<i class="fas fa-check" aria-hidden="true"></i>
</span>
</span>
<span class="pf-c-switch__label"
>${t`Intercept header authentication`}</span
>
</label>
<p class="pf-c-form__helper-text">
${t`When enabled, authentik will intercept the Authorization header to authenticate the request.`}
</p>
</ak-form-element-horizontal>
<ak-form-element-horizontal name="basicAuthEnabled">
<label class="pf-c-switch">
<input

View file

@ -21,11 +21,9 @@ If the user does not have a matching attribute, authentik falls back to using th
## Receiving authentication
By default, when the proxy provider receives credentials that aren't valid for itself, it will start a normal authentication flow, and redirect to the flow start page. Some applications might require a 401 response to prompt for credentials.
By default, when _Intercept header authentication_ is enabled, authentik will intercept the authorization header. If the authorization header value is invalid, an error response will be shown with a 401 status code. Requests without an authorization header will still be redirected to the standard login flow.
To always return a 401 response when authentication headers are missing/invalid, you can either set the `X-Authentik-No-Redirect` header to any value or the query parameter `x-authentik-no-redirect` to any value.
This is the default behaviour as some applications use the Authorization header for themselves, and as such if the proxy provider would check it, these applications would be inaccessible.
If the proxied application requires usage of the "Authorization" header, the setting should be disabled. When this setting is disabled, authentik will still attempt to interpret the "Authorization" header, and fall back to the default behaviour if it can't.
### Receiving HTTP Basic authentication