Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .docker/Dockerfile-build
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ RUN apt-get update && apt-get upgrade -y
COPY go.mod go.mod
COPY go.sum go.sum
COPY oryx/go.mod oryx/go.mod
COPY oryx/go.sum proto/go.sum
COPY oryx/go.sum oryx/go.sum
COPY middleware/rpctest/go.mod middleware/rpctest/go.mod
COPY middleware/rpctest/go.sum middleware/rpctest/go.sum

ENV CGO_ENABLED=0

Expand Down
19 changes: 18 additions & 1 deletion credentials/verifier_default.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ func (v *VerifierDefault) Verify(
}

if len(r.Issuers) > 0 {
if !slices.Contains(r.Issuers, parsedClaims.Issuer) {
if !matchesTrustedIssuer(r.Issuers, parsedClaims.Issuer) {
return nil, herodot.ErrUnauthorized().WithReasonf("Token issuer does not match any trusted issuer %s.", parsedClaims.Issuer).
WithDetail("received issuers", strings.Join(r.Issuers, ", "))
}
Expand Down Expand Up @@ -166,3 +166,20 @@ func scope(claims map[string]interface{}) ([]string, string) {
return []string{}, key
}
}

// matchesTrustedIssuer reports whether the token issuer matches any of the
// trusted issuers, treating issuers that differ only by a trailing slash as
// equal. This avoids rejecting otherwise-valid tokens when the trusted_issuers
// configuration and the token's "iss" claim disagree on a trailing "/" (for
// example "https://issuer" versus "https://issuer/").
//
// See https://github.com/ory/oathkeeper/issues/527.
func matchesTrustedIssuer(trusted []string, issuer string) bool {
issuer = strings.TrimSuffix(issuer, "/")
for _, t := range trusted {
if strings.TrimSuffix(t, "/") == issuer {
return true
}
}
return false
}
40 changes: 40 additions & 0 deletions credentials/verifier_default_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,46 @@ func TestVerifierDefault(t *testing.T) {
}, "file://../test/stub/jwks-hs.json"),
expectErr: true,
},
{
d: "should pass when the trusted issuer has a trailing slash but the token issuer does not (issue #527)",
c: &ValidationContext{
Algorithms: []string{"HS256"},
Issuers: []string{"https://my-issuer/"},
KeyURLs: []url.URL{*x.ParseURLOrPanic("file://../test/stub/jwks-hs.json")},
},
token: sign(jwt.MapClaims{
"sub": "sub",
"exp": now.Add(time.Hour).Unix(),
"iss": "https://my-issuer",
}, "file://../test/stub/jwks-hs.json"),
},
{
d: "should pass when the token issuer has a trailing slash but the trusted issuer does not (issue #527)",
c: &ValidationContext{
Algorithms: []string{"HS256"},
Issuers: []string{"https://my-issuer"},
KeyURLs: []url.URL{*x.ParseURLOrPanic("file://../test/stub/jwks-hs.json")},
},
token: sign(jwt.MapClaims{
"sub": "sub",
"exp": now.Add(time.Hour).Unix(),
"iss": "https://my-issuer/",
}, "file://../test/stub/jwks-hs.json"),
},
{
d: "should still fail when the issuer genuinely differs despite trailing-slash normalization (issue #527)",
c: &ValidationContext{
Algorithms: []string{"HS256"},
Issuers: []string{"https://my-issuer/"},
KeyURLs: []url.URL{*x.ParseURLOrPanic("file://../test/stub/jwks-hs.json")},
},
token: sign(jwt.MapClaims{
"sub": "sub",
"exp": now.Add(time.Hour).Unix(),
"iss": "https://evil-issuer",
}, "file://../test/stub/jwks-hs.json"),
expectErr: true,
},
} {
t.Run(fmt.Sprintf("case=%d/description=%s", k, tc.d), func(t *testing.T) {
claims, err := verifier.Verify(context.Background(), tc.token, tc.c)
Expand Down
5 changes: 3 additions & 2 deletions oryx/openapix/jsonpatch.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ type JSONPatchDocument []JSONPatch
//
// swagger:model jsonPatch
type JSONPatch struct {
// The operation to be performed. One of "add", "remove", "replace", "move", "copy", or "test".
// The operation to be performed. One of "add", "remove", or "replace".
//
// required: true
// example: replace
Expand All @@ -33,7 +33,8 @@ type JSONPatch struct {
// example: foobar
Value interface{} `json:"value"`

// This field is used together with operation "move" and uses JSON Pointer notation.
// The source path for operations that require it. Uses JSON pointer notation.
// Not used by the currently supported operations ("add", "remove", "replace").
//
// Learn more [about JSON Pointers](https://datatracker.ietf.org/doc/html/rfc6901#section-5).
//
Expand Down
Loading