mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2025-08-19 17:01:12 +00:00
As stated in a comment: https://codeberg.org/forgejo/forgejo/issues/8634#issuecomment-6136933 > `routers/web/webfinger.go` was left unchanged, so it still includes the trailing slash, no longer matching the issuer specified in other endpoints. > > ... > > From the [OpenID Connect Discovery specification](https://openid.net/specs/openid-connect-discovery-1_0.html#IssuerDiscovery): > > > The Issuer location MUST be returned in the WebFinger response as the value of the href member of a links array element with rel member value http://openid.net/specs/connect/1.0/issuer. > > This sounds to me like the `href` should be the issuer location exactly. > > Using Forgejo for OIDC for auth with Tailscale is one instance of this change breaking something - signing up to Tailscale with OIDC now gives an error. Unsure what happens for existing accounts. In summary, since !8028, trailing slashes have been removed from the OIDC issuer locations specified by Forgejo everywhere except in WebFinger responses at `/.well-known/webfinger`, which still includes a trailing slash and so no longer matches the issuer as specified elsewhere (such as at `/.well-known/openid-configuration`). ## Checklist The [contributor guide](https://forgejo.org/docs/next/contributor/) contains information that will be helpful to first time contributors. There also are a few [conditions for merging Pull Requests in Forgejo repositories](https://codeberg.org/forgejo/governance/src/branch/main/PullRequestsAgreement.md). You are also welcome to join the [Forgejo development chatroom](https://matrix.to/#/#forgejo-development:matrix.org). ### Tests - I added test coverage for Go changes... - [ ] in their respective `*_test.go` for unit tests. - [x] in the `tests/integration` directory if it involves interactions with a live Forgejo server. - I added test coverage for JavaScript changes... - [ ] in `web_src/js/*.test.js` if it can be unit tested. - [ ] in `tests/e2e/*.test.e2e.js` if it requires interactions with a live Forgejo server (see also the [developer guide for JavaScript testing](https://codeberg.org/forgejo/forgejo/src/branch/forgejo/tests/e2e/README.md#end-to-end-tests)). ### Documentation - [ ] I created a pull request [to the documentation](https://codeberg.org/forgejo/docs) to explain to Forgejo users how to use this change. - [ ] I did not document these changes and I do not expect someone else to do it. ### Release notes - [ ] I do not want this change to show in the release notes. - [ ] I want the title to show in the release notes with a link to this pull request. - [ ] I want the content of the `release-notes/<pull request number>.md` to be be used for the release notes instead of the title. Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/8794 Reviewed-by: Gusted <gusted@noreply.codeberg.org> Reviewed-by: Michael Kriese <michael.kriese@gmx.de> Co-authored-by: hazycora <git@hazy.gay> Co-committed-by: hazycora <git@hazy.gay>
113 lines
4 KiB
Go
113 lines
4 KiB
Go
// Copyright 2022 The Gitea Authors. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package integration
|
|
|
|
import (
|
|
"fmt"
|
|
"net/http"
|
|
"net/url"
|
|
"strings"
|
|
"testing"
|
|
|
|
"forgejo.org/models/unittest"
|
|
user_model "forgejo.org/models/user"
|
|
"forgejo.org/modules/setting"
|
|
"forgejo.org/modules/test"
|
|
"forgejo.org/tests"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
func TestWebfinger(t *testing.T) {
|
|
defer tests.PrepareTestEnv(t)()
|
|
defer test.MockVariableValue(&setting.Federation.Enabled, true)()
|
|
|
|
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
|
|
|
appURL, _ := url.Parse(setting.AppURL)
|
|
|
|
type webfingerLink struct {
|
|
Rel string `json:"rel,omitempty"`
|
|
Type string `json:"type,omitempty"`
|
|
Href string `json:"href,omitempty"`
|
|
Titles map[string]string `json:"titles,omitempty"`
|
|
Properties map[string]any `json:"properties,omitempty"`
|
|
}
|
|
|
|
type webfingerJRD struct {
|
|
Subject string `json:"subject,omitempty"`
|
|
Aliases []string `json:"aliases,omitempty"`
|
|
Properties map[string]any `json:"properties,omitempty"`
|
|
Links []*webfingerLink `json:"links,omitempty"`
|
|
}
|
|
|
|
session := loginUser(t, "user1")
|
|
|
|
ctx := t.Context()
|
|
|
|
req := NewRequest(t, "GET", fmt.Sprintf("/.well-known/webfinger?resource=acct:%s@%s", user.LowerName, appURL.Host))
|
|
resp := MakeRequest(t, req, http.StatusOK)
|
|
assert.Equal(t, "application/jrd+json", resp.Header().Get("Content-Type"))
|
|
|
|
var jrd webfingerJRD
|
|
DecodeJSON(t, resp, &jrd)
|
|
assert.Equal(t, "acct:user2@"+appURL.Host, jrd.Subject)
|
|
assert.ElementsMatch(t, []*webfingerLink{
|
|
{
|
|
Rel: "http://webfinger.net/rel/profile-page",
|
|
Type: "text/html",
|
|
Href: user.HTMLURL(),
|
|
},
|
|
{
|
|
Rel: "http://webfinger.net/rel/avatar",
|
|
Href: user.AvatarLink(ctx),
|
|
},
|
|
{
|
|
Rel: "self",
|
|
Type: "application/activity+json",
|
|
Href: appURL.String() + "api/v1/activitypub/user-id/" + fmt.Sprint(user.ID),
|
|
},
|
|
{
|
|
Rel: "http://openid.net/specs/connect/1.0/issuer",
|
|
Href: strings.TrimSuffix(appURL.String(), "/"),
|
|
},
|
|
}, jrd.Links)
|
|
assert.ElementsMatch(t, []string{user.HTMLURL(), appURL.String() + "api/v1/activitypub/user-id/" + fmt.Sprint(user.ID)}, jrd.Aliases)
|
|
|
|
instanceReq := NewRequest(t, "GET", fmt.Sprintf("/.well-known/webfinger?resource=acct:ghost@%s", appURL.Host))
|
|
instanceResp := MakeRequest(t, instanceReq, http.StatusOK)
|
|
assert.Equal(t, "application/jrd+json", instanceResp.Header().Get("Content-Type"))
|
|
|
|
var instanceActor webfingerJRD
|
|
DecodeJSON(t, instanceResp, &instanceActor)
|
|
assert.Equal(t, "acct:ghost@"+appURL.Host, instanceActor.Subject)
|
|
assert.ElementsMatch(t, []string{appURL.String() + "api/v1/activitypub/actor"}, instanceActor.Aliases)
|
|
|
|
req = NewRequest(t, "GET", fmt.Sprintf("/.well-known/webfinger?resource=acct:%s@%s", user.LowerName, "unknown.host"))
|
|
MakeRequest(t, req, http.StatusBadRequest)
|
|
|
|
req = NewRequest(t, "GET", fmt.Sprintf("/.well-known/webfinger?resource=acct:%s@%s", "user31", appURL.Host))
|
|
MakeRequest(t, req, http.StatusNotFound)
|
|
|
|
req = NewRequest(t, "GET", fmt.Sprintf("/.well-known/webfinger?resource=acct:%s@%s", "user31", appURL.Host))
|
|
session.MakeRequest(t, req, http.StatusOK)
|
|
|
|
req = NewRequest(t, "GET", fmt.Sprintf("/.well-known/webfinger?resource=mailto:%s", user.Email))
|
|
MakeRequest(t, req, http.StatusNotFound)
|
|
|
|
req = NewRequest(t, "GET", fmt.Sprintf("/.well-known/webfinger?resource=https://%s/%s/", appURL.Host, user.Name))
|
|
session.MakeRequest(t, req, http.StatusOK)
|
|
|
|
req = NewRequest(t, "GET", fmt.Sprintf("/.well-known/webfinger?resource=https://%s/%s", appURL.Host, user.Name))
|
|
session.MakeRequest(t, req, http.StatusOK)
|
|
|
|
req = NewRequest(t, "GET", fmt.Sprintf("/.well-known/webfinger?resource=http://%s/%s/foo", appURL.Host, user.Name))
|
|
session.MakeRequest(t, req, http.StatusNotFound)
|
|
|
|
req = NewRequest(t, "GET", fmt.Sprintf("/.well-known/webfinger?resource=http://%s", appURL.Host))
|
|
MakeRequest(t, req, http.StatusNotFound)
|
|
|
|
req = NewRequest(t, "GET", fmt.Sprintf("/.well-known/webfinger?resource=http://%s/%s/foo", "example.com", user.Name))
|
|
MakeRequest(t, req, http.StatusBadRequest)
|
|
}
|