From c4af36f130c529d3e5aeeffcf9df4825fb0ee2b1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 11 Aug 2026 16:39:27 +0000 Subject: [PATCH 1/3] Bump golang.org/x/crypto from 0.53.0 to 0.54.0 in the minor-and-patches group across 1 directory (#907) Signed-off-by: dependabot[bot] --- go.mod | 6 +++--- go.sum | 28 ++++++++++++++-------------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/go.mod b/go.mod index fec5f3bc..80d516e5 100644 --- a/go.mod +++ b/go.mod @@ -12,7 +12,7 @@ require ( github.com/sirupsen/logrus v1.9.4 github.com/tidwall/gjson v1.19.0 github.com/tidwall/sjson v1.2.5 - golang.org/x/crypto v0.53.0 + golang.org/x/crypto v0.54.0 golang.org/x/exp v0.0.0-20230905200255-921286631fa9 gonum.org/v1/plot v0.17.0 ) @@ -49,7 +49,7 @@ require ( go.opentelemetry.io/otel/sdk/metric v1.43.0 // indirect go.opentelemetry.io/otel/trace v1.43.0 // indirect golang.org/x/image v0.41.0 // indirect - golang.org/x/sys v0.46.0 // indirect - golang.org/x/text v0.38.0 // indirect + golang.org/x/sys v0.47.0 // indirect + golang.org/x/text v0.40.0 // indirect gonum.org/v1/gonum v0.17.0 // indirect ) diff --git a/go.sum b/go.sum index 93a3d7cd..f467423c 100644 --- a/go.sum +++ b/go.sum @@ -109,39 +109,39 @@ go.opentelemetry.io/otel/trace v1.43.0/go.mod h1:/QJhyVBUUswCphDVxq+8mld+AvhXZLh golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.53.0 h1:QZ4Muo8THX6CizN2vPPd5fBGHyogrdK9fG4wLPFUsto= -golang.org/x/crypto v0.53.0/go.mod h1:DNLU434OwVakk9PzuwV8w62mAJpRJL3vsgcfp4Qnsio= +golang.org/x/crypto v0.54.0 h1:YLIA59K4fiNzHzjnZt2tUJQjQtUWfWbeHBqKtk3eScw= +golang.org/x/crypto v0.54.0/go.mod h1:KWL8ny2AZdGR2cWmzeHrp2azQPGogOv+HeQaVEXC2dk= golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g= golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= golang.org/x/image v0.41.0 h1:8wS72eGJMJaBxK6okTzd4WaXumUlTVlb753MlsSvTCo= golang.org/x/image v0.41.0/go.mod h1:uIc348UZMSvS5Z65CVZ7iDPaNobNFEPeJ4kbqTOszmA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.36.0 h1:JJjpVx6myfUsUdAzZuOSTTmRE0PfZeNWzzvKrP7amb4= -golang.org/x/mod v0.36.0/go.mod h1:moc6ELqsWcOw5Ef3xVprK5ul/MvtVvkIXLziUOICjUQ= +golang.org/x/mod v0.37.0 h1:vF1DjpVEshcIqoEaauuHebaLk1O1forxjxBaVn884JQ= +golang.org/x/mod v0.37.0/go.mod h1:m8S8VeM9r4dzDwjrKO0a1sZP3YjeMamRRlD+fmR2Q/0= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.55.0 h1:bcvxaJn3e1U6InsFWt1JUq1aSjnRxLzT2rtD2KfkDF8= -golang.org/x/net v0.55.0/go.mod h1:L5U2KuzuOe1lY7Z+aWVIKK6qEeJXnXV9yzGA+WCHJww= +golang.org/x/net v0.56.0 h1:Rw8j/hFzGvJUZwNBXnAtf5sVDVt+65SK2C7IxCxZt5o= +golang.org/x/net v0.56.0/go.mod h1:D3Ku6r+V6JROoZK144D2XfMHFcMq/0zSfLelVTCFKec= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.21.0 h1:HLII4xRRTtCRkxYp4HNFF0Js/Og6q2i++KXbg0gHCwM= -golang.org/x/sync v0.21.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= +golang.org/x/sync v0.22.0 h1:SZjpbeLmrCk4xhRSZFNZW5gFUeCeFgjekvI/+gfScek= +golang.org/x/sync v0.22.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.46.0 h1:noSf2Fq6F8DBgS+LysIkx7rIExoNHJsxOAtPp4rthXw= -golang.org/x/sys v0.46.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= +golang.org/x/sys v0.47.0 h1:o7XGOvZQCADBQQ4Y7VNq2dRWQR7JmOUW8Kxx4ZsNgWs= +golang.org/x/sys v0.47.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.38.0 h1:sXmwo9DwP3OK9EZ7PqAdaooSGozfl/3a6/xJcbzPRhE= -golang.org/x/text v0.38.0/go.mod h1:YXZt3QhHUKYT53r2lLKFIVi6Ao1jdzrTR/KQ09qyxF4= +golang.org/x/text v0.40.0 h1:Ub2Z6/xjgF1WrYQz2nuITOEegKFtiIy+rieRJ5lHZKs= +golang.org/x/text v0.40.0/go.mod h1:hpnzDAfGV753zIKo+wk3u1bVKCGPbrnF7+7LBF/UHVY= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= -golang.org/x/tools v0.45.0 h1:18qN3FAooORvApf5XjCXgsuayZOEtXf6JK18I3+ONa8= -golang.org/x/tools v0.45.0/go.mod h1:LuUGqqaXcXMEFEruIVJVm5mgDD8vww/z/SR1gQ4uE/0= +golang.org/x/tools v0.47.0 h1:7Kn5x/d1svx/PzryTsqeoZN4TZwqeH5pGWjefhLi/1Q= +golang.org/x/tools v0.47.0/go.mod h1:dFHnyTvFWY212G+h7ZY4Vsp/K3U4/7W9TyVaAul8uCA= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= From 13f0b93a9dd57de5f40f82fdc497a03a9d9ef82e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 14 Aug 2026 08:11:34 +0000 Subject: [PATCH 2/3] Bump the minor-and-patches group across 1 directory with 2 updates (#910) Signed-off-by: dependabot[bot] --- .github/workflows/ci.yaml | 4 ++-- .github/workflows/zizmor.yaml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 4b118f05..5e07a8c5 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -20,7 +20,7 @@ jobs: permissions: contents: read steps: - - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: persist-credentials: false - uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0 @@ -64,7 +64,7 @@ jobs: timeout: 10m steps: - - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: persist-credentials: false diff --git a/.github/workflows/zizmor.yaml b/.github/workflows/zizmor.yaml index c28b744f..a1a8ddf5 100644 --- a/.github/workflows/zizmor.yaml +++ b/.github/workflows/zizmor.yaml @@ -16,9 +16,9 @@ jobs: security-events: write steps: - name: Checkout repository - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: persist-credentials: false - name: Run zizmor 🌈 - uses: zizmorcore/zizmor-action@192e21d79ab29983730a13d1382995c2307fbcaa # v0.5.7 + uses: zizmorcore/zizmor-action@6fc4b006235f201fdab3722e17240ab420d580e5 # v0.6.1 From 6d2fdc286c2b44faaddd1037205869b2242a4005 Mon Sep 17 00:00:00 2001 From: timedout Date: Fri, 14 Aug 2026 16:41:38 +0100 Subject: [PATCH 3/3] Perform UIA correctly when registering users on a deployment (#896) * Perform UIA correctly when registering users on a deployment Fixes #893 Signed-off-by: timedout * Properly initiate UIA sessions in `TestRegistration` Signed-off-by: timedout * `session` is optional and may be omitted if not provided Signed-off-by: timedout * Add a regression test to ensure `session` optionality is respected during registration Signed-off-by: timedout * Request validation is performed before authentication Also fixes the maps.Clone param order being inverted Signed-off-by: timedout * Skip sessionless UIA test on some homeservers Signed-off-by: timedout * Start a new session in pre-existing user register test Synapse validates the request body before auth, but Dendrite does not. This breaks the stalemate by just starting a "new" UIA session Signed-off-by: timedout * Skip existing user registration test on Dendrite and revert to previous behaviour Signed-off-by: timedout --------- Signed-off-by: timedout --- client/auth.go | 29 +++++-- tests/csapi/apidoc_register_test.go | 130 ++++++++++++++++------------ tests/csapi/power_levels_test.go | 2 +- 3 files changed, 98 insertions(+), 63 deletions(-) diff --git a/client/auth.go b/client/auth.go index 8935ecb2..13c629a8 100644 --- a/client/auth.go +++ b/client/auth.go @@ -99,22 +99,39 @@ func (c *CSAPI) ConsumeRefreshToken(t ct.TestLike, refreshToken string) (newAcce } // RegisterUser will register the user with given parameters and -// return user ID, access token and device ID. It fails the test on network error. +// return user ID, access token and device ID. It fails the test on network error, +// or if registration fails for another reason (e.g. server has non-dummy requirements). func (c *CSAPI) RegisterUser(t ct.TestLike, localpart, password string) (userID, accessToken, deviceID string) { t.Helper() - reqBody := map[string]interface{}{ - "auth": map[string]string{ - "type": "m.login.dummy", - }, + reqBody := map[string]any{ "username": localpart, "password": password, } - res := c.MustDo(t, "POST", []string{"_matrix", "client", "v3", "register"}, WithJSONBody(t, reqBody)) + // First request is expected to receive a UIA challenge + res := c.Do(t, "POST", []string{"_matrix", "client", "v3", "register"}, WithJSONBody(t, reqBody)) + if res.StatusCode != 401 { + ct.Fatalf(t, "Expected 401 Unauthorized, got %d", res.StatusCode) + } body, err := io.ReadAll(res.Body) if err != nil { ct.Fatalf(t, "unable to read response body: %v", err) } + session := GetJSONFieldStr(t, body, "session") + + // Now actually register the user + reqBody["auth"] = map[string]any{ + "session": session, + "type": "m.login.dummy", + } + if session == "" { + delete(reqBody["auth"].(map[string]any), "session") + } + res = c.MustDo(t, "POST", []string{"_matrix", "client", "v3", "register"}, WithJSONBody(t, reqBody)) + body, err = io.ReadAll(res.Body) + if err != nil { + ct.Fatalf(t, "unable to read response body: %v", err) + } userID = GetJSONFieldStr(t, body, "user_id") accessToken = GetJSONFieldStr(t, body, "access_token") diff --git a/tests/csapi/apidoc_register_test.go b/tests/csapi/apidoc_register_test.go index b876abea..ca5c0a49 100644 --- a/tests/csapi/apidoc_register_test.go +++ b/tests/csapi/apidoc_register_test.go @@ -6,7 +6,9 @@ import ( "encoding/hex" "encoding/json" "fmt" + "io" "io/ioutil" + "maps" "net/http" "net/url" "testing" @@ -63,17 +65,11 @@ func TestRegistration(t *testing.T) { }) // sytest: POST /register can create a user t.Run("POST /register can create a user", func(t *testing.T) { - // Venator: https://github.com/matrix-org/complement/issues/893 - runtime.SkipIf(t, runtime.Venator) t.Parallel() - res := unauthedClient.Do(t, "POST", []string{"_matrix", "client", "v3", "register"}, client.WithRawBody(json.RawMessage(`{ - "auth": { - "type": "m.login.dummy" - }, - "username": "post-can-create-a-user", - "password": "sUp3rs3kr1t" - }`))) + reqBody, _ := startUIASession(t, unauthedClient, "post-can-create-a-user", "sUp3rs3kr1t", nil) + res := unauthedClient.Do(t, "POST", []string{"_matrix", "client", "v3", "register"}, client.WithJSONBody(t, reqBody)) must.MatchResponse(t, res, match.HTTPResponse{ + StatusCode: 200, JSON: []match.JSON{ match.JSONKeyTypeEqual("access_token", gjson.String), match.JSONKeyTypeEqual("user_id", gjson.String), @@ -82,17 +78,11 @@ func TestRegistration(t *testing.T) { }) // sytest: POST /register downcases capitals in usernames t.Run("POST /register downcases capitals in usernames", func(t *testing.T) { - // Venator: https://github.com/matrix-org/complement/issues/893 - runtime.SkipIf(t, runtime.Venator) t.Parallel() - res := unauthedClient.Do(t, "POST", []string{"_matrix", "client", "v3", "register"}, client.WithRawBody(json.RawMessage(`{ - "auth": { - "type": "m.login.dummy" - }, - "username": "user-UPPER", - "password": "sUp3rs3kr1t" - }`))) + reqBody, _ := startUIASession(t, unauthedClient, "user-UPPER", "sUp3rs3kr1t", nil) + res := unauthedClient.Do(t, "POST", []string{"_matrix", "client", "v3", "register"}, client.WithJSONBody(t, reqBody)) must.MatchResponse(t, res, match.HTTPResponse{ + StatusCode: 200, JSON: []match.JSON{ match.JSONKeyTypeEqual("access_token", gjson.String), match.JSONKeyEqual("user_id", "@user-upper:hs1"), @@ -101,19 +91,12 @@ func TestRegistration(t *testing.T) { }) // sytest: POST /register returns the same device_id as that in the request t.Run("POST /register returns the same device_id as that in the request", func(t *testing.T) { - // Venator: https://github.com/matrix-org/complement/issues/893 - runtime.SkipIf(t, runtime.Venator) t.Parallel() deviceID := "my_device_id" - res := unauthedClient.Do(t, "POST", []string{"_matrix", "client", "v3", "register"}, client.WithRawBody(json.RawMessage(`{ - "auth": { - "type": "m.login.dummy" - }, - "username": "user-device", - "password": "sUp3rs3kr1t", - "device_id": "`+deviceID+`" - }`))) + reqBody, _ := startUIASession(t, unauthedClient, "user-device", deviceID, map[string]any{"device_id": deviceID}) + res := unauthedClient.Do(t, "POST", []string{"_matrix", "client", "v3", "register"}, client.WithJSONBody(t, reqBody)) must.MatchResponse(t, res, match.HTTPResponse{ + StatusCode: 200, JSON: []match.JSON{ match.JSONKeyTypeEqual("access_token", gjson.String), match.JSONKeyEqual("device_id", deviceID), @@ -122,8 +105,6 @@ func TestRegistration(t *testing.T) { }) // sytest: POST /register rejects registration of usernames with '$q' t.Run("POST /register rejects usernames with special characters", func(t *testing.T) { - // Venator: https://github.com/matrix-org/complement/issues/893 - runtime.SkipIf(t, runtime.Venator) t.Parallel() specialChars := []string{ `!`, @@ -143,14 +124,13 @@ func TestRegistration(t *testing.T) { `'`, } for _, ch := range specialChars { - res := unauthedClient.Do(t, "POST", []string{"_matrix", "client", "v3", "register"}, - client.WithJSONBody(t, map[string]interface{}{ - "auth": map[string]string{ - "type": "m.login.dummy", - }, - "username": "user-" + ch + "-reject-please", - "password": "sUp3rs3kr1t", - })) + reqBody := map[string]any{ + "username": "user-" + ch + "-reject-please", + "password": "sUp3rs3kr1t", + } + res := unauthedClient.Do(t, "POST", []string{"_matrix", "client", "v3", "register"}, client.WithJSONBody(t, reqBody)) + // N.B. servers are expected to validate request bodies before handling UIA, + // so 400 is expected here, not 401. must.MatchResponse(t, res, match.HTTPResponse{ StatusCode: 400, JSON: []match.JSON{ @@ -160,37 +140,30 @@ func TestRegistration(t *testing.T) { } }) t.Run("POST /register rejects if user already exists", func(t *testing.T) { - // Venator: https://github.com/matrix-org/complement/issues/893 - runtime.SkipIf(t, runtime.Venator) + // Dendrite: auth is validated before input, meaning the second register request needs to start a fresh + // auth session. This conflicts with Synapse, which forbids a second session being started, as it + // validates the input before auth. Skip on Dendrite for now. + runtime.SkipIf(t, runtime.Dendrite) t.Parallel() - res := unauthedClient.Do(t, "POST", []string{"_matrix", "client", "v3", "register"}, client.WithRawBody(json.RawMessage(`{ - "auth": { - "type": "m.login.dummy" - }, - "username": "post-can-create-a-user-once", - "password": "sUp3rs3kr1t" - }`))) + reqBody, _ := startUIASession(t, unauthedClient, "post-can-create-a-user-once", "sUp3rs3kr1t", nil) + res := unauthedClient.Do(t, "POST", []string{"_matrix", "client", "v3", "register"}, client.WithJSONBody(t, reqBody)) must.MatchResponse(t, res, match.HTTPResponse{ JSON: []match.JSON{ match.JSONKeyTypeEqual("access_token", gjson.String), match.JSONKeyTypeEqual("user_id", gjson.String), }, }) - res = unauthedClient.Do(t, "POST", []string{"_matrix", "client", "v3", "register"}, client.WithRawBody(json.RawMessage(`{ - "auth": { - "type": "m.login.dummy" - }, - "username": "post-can-create-a-user-once", - "password": "anotherSuperSecret" - }`))) + delete(reqBody, "auth") + res = unauthedClient.Do(t, "POST", []string{"_matrix", "client", "v3", "register"}, client.WithJSONBody(t, reqBody)) must.MatchResponse(t, res, match.HTTPResponse{ StatusCode: 400, + JSON: []match.JSON{ + match.JSONKeyEqual("errcode", "M_USER_IN_USE"), + }, }) }) // sytest: POST /register allows registration of usernames with '$chr' t.Run("POST /register allows registration of usernames with ", func(t *testing.T) { - // Venator: https://github.com/matrix-org/complement/issues/893 - runtime.SkipIf(t, runtime.Venator) testChars := []rune("q3._=-/") for x := range testChars { localpart := fmt.Sprintf("chrtestuser%s", string(testChars[x])) @@ -321,6 +294,25 @@ func TestRegistration(t *testing.T) { }, }) }) + // Test that subsequent calls to /_matrix/client/v3/register after receiving a UIA + // challenge fail if the session is not provided. + t.Run("Registration without a session fails", func(t *testing.T) { + // Many implementations historically did not enforce this requirement strictly + runtime.SkipIf(t, runtime.Synapse, runtime.Dendrite, runtime.Conduit) + t.Parallel() + reqBody, session := startUIASession(t, unauthedClient, "auth-requires-session", "sUp3rs3kr1t", nil) + if session == "" { + t.Skip("Homeserver does not require a session for UIA") + } + delete(reqBody["auth"].(map[string]any), "session") + // Re-send the same request without the session. + // Since session is required if it is provided by the homeserver, this should + // return an error + res := unauthedClient.Do(t, "POST", []string{"_matrix", "client", "v3", "register"}, client.WithJSONBody(t, reqBody)) + must.MatchResponse(t, res, match.HTTPResponse{ + StatusCode: 401, + }) + }) }) } @@ -359,3 +351,29 @@ func registerSharedSecret(t *testing.T, c *client.CSAPI, user, pass string, isAd resp = c.Do(t, "POST", []string{"_synapse", "admin", "v1", "register"}, client.WithJSONBody(t, reqBody)) return resp } + +// startUIASession starts a UIA session and returns the updated request body, +// and associated session token, failing the test if the response is not a UIA challenge. +func startUIASession(t *testing.T, c *client.CSAPI, user, pass string, extra map[string]any) (map[string]any, string) { + reqBody := map[string]any{ + "username": user, + "password": pass, + } + if extra != nil { + maps.Copy(reqBody, extra) + } + res := c.Do(t, "POST", []string{"_matrix", "client", "v3", "register"}, client.WithJSONBody(t, reqBody)) + if res.StatusCode != 401 { + t.Fatalf("expected status code 401 (UIA challenge), got %d", res.StatusCode) + } + body, err := io.ReadAll(res.Body) + if err != nil { + t.Fatal(err) + } + session := client.GetJSONFieldStr(t, body, "session") + reqBody["auth"] = map[string]any{"session": session, "type": "m.login.dummy"} + if session == "" { + delete(reqBody["auth"].(map[string]any), "session") + } + return reqBody, session +} diff --git a/tests/csapi/power_levels_test.go b/tests/csapi/power_levels_test.go index a28e6b81..030631b3 100644 --- a/tests/csapi/power_levels_test.go +++ b/tests/csapi/power_levels_test.go @@ -129,7 +129,7 @@ func TestPowerLevels(t *testing.T) { func(body gjson.Result) error { // This key should be missing for room v12+ if gomatrixserverlib.MustGetRoomVersion(defaultRoomVersion).PrivilegedCreators() { - must.MatchGJSON(t, body, match.JSONKeyMissing("users." + client.GjsonEscape(alice.UserID))) + must.MatchGJSON(t, body, match.JSONKeyMissing("users."+client.GjsonEscape(alice.UserID))) return nil } else { userDefault := int(body.Get("users_default").Num)