Skip to content

Commit

Permalink
Merge branch 'master' into fix-oidc-redirect-uri
Browse files Browse the repository at this point in the history
  • Loading branch information
james-d-elliott authored Dec 2, 2023
2 parents 63c797c + dfa2c0a commit 37f4ada
Show file tree
Hide file tree
Showing 69 changed files with 702 additions and 2,024 deletions.
7 changes: 6 additions & 1 deletion .github/ISSUE_TEMPLATE/BUG-REPORT.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,17 @@ body:
- label: "I have read and am following this repository's [Contribution
Guidelines](https://github.com/ory/fosite/blob/master/CONTRIBUTING.md)."
required: true
- label: "This issue affects my [Ory Network](https://www.ory.sh/) project."
- label: "I have joined the [Ory Community Slack](https://slack.ory.sh)."
- label: "I am signed up to the [Ory Security Patch
Newsletter](https://ory.us10.list-manage.com/subscribe?u=ffb1a878e4ec6c0ed312a3480&id=f605a41b53)."
id: checklist
type: checkboxes
- attributes:
description: "Enter the slug or API URL of the affected Ory Network project. Leave empty when you are self-hosting."
label: "Ory Network Project"
placeholder: "https://<your-project-slug>.projects.oryapis.com"
id: ory-network-project
type: input
- attributes:
description: "A clear and concise description of what the bug is."
label: "Describe the bug"
Expand Down
7 changes: 6 additions & 1 deletion .github/ISSUE_TEMPLATE/DESIGN-DOC.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,17 @@ body:
- label: "I have read and am following this repository's [Contribution
Guidelines](https://github.com/ory/fosite/blob/master/CONTRIBUTING.md)."
required: true
- label: "This issue affects my [Ory Network](https://www.ory.sh/) project."
- label: "I have joined the [Ory Community Slack](https://slack.ory.sh)."
- label: "I am signed up to the [Ory Security Patch
Newsletter](https://ory.us10.list-manage.com/subscribe?u=ffb1a878e4ec6c0ed312a3480&id=f605a41b53)."
id: checklist
type: checkboxes
- attributes:
description: "Enter the slug or API URL of the affected Ory Network project. Leave empty when you are self-hosting."
label: "Ory Network Project"
placeholder: "https://<your-project-slug>.projects.oryapis.com"
id: ory-network-project
type: input
- attributes:
description: |
This section gives the reader a very rough overview of the landscape in which the new system is being built and what is actually being built. This isn’t a requirements doc. Keep it succinct! The goal is that readers are brought up to speed but some previous knowledge can be assumed and detailed info can be linked to. This section should be entirely focused on objective background facts.
Expand Down
7 changes: 6 additions & 1 deletion .github/ISSUE_TEMPLATE/FEATURE-REQUEST.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,17 @@ body:
- label: "I have read and am following this repository's [Contribution
Guidelines](https://github.com/ory/fosite/blob/master/CONTRIBUTING.md)."
required: true
- label: "This issue affects my [Ory Network](https://www.ory.sh/) project."
- label: "I have joined the [Ory Community Slack](https://slack.ory.sh)."
- label: "I am signed up to the [Ory Security Patch
Newsletter](https://ory.us10.list-manage.com/subscribe?u=ffb1a878e4ec6c0ed312a3480&id=f605a41b53)."
id: checklist
type: checkboxes
- attributes:
description: "Enter the slug or API URL of the affected Ory Network project. Leave empty when you are self-hosting."
label: "Ory Network Project"
placeholder: "https://<your-project-slug>.projects.oryapis.com"
id: ory-network-project
type: input
- attributes:
description: "Is your feature request related to a problem? Please describe."
label: "Describe your problem"
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/format.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-go@v3
with:
go-version: 1.19
go-version: "1.20"
- run: make format
- name: Indicate formatting issues
run: git diff HEAD --exit-code --color
2 changes: 1 addition & 1 deletion .github/workflows/licenses.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
- uses: actions/checkout@v2
- uses: actions/setup-go@v2
with:
go-version: "1.18"
go-version: "1.20"
- uses: actions/setup-node@v2
with:
node-version: "18"
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/oidc-conformity-master.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
ref: master
- uses: actions/setup-go@v2
with:
go-version: "^1.19.0"
go-version: "1.20"
- name: Update fosite
run: |
go mod edit -replace github.com/ory/fosite=github.com/ory/fosite@${{ github.sha }}
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/oidc-conformity.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
ref: master
- uses: actions/setup-go@v2
with:
go-version: "^1.19.0"
go-version: "1.20"
- name: Update fosite
run: |
go mod edit -replace github.com/ory/fosite=github.com/${{ github.event.pull_request.head.repo.full_name }}@${{ github.event.pull_request.head.sha }}
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-go@v3
with:
go-version: 1.19
go-version: "1.20"
- run: make test
7 changes: 6 additions & 1 deletion access_request_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import (

"github.com/ory/fosite/i18n"
"github.com/ory/x/errorsx"
"github.com/ory/x/otelx"
"go.opentelemetry.io/otel/trace"

"github.com/pkg/errors"
)
Expand Down Expand Up @@ -39,7 +41,10 @@ import (
// credentials (or assigned other authentication requirements), the
// client MUST authenticate with the authorization server as described
// in Section 3.2.1.
func (f *Fosite) NewAccessRequest(ctx context.Context, r *http.Request, session Session) (AccessRequester, error) {
func (f *Fosite) NewAccessRequest(ctx context.Context, r *http.Request, session Session) (_ AccessRequester, err error) {
ctx, span := trace.SpanFromContext(ctx).TracerProvider().Tracer("github.com/ory/fosite").Start(ctx, "Fosite.NewAccessRequest")
defer otelx.End(span, &err)

accessRequest := NewAccessRequest(session)
accessRequest.Request.Lang = i18n.GetLangFromRequest(f.Config.GetMessageCatalog(ctx), r)

Expand Down
15 changes: 5 additions & 10 deletions access_request_handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
package fosite_test

import (
"context"
"encoding/base64"
"fmt"
"net/http"
Expand All @@ -29,8 +28,6 @@ func TestNewAccessRequest(t *testing.T) {
hasher := internal.NewMockHasher(ctrl)
defer ctrl.Finish()

ctx := gomock.AssignableToTypeOf(context.WithValue(context.TODO(), ContextKey("test"), nil))

client := &DefaultClient{}
config := &Config{ClientSecretsHasher: hasher, AudienceMatchingStrategy: DefaultAudienceMatchingStrategy}
fosite := &Fosite{Store: store, Config: config}
Expand Down Expand Up @@ -121,7 +118,7 @@ func TestNewAccessRequest(t *testing.T) {
store.EXPECT().GetClient(gomock.Any(), gomock.Eq("foo")).Return(client, nil)
client.Public = false
client.Secret = []byte("foo")
hasher.EXPECT().Compare(ctx, gomock.Eq([]byte("foo")), gomock.Eq([]byte("bar"))).Return(errors.New(""))
hasher.EXPECT().Compare(gomock.Any(), gomock.Eq([]byte("foo")), gomock.Eq([]byte("bar"))).Return(errors.New(""))
},
handlers: TokenEndpointHandlers{handler},
},
Expand All @@ -138,7 +135,7 @@ func TestNewAccessRequest(t *testing.T) {
store.EXPECT().GetClient(gomock.Any(), gomock.Eq("foo")).Return(client, nil)
client.Public = false
client.Secret = []byte("foo")
hasher.EXPECT().Compare(ctx, gomock.Eq([]byte("foo")), gomock.Eq([]byte("bar"))).Return(nil)
hasher.EXPECT().Compare(gomock.Any(), gomock.Eq([]byte("foo")), gomock.Eq([]byte("bar"))).Return(nil)
handler.EXPECT().HandleTokenEndpointRequest(gomock.Any(), gomock.Any()).Return(ErrServerError)
},
handlers: TokenEndpointHandlers{handler},
Expand All @@ -155,7 +152,7 @@ func TestNewAccessRequest(t *testing.T) {
store.EXPECT().GetClient(gomock.Any(), gomock.Eq("foo")).Return(client, nil)
client.Public = false
client.Secret = []byte("foo")
hasher.EXPECT().Compare(ctx, gomock.Eq([]byte("foo")), gomock.Eq([]byte("bar"))).Return(nil)
hasher.EXPECT().Compare(gomock.Any(), gomock.Eq([]byte("foo")), gomock.Eq([]byte("bar"))).Return(nil)
handler.EXPECT().HandleTokenEndpointRequest(gomock.Any(), gomock.Any()).Return(nil)
},
handlers: TokenEndpointHandlers{handler},
Expand Down Expand Up @@ -355,8 +352,6 @@ func TestNewAccessRequestWithMixedClientAuth(t *testing.T) {
hasher := internal.NewMockHasher(ctrl)
defer ctrl.Finish()

ctx := gomock.AssignableToTypeOf(context.WithValue(context.TODO(), ContextKey("test"), nil))

client := &DefaultClient{}
config := &Config{ClientSecretsHasher: hasher, AudienceMatchingStrategy: DefaultAudienceMatchingStrategy}
fosite := &Fosite{Store: store, Config: config}
Expand All @@ -380,7 +375,7 @@ func TestNewAccessRequestWithMixedClientAuth(t *testing.T) {
store.EXPECT().GetClient(gomock.Any(), gomock.Eq("foo")).Return(client, nil)
client.Public = false
client.Secret = []byte("foo")
hasher.EXPECT().Compare(ctx, gomock.Eq([]byte("foo")), gomock.Eq([]byte("bar"))).Return(errors.New("hash err"))
hasher.EXPECT().Compare(gomock.Any(), gomock.Eq([]byte("foo")), gomock.Eq([]byte("bar"))).Return(errors.New("hash err"))
handlerWithoutClientAuth.EXPECT().HandleTokenEndpointRequest(gomock.Any(), gomock.Any()).Return(nil)
},
method: "POST",
Expand All @@ -398,7 +393,7 @@ func TestNewAccessRequestWithMixedClientAuth(t *testing.T) {
store.EXPECT().GetClient(gomock.Any(), gomock.Eq("foo")).Return(client, nil)
client.Public = false
client.Secret = []byte("foo")
hasher.EXPECT().Compare(ctx, gomock.Eq([]byte("foo")), gomock.Eq([]byte("bar"))).Return(nil)
hasher.EXPECT().Compare(gomock.Any(), gomock.Eq([]byte("foo")), gomock.Eq([]byte("bar"))).Return(nil)
handlerWithoutClientAuth.EXPECT().HandleTokenEndpointRequest(gomock.Any(), gomock.Any()).Return(nil)
handlerWithClientAuth.EXPECT().HandleTokenEndpointRequest(gomock.Any(), gomock.Any()).Return(nil)
},
Expand Down
8 changes: 6 additions & 2 deletions access_response_writer.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,16 @@ import (
"context"

"github.com/ory/x/errorsx"
"github.com/ory/x/otelx"
"go.opentelemetry.io/otel/trace"

"github.com/pkg/errors"
)

func (f *Fosite) NewAccessResponse(ctx context.Context, requester AccessRequester) (AccessResponder, error) {
var err error
func (f *Fosite) NewAccessResponse(ctx context.Context, requester AccessRequester) (_ AccessResponder, err error) {
ctx, span := trace.SpanFromContext(ctx).TracerProvider().Tracer("github.com/ory/fosite").Start(ctx, "Fosite.NewAccessResponse")
defer otelx.End(span, &err)

var tk TokenEndpointHandler

response := NewAccessResponse()
Expand Down
7 changes: 5 additions & 2 deletions authorize_helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,11 +141,14 @@ func isMatchingAsLoopback(requested *url.URL, registeredURI string) bool {
return false
}

var (
regexLoopbackAddress = regexp.MustCompile(`^(127\.0\.0\.1|\[::1])(:\d+)?$`)
)

// Check if address is either an IPv4 loopback or an IPv6 loopback-
// An optional port is ignored
func isLoopbackAddress(address string) bool {
match, _ := regexp.MatchString("^(127.0.0.1|\\[::1\\])(:?)(\\d*)$", address)
return match
return regexLoopbackAddress.MatchString(address)
}

// IsValidRedirectURI validates a redirect_uri as specified in:
Expand Down
4 changes: 2 additions & 2 deletions authorize_helper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ package fosite_test
import (
"bytes"
"context"
"io/ioutil"
"io"
"net/url"
"strings"
"testing"
Expand Down Expand Up @@ -284,7 +284,7 @@ func TestWriteAuthorizeFormPostResponse(t *testing.T) {
redirectURL := "https://localhost:8080/cb"
//parameters :=
fosite.WriteAuthorizeFormPostResponse(redirectURL, c.parameters, fosite.DefaultFormPostTemplate, &responseBuffer)
code, state, _, _, customParams, _, err := internal.ParseFormPostResponse(redirectURL, ioutil.NopCloser(bytes.NewReader(responseBuffer.Bytes())))
code, state, _, _, customParams, _, err := internal.ParseFormPostResponse(redirectURL, io.NopCloser(bytes.NewReader(responseBuffer.Bytes())))
assert.NoError(t, err, "case %d", d)
c.check(code, state, customParams, d)

Expand Down
69 changes: 69 additions & 0 deletions authorize_helper_whitebox_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
// Copyright © 2023 Ory Corp
// SPDX-License-Identifier: Apache-2.0

package fosite

import (
"testing"

"github.com/stretchr/testify/assert"
)

func TestIsLookbackAddress(t *testing.T) {
testCases := []struct {
name string
have string
expected bool
}{
{
"ShouldReturnTrueIPv4Loopback",
"127.0.0.1",
true,
},
{
"ShouldReturnTrueIPv4LoopbackWithPort",
"127.0.0.1:1230",
true,
},
{
"ShouldReturnTrueIPv6Loopback",
"[::1]",
true,
},
{
"ShouldReturnTrueIPv6LoopbackWithPort",
"[::1]:1230",
true,
}, {
"ShouldReturnFalse12700255",
"127.0.0.255",
false,
},
{
"ShouldReturnFalse12700255WithPort",
"127.0.0.255:1230",
false,
},
{
"ShouldReturnFalseInvalidFourthOctet",
"127.0.0.11230",
false,
},
{
"ShouldReturnFalseInvalidIPv4",
"127x0x0x11230",
false,
},
{
"ShouldReturnFalseInvalidIPv6",
"[::1]1230",
false,
},
}

for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
assert.Equal(t, tc.expected, isLoopbackAddress(tc.have))
})
}
}
11 changes: 8 additions & 3 deletions authorize_request_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,17 @@ package fosite
import (
"context"
"fmt"
"io/ioutil"
"io"
"net/http"
"strings"

"github.com/go-jose/go-jose/v3"
"go.opentelemetry.io/otel/trace"

"github.com/ory/fosite/i18n"
"github.com/ory/fosite/token/jwt"
"github.com/ory/x/errorsx"
"github.com/ory/x/otelx"

"github.com/pkg/errors"

Expand Down Expand Up @@ -74,7 +76,7 @@ func (f *Fosite) authorizeRequestParametersFromOpenIDConnectRequest(ctx context.
return errorsx.WithStack(ErrInvalidRequestURI.WithHintf("Unable to fetch OpenID Connect request parameters from 'request_uri' because status code '%d' was expected, but got '%d'.", http.StatusOK, response.StatusCode))
}

body, err := ioutil.ReadAll(response.Body)
body, err := io.ReadAll(response.Body)
if err != nil {
return errorsx.WithStack(ErrInvalidRequestURI.WithHintf("Unable to fetch OpenID Connect request parameters from 'request_uri' because body parsing failed with: %s.", err).WithWrap(err).WithDebug(err.Error()))
}
Expand Down Expand Up @@ -321,7 +323,10 @@ func (f *Fosite) authorizeRequestFromPAR(ctx context.Context, r *http.Request, r
return true, nil
}

func (f *Fosite) NewAuthorizeRequest(ctx context.Context, r *http.Request) (AuthorizeRequester, error) {
func (f *Fosite) NewAuthorizeRequest(ctx context.Context, r *http.Request) (_ AuthorizeRequester, err error) {
ctx, span := trace.SpanFromContext(ctx).TracerProvider().Tracer("github.com/ory/fosite").Start(ctx, "Fosite.NewAuthorizeRequest")
defer otelx.End(span, &err)

return f.newAuthorizeRequest(ctx, r, false)
}

Expand Down
7 changes: 6 additions & 1 deletion authorize_response_writer.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,14 @@ import (
"net/url"

"github.com/ory/x/errorsx"
"github.com/ory/x/otelx"
"go.opentelemetry.io/otel/trace"
)

func (f *Fosite) NewAuthorizeResponse(ctx context.Context, ar AuthorizeRequester, session Session) (AuthorizeResponder, error) {
func (f *Fosite) NewAuthorizeResponse(ctx context.Context, ar AuthorizeRequester, session Session) (_ AuthorizeResponder, err error) {
ctx, span := trace.SpanFromContext(ctx).TracerProvider().Tracer("github.com/ory/fosite").Start(ctx, "Fosite.NewAuthorizeResponse")
defer otelx.End(span, &err)

var resp = &AuthorizeResponse{
Header: http.Header{},
Parameters: url.Values{},
Expand Down
7 changes: 3 additions & 4 deletions client_authentication_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,7 @@ func TestAuthenticateClient(t *testing.T) {
},
}

var h http.HandlerFunc
h = func(w http.ResponseWriter, r *http.Request) {
var h http.HandlerFunc = func(w http.ResponseWriter, r *http.Request) {
require.NoError(t, json.NewEncoder(w).Encode(rsaJwks))
}
ts := httptest.NewServer(h)
Expand Down Expand Up @@ -586,12 +585,12 @@ func TestAuthenticateClientTwice(t *testing.T) {
"aud": "token-url",
}, key, "kid-foo")}, "client_assertion_type": []string{at}}

c, err := f.AuthenticateClient(nil, new(http.Request), formValues)
c, err := f.AuthenticateClient(context.Background(), new(http.Request), formValues)
require.NoError(t, err, "%#v", err)
assert.Equal(t, client, c)

// replay the request and expect it to fail
c, err = f.AuthenticateClient(nil, new(http.Request), formValues)
c, err = f.AuthenticateClient(context.Background(), new(http.Request), formValues)
require.Error(t, err)
assert.EqualError(t, err, ErrJTIKnown.Error())
assert.Nil(t, c)
Expand Down
Loading

0 comments on commit 37f4ada

Please sign in to comment.