Skip to content

Commit

Permalink
fix!: The term "scheme" is used properly as defined by RFC9110 (#1042)
Browse files Browse the repository at this point in the history
  • Loading branch information
dadrus authored Nov 17, 2023
1 parent 1615f40 commit aaf4bd3
Show file tree
Hide file tree
Showing 19 changed files with 57 additions and 57 deletions.
4 changes: 2 additions & 2 deletions cmd/validate/test_data/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ mechanisms:
password: bar
token_source:
- header: Authorization
schema: Bearer
scheme: Bearer
assertions:
issuers:
- http://127.0.0.1:4444/
Expand All @@ -63,7 +63,7 @@ mechanisms:
enable_http_cache: true
jwt_source:
- header: Authorization
schema: Bearer
scheme: Bearer
assertions:
audience:
- bla
Expand Down
4 changes: 2 additions & 2 deletions docs/content/docs/configuration/reference/reference.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ mechanisms:
value: VerySecret!
token_source:
- header: Authorization
schema: Bearer
scheme: Bearer
- query_parameter: access_token
- body_parameter: access_token
assertions:
Expand All @@ -209,7 +209,7 @@ mechanisms:
enable_http_cache: true
jwt_source:
- header: Authorization
schema: Bearer
scheme: Bearer
- query_parameter: access_token
- body_parameter: access_token
assertions:
Expand Down
10 changes: 5 additions & 5 deletions docs/content/docs/configuration/reference/types.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ This fallback mechanism can become handy, if different clients of your applicati
[source, yaml]
----
- header: Authorization
schema: Bearer
scheme: Bearer
- query_parameter: access_token
- body_parameter: access_token
----
Expand Down Expand Up @@ -97,9 +97,9 @@ This strategy can retrieve authentication data from a specific HTTP header. Foll
+
The name of the header to use.

* *`schema`*: _string_ (optional)
* *`scheme`*: _string_ (optional)
+
Schema, which should be present in the header value. If specified, but not present in the header value, the authentication data cannot be retrieved, effectively making the affected authenticator feel not responsible for the request.
Scheme, which should be present in the header value. If specified, but not present in the header value, the authentication data cannot be retrieved, effectively making the affected authenticator feel not responsible for the request.

.Header Strategy usage
====
Expand All @@ -109,7 +109,7 @@ Imagine you want Heimdall to verify an access token used to protect your upstrea
[source, yaml]
----
- header: Authorization
schema: Bearer
scheme: Bearer
----
====

Expand Down Expand Up @@ -231,7 +231,7 @@ The scheme for the header added in front of the authentication data value.

.Header strategy configuration
====
The following snippet shows how to configure this strategy to send e.g. a token in a header named "X-ID-Token" with schema "Bearer".
The following snippet shows how to configure this strategy to send e.g. a token in a header named "X-ID-Token" with scheme "Bearer".
[source, yaml]
----
Expand Down
2 changes: 1 addition & 1 deletion docs/content/docs/guides/nginx.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ location = /_auth {
----
<1> Configures NGINX to pass the request to heimdall.
<2> Let NGINX forward the used HTTP method to heimdall.
<3> Let NGINX forward the used HTTP schema to heimdall.
<3> Let NGINX forward the used HTTP scheme to heimdall.
<4> Let NGINX forward the used host to heimdall.
<5> Let NGINX forward the used path and query parameter to heimdall.
====
Expand Down
2 changes: 1 addition & 1 deletion docs/content/docs/operations/security.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ To operate heimdall in a secure way, you should configure heimdall accordingly.

If `trusted_proxies` property is configured (see also the corresponding link:{{< relref "/docs/configuration/services/decision.adoc#_trusted_proxies" >}}[Decision] and link:{{< relref "/docs/configuration/services/proxy.adoc#_trusted_proxies" >}}[Proxy] service configuration options) to let heimdall make use of different HTTP headers to build the URL for rule and HTTP method matching purposes, following logic apply:

* The value for the used HTTP schema is taken from the `X-Forwarded-Proto` header.
* The value for the used HTTP scheme is taken from the `X-Forwarded-Proto` header.
* The value for the used HTTP host and port is taken from the `X-Forwarded-Host` header.
* The value for the used HTTP path is taken either from `X-Forwarded-Uri` or `X-Forwarded-Path` with `X-Forwarded-Uri` taking precedence. Compared to `X-Forwarded-Path`, `X-Forwarded-Uri` does also contain query parameters.
* The value for the used HTTP method is taken from the `X-Forwarded-Method` header.
Expand Down
4 changes: 2 additions & 2 deletions docs/openapi/specification.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -619,7 +619,7 @@ paths:
type: string
- name: X-Forwarded-Proto
in: header
description: Schema to use to build the url to verify access to. If not present defaults to the schema used to operate heimdall.
description: HTTP scheme to use to build the url to verify access to. If not present defaults to the scheme used to operate heimdall.
schema:
type: string
- name: X-Forwarded-Host
Expand Down Expand Up @@ -706,7 +706,7 @@ paths:
type: string
- name: X-Forwarded-Proto
in: header
description: Schema to use to build the url to verify access to. If not present defaults to the schema used to operate heimdall.
description: HTTP scheme to use to build the url to verify access to. If not present defaults to the scheme used to operate heimdall.
schema:
type: string
- name: X-Forwarded-Host
Expand Down
2 changes: 1 addition & 1 deletion example_config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ mechanisms:
enable_http_cache: true
jwt_source:
- header: Authorization
schema: Bearer
scheme: Bearer
assertions:
audience:
- bla
Expand Down
4 changes: 2 additions & 2 deletions internal/config/test_data/test_config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ mechanisms:
password: bar
token_source:
- header: Authorization
schema: Bearer
scheme: Bearer
assertions:
issuers:
- http://127.0.0.1:4444/
Expand All @@ -237,7 +237,7 @@ mechanisms:
enable_http_cache: true
jwt_source:
- header: Authorization
schema: Bearer
scheme: Bearer
assertions:
audience:
- bla
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ func (a *basicAuthAuthenticator) Execute(ctx heimdall.Context) (*subject.Subject
logger := zerolog.Ctx(ctx.AppContext())
logger.Debug().Str("_id", a.id).Msg("Authenticating using basic_auth authenticator")

strategy := extractors.HeaderValueExtractStrategy{Name: "Authorization", Schema: "Basic"}
strategy := extractors.HeaderValueExtractStrategy{Name: "Authorization", Scheme: "Basic"}

authData, err := strategy.GetAuthData(ctx)
if err != nil {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import (
"github.com/dadrus/heimdall/internal/heimdall/mocks"
)

func TestCompositeExtractCookieValueWithoutSchema(t *testing.T) {
func TestCompositeExtractCookieValueWithoutScheme(t *testing.T) {
t.Parallel()

// GIVEN
Expand Down Expand Up @@ -55,17 +55,17 @@ func TestCompositeExtractCookieValueWithoutSchema(t *testing.T) {
assert.Equal(t, actualValue, val)
}

func TestCompositeExtractHeaderValueWithSchema(t *testing.T) {
func TestCompositeExtractHeaderValueWithScheme(t *testing.T) {
t.Parallel()

// GIVEN
headerName := "Test-Header"
queryParamName := "test_param"
headerSchema := "bar:"
headerScheme := "bar:"
actualValue := "foo"

fnt := mocks.NewRequestFunctionsMock(t)
fnt.EXPECT().Header(headerName).Return(headerSchema + " " + actualValue)
fnt.EXPECT().Header(headerName).Return(headerScheme + " " + actualValue)

ctx := mocks.NewContextMock(t)
ctx.EXPECT().Request().Return(&heimdall.Request{
Expand All @@ -75,7 +75,7 @@ func TestCompositeExtractHeaderValueWithSchema(t *testing.T) {

strategy := CompositeExtractStrategy{
QueryParameterExtractStrategy{Name: queryParamName},
HeaderValueExtractStrategy{Name: headerName, Schema: headerSchema},
HeaderValueExtractStrategy{Name: headerName, Scheme: headerScheme},
}

// WHEN
Expand All @@ -92,17 +92,17 @@ func TestCompositeExtractStrategyOrder(t *testing.T) {
// GIVEN
headerName := "Test-Header"
queryParamName := "test_param"
headerSchema := "bar:"
headerScheme := "bar:"
actualValue := "foo"

fnt := mocks.NewRequestFunctionsMock(t)
fnt.EXPECT().Header(headerName).Return(headerSchema + " " + actualValue)
fnt.EXPECT().Header(headerName).Return(headerScheme + " " + actualValue)

ctx := mocks.NewContextMock(t)
ctx.EXPECT().Request().Return(&heimdall.Request{RequestFunctions: fnt})

strategy := CompositeExtractStrategy{
HeaderValueExtractStrategy{Name: headerName, Schema: headerSchema},
HeaderValueExtractStrategy{Name: headerName, Scheme: headerScheme},
QueryParameterExtractStrategy{Name: queryParamName},
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,17 +26,17 @@ import (

type HeaderValueExtractStrategy struct {
Name string
Schema string
Scheme string
}

func (es HeaderValueExtractStrategy) GetAuthData(s heimdall.Context) (string, error) {
if val := s.Request().Header(es.Name); len(val) != 0 {
if len(es.Schema) != 0 && !strings.HasPrefix(val, fmt.Sprintf("%s ", es.Schema)) {
if len(es.Scheme) != 0 && !strings.HasPrefix(val, fmt.Sprintf("%s ", es.Scheme)) {
return "", errorchain.NewWithMessagef(heimdall.ErrArgument,
"'%s' header present, but without required '%s' schema", es.Name, es.Schema)
"'%s' header present, but without required '%s' scheme", es.Name, es.Scheme)
}

return strings.TrimSpace(strings.TrimPrefix(val, es.Schema)), nil
return strings.TrimSpace(strings.TrimPrefix(val, es.Scheme)), nil
}

return "", errorchain.NewWithMessagef(heimdall.ErrArgument, "no '%s' header present", es.Name)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ func TestExtractHeaderValue(t *testing.T) {
assert func(t *testing.T, err error, authData string)
}{
{
uc: "header is present, schema is irrelevant",
uc: "header is present, scheme is irrelevant",
strategy: HeaderValueExtractStrategy{Name: "X-Test-Header"},
configureMocks: func(t *testing.T, ctx *mocks.ContextMock) {
t.Helper()
Expand All @@ -54,8 +54,8 @@ func TestExtractHeaderValue(t *testing.T) {
},
},
{
uc: "schema is required, header is present, but without any schema",
strategy: HeaderValueExtractStrategy{Name: "X-Test-Header", Schema: "Foo"},
uc: "scheme is required, header is present, but without any scheme",
strategy: HeaderValueExtractStrategy{Name: "X-Test-Header", Scheme: "Foo"},
configureMocks: func(t *testing.T, ctx *mocks.ContextMock) {
t.Helper()

Expand All @@ -69,12 +69,12 @@ func TestExtractHeaderValue(t *testing.T) {

require.Error(t, err)
require.ErrorIs(t, err, heimdall.ErrArgument)
assert.Contains(t, err.Error(), "'Foo' schema")
assert.Contains(t, err.Error(), "'Foo' scheme")
},
},
{
uc: "schema is required, header is present, but with different schema",
strategy: HeaderValueExtractStrategy{Name: "X-Test-Header", Schema: "Foo"},
uc: "scheme is required, header is present, but with different scheme",
strategy: HeaderValueExtractStrategy{Name: "X-Test-Header", Scheme: "Foo"},
configureMocks: func(t *testing.T, ctx *mocks.ContextMock) {
t.Helper()

Expand All @@ -88,12 +88,12 @@ func TestExtractHeaderValue(t *testing.T) {

require.Error(t, err)
require.ErrorIs(t, err, heimdall.ErrArgument)
assert.Contains(t, err.Error(), "'Foo' schema")
assert.Contains(t, err.Error(), "'Foo' scheme")
},
},
{
uc: "header with required schema is present",
strategy: HeaderValueExtractStrategy{Name: "X-Test-Header", Schema: "Foo"},
uc: "header with required scheme is present",
strategy: HeaderValueExtractStrategy{Name: "X-Test-Header", Scheme: "Foo"},
configureMocks: func(t *testing.T, ctx *mocks.ContextMock) {
t.Helper()

Expand All @@ -111,7 +111,7 @@ func TestExtractHeaderValue(t *testing.T) {
},
{
uc: "header is not present at all",
strategy: HeaderValueExtractStrategy{Name: "X-Test-Header", Schema: "Foo"},
strategy: HeaderValueExtractStrategy{Name: "X-Test-Header", Scheme: "Foo"},
configureMocks: func(t *testing.T, ctx *mocks.ContextMock) {
t.Helper()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,12 +78,12 @@ func DecodeCompositeExtractStrategyHookFunc() mapstructure.DecodeHookFunc {

func createStrategy(data map[string]string) (AuthDataExtractStrategy, error) {
if value, ok := data["header"]; ok { // nolint: nestif
var schema string
if p, ok := data["schema"]; ok {
schema = p
var scheme string
if p, ok := data["scheme"]; ok {
scheme = p
}

return &HeaderValueExtractStrategy{Name: value, Schema: schema}, nil
return &HeaderValueExtractStrategy{Name: value, Scheme: scheme}, nil
} else if value, ok := data["cookie"]; ok {
return &CookieValueExtractStrategy{Name: value}, nil
} else if value, ok := data["query_parameter"]; ok {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ func TestUnmarshalAuthenticationDataSourceFromValidYaml(t *testing.T) {
authentication_data_source:
- cookie: foo_cookie
- header: foo_header
schema: hfoo
scheme: hfoo
- query_parameter: foo_qparam
- body_parameter: foo_bparam
`)
Expand Down Expand Up @@ -70,7 +70,7 @@ authentication_data_source:
he, ok := ces[1].(*HeaderValueExtractStrategy)
require.True(t, ok)
assert.Equal(t, "foo_header", he.Name)
assert.Equal(t, "hfoo", he.Schema)
assert.Equal(t, "hfoo", he.Scheme)

qe, ok := ces[2].(*QueryParameterExtractStrategy)
require.True(t, ok)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ func newJwtAuthenticator(id string, rawConfig map[string]any) (*jwtAuthenticator
ads := x.IfThenElseExec(conf.AuthDataSource == nil,
func() extractors.CompositeExtractStrategy {
return extractors.CompositeExtractStrategy{
extractors.HeaderValueExtractStrategy{Name: "Authorization", Schema: "Bearer"},
extractors.HeaderValueExtractStrategy{Name: "Authorization", Scheme: "Bearer"},
extractors.QueryParameterExtractStrategy{Name: "access_token"},
extractors.BodyParameterExtractStrategy{Name: "access_token"},
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ assertions:
// token extractor settings
assert.IsType(t, extractors.CompositeExtractStrategy{}, auth.ads)
assert.Len(t, auth.ads, 3)
assert.Contains(t, auth.ads, extractors.HeaderValueExtractStrategy{Name: "Authorization", Schema: "Bearer"})
assert.Contains(t, auth.ads, extractors.HeaderValueExtractStrategy{Name: "Authorization", Scheme: "Bearer"})
assert.Contains(t, auth.ads, extractors.QueryParameterExtractStrategy{Name: "access_token"})
assert.Contains(t, auth.ads, extractors.BodyParameterExtractStrategy{Name: "access_token"})

Expand Down Expand Up @@ -222,7 +222,7 @@ cache_ttl: 5s`),
// token extractor settings
assert.IsType(t, extractors.CompositeExtractStrategy{}, auth.ads)
assert.Len(t, auth.ads, 3)
assert.Contains(t, auth.ads, extractors.HeaderValueExtractStrategy{Name: "Authorization", Schema: "Bearer"})
assert.Contains(t, auth.ads, extractors.HeaderValueExtractStrategy{Name: "Authorization", Scheme: "Bearer"})
assert.Contains(t, auth.ads, extractors.QueryParameterExtractStrategy{Name: "access_token"})
assert.Contains(t, auth.ads, extractors.BodyParameterExtractStrategy{Name: "access_token"})

Expand Down Expand Up @@ -271,7 +271,7 @@ jwks_endpoint:
Accept-Type: application/foobar
jwt_source:
- header: foo-header
schema: foo
scheme: foo
- query_parameter: foo_query_param
- body_parameter: foo_body_param
assertions:
Expand Down Expand Up @@ -304,7 +304,7 @@ trust_store: ` + trustStorePath),
assert.IsType(t, extractors.CompositeExtractStrategy{}, auth.ads)
assert.Len(t, auth.ads, 3)
assert.Contains(t, auth.ads, &extractors.HeaderValueExtractStrategy{
Name: "foo-header", Schema: "foo",
Name: "foo-header", Scheme: "foo",
})
assert.Contains(t, auth.ads, &extractors.QueryParameterExtractStrategy{Name: "foo_query_param"})
assert.Contains(t, auth.ads, &extractors.BodyParameterExtractStrategy{Name: "foo_body_param"})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ func newOAuth2IntrospectionAuthenticator(id string, rawConfig map[string]any) (
ads := x.IfThenElseExec(conf.AuthDataSource == nil,
func() extractors.CompositeExtractStrategy {
return extractors.CompositeExtractStrategy{
extractors.HeaderValueExtractStrategy{Name: "Authorization", Schema: "Bearer"},
extractors.HeaderValueExtractStrategy{Name: "Authorization", Scheme: "Bearer"},
extractors.QueryParameterExtractStrategy{Name: "access_token"},
extractors.BodyParameterExtractStrategy{Name: "access_token"},
}
Expand Down
Loading

0 comments on commit aaf4bd3

Please sign in to comment.