aboutsummaryrefslogtreecommitdiff
path: root/clientapi/auth/user_interactive_test.go
diff options
context:
space:
mode:
authorKegsay <kegan@matrix.org>2020-07-10 00:39:44 +0100
committerGitHub <noreply@github.com>2020-07-10 00:39:44 +0100
commitabf26c12f1a97fd2894a0509de9cf4a91c79d3ab (patch)
tree13b693141a36bfc4ae2ef2759e67dca92b2fc857 /clientapi/auth/user_interactive_test.go
parent9cc52f47f3ea2e8a009731cc46117cb996aed722 (diff)
Add User-Interactive Authentication (#1193)
* Add User-Interactive Authentication And use it when deleting a device. With tests. * Make remaining sytest pass * Linting * 403 not 401 on wrong user/pass
Diffstat (limited to 'clientapi/auth/user_interactive_test.go')
-rw-r--r--clientapi/auth/user_interactive_test.go174
1 files changed, 174 insertions, 0 deletions
diff --git a/clientapi/auth/user_interactive_test.go b/clientapi/auth/user_interactive_test.go
new file mode 100644
index 00000000..d12652c0
--- /dev/null
+++ b/clientapi/auth/user_interactive_test.go
@@ -0,0 +1,174 @@
+package auth
+
+import (
+ "context"
+ "encoding/json"
+ "fmt"
+ "testing"
+
+ "github.com/matrix-org/dendrite/internal/config"
+ "github.com/matrix-org/dendrite/userapi/api"
+ "github.com/matrix-org/gomatrixserverlib"
+ "github.com/matrix-org/util"
+)
+
+var (
+ ctx = context.Background()
+ serverName = gomatrixserverlib.ServerName("example.com")
+ // space separated localpart+password -> account
+ lookup = make(map[string]*api.Account)
+ device = &api.Device{
+ AccessToken: "flibble",
+ DisplayName: "My Device",
+ ID: "device_id_goes_here",
+ }
+)
+
+func getAccountByPassword(ctx context.Context, localpart, plaintextPassword string) (*api.Account, error) {
+ acc, ok := lookup[localpart+" "+plaintextPassword]
+ if !ok {
+ return nil, fmt.Errorf("unknown user/password")
+ }
+ return acc, nil
+}
+
+func setup() *UserInteractive {
+ cfg := &config.Dendrite{}
+ cfg.Matrix.ServerName = serverName
+ return NewUserInteractive(getAccountByPassword, cfg)
+}
+
+func TestUserInteractiveChallenge(t *testing.T) {
+ uia := setup()
+ // no auth key results in a challenge
+ _, errRes := uia.Verify(ctx, []byte(`{}`), device)
+ if errRes == nil {
+ t.Fatalf("Verify succeeded with {} but expected failure")
+ }
+ if errRes.Code != 401 {
+ t.Errorf("Expected HTTP 401, got %d", errRes.Code)
+ }
+}
+
+func TestUserInteractivePasswordLogin(t *testing.T) {
+ uia := setup()
+ // valid password login succeeds when an account exists
+ lookup["alice herpassword"] = &api.Account{
+ Localpart: "alice",
+ ServerName: serverName,
+ UserID: fmt.Sprintf("@alice:%s", serverName),
+ }
+ // valid password requests
+ testCases := []json.RawMessage{
+ // deprecated form
+ []byte(`{
+ "auth": {
+ "type": "m.login.password",
+ "user": "alice",
+ "password": "herpassword"
+ }
+ }`),
+ // new form
+ []byte(`{
+ "auth": {
+ "type": "m.login.password",
+ "identifier": {
+ "type": "m.id.user",
+ "user": "alice"
+ },
+ "password": "herpassword"
+ }
+ }`),
+ }
+ for _, tc := range testCases {
+ _, errRes := uia.Verify(ctx, tc, device)
+ if errRes != nil {
+ t.Errorf("Verify failed but expected success for request: %s - got %+v", string(tc), errRes)
+ }
+ }
+}
+
+func TestUserInteractivePasswordBadLogin(t *testing.T) {
+ uia := setup()
+ // password login fails when an account exists but is specced wrong
+ lookup["bob hispassword"] = &api.Account{
+ Localpart: "bob",
+ ServerName: serverName,
+ UserID: fmt.Sprintf("@bob:%s", serverName),
+ }
+ // invalid password requests
+ testCases := []struct {
+ body json.RawMessage
+ wantRes util.JSONResponse
+ }{
+ {
+ // fields not in an auth dict
+ body: []byte(`{
+ "type": "m.login.password",
+ "user": "bob",
+ "password": "hispassword"
+ }`),
+ wantRes: util.JSONResponse{
+ Code: 401,
+ },
+ },
+ {
+ // wrong type
+ body: []byte(`{
+ "auth": {
+ "type": "m.login.not_password",
+ "identifier": {
+ "type": "m.id.user",
+ "user": "bob"
+ },
+ "password": "hispassword"
+ }
+ }`),
+ wantRes: util.JSONResponse{
+ Code: 400,
+ },
+ },
+ {
+ // identifier type is wrong
+ body: []byte(`{
+ "auth": {
+ "type": "m.login.password",
+ "identifier": {
+ "type": "m.id.thirdparty",
+ "user": "bob"
+ },
+ "password": "hispassword"
+ }
+ }`),
+ wantRes: util.JSONResponse{
+ Code: 401,
+ },
+ },
+ {
+ // wrong password
+ body: []byte(`{
+ "auth": {
+ "type": "m.login.password",
+ "identifier": {
+ "type": "m.id.user",
+ "user": "bob"
+ },
+ "password": "not_his_password"
+ }
+ }`),
+ wantRes: util.JSONResponse{
+ Code: 401,
+ },
+ },
+ }
+ for _, tc := range testCases {
+ _, errRes := uia.Verify(ctx, tc.body, device)
+ if errRes == nil {
+ t.Errorf("Verify succeeded but expected failure for request: %s", string(tc.body))
+ continue
+ }
+ if errRes.Code != tc.wantRes.Code {
+ t.Errorf("got code %d want code %d for request: %s", errRes.Code, tc.wantRes.Code, string(tc.body))
+ }
+ }
+}