mirror of
https://github.com/matrix-org/dendrite.git
synced 2026-01-16 18:43:10 -06:00
Takwaiw/dendrite publickey (#2)
* Implementation of MSC 3782 Add publickey login as a new auth type. Co-authored-by: Tak Wai Wong <takwaiw@gmail.com>
This commit is contained in:
parent
56194c4e32
commit
3145a9dc52
|
|
@ -246,7 +246,7 @@ func (u *UserInteractive) ResponseWithChallenge(sessionID string, response inter
|
||||||
// Verify returns an error/challenge response to send to the client, or nil if the user is authenticated.
|
// Verify returns an error/challenge response to send to the client, or nil if the user is authenticated.
|
||||||
// `bodyBytes` is the HTTP request body which must contain an `auth` key.
|
// `bodyBytes` is the HTTP request body which must contain an `auth` key.
|
||||||
// Returns the login that was verified for additional checks if required.
|
// Returns the login that was verified for additional checks if required.
|
||||||
func (u *UserInteractive) Verify(ctx context.Context, bodyBytes []byte, device *api.Device) (*Login, *util.JSONResponse) {
|
func (u *UserInteractive) Verify(ctx context.Context, bodyBytes []byte) (*Login, *util.JSONResponse) {
|
||||||
// TODO: rate limit
|
// TODO: rate limit
|
||||||
|
|
||||||
// "A client should first make a request with no auth parameter. The homeserver returns an HTTP 401 response, with a JSON body"
|
// "A client should first make a request with no auth parameter. The homeserver returns an HTTP 401 response, with a JSON body"
|
||||||
|
|
|
||||||
|
|
@ -17,11 +17,6 @@ var (
|
||||||
serverName = gomatrixserverlib.ServerName("example.com")
|
serverName = gomatrixserverlib.ServerName("example.com")
|
||||||
// space separated localpart+password -> account
|
// space separated localpart+password -> account
|
||||||
lookup = make(map[string]*api.Account)
|
lookup = make(map[string]*api.Account)
|
||||||
device = &api.Device{
|
|
||||||
AccessToken: "flibble",
|
|
||||||
DisplayName: "My Device",
|
|
||||||
ID: "device_id_goes_here",
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type fakeAccountDatabase struct {
|
type fakeAccountDatabase struct {
|
||||||
|
|
@ -60,7 +55,7 @@ func setup() *UserInteractive {
|
||||||
func TestUserInteractiveChallenge(t *testing.T) {
|
func TestUserInteractiveChallenge(t *testing.T) {
|
||||||
uia := setup()
|
uia := setup()
|
||||||
// no auth key results in a challenge
|
// no auth key results in a challenge
|
||||||
_, errRes := uia.Verify(ctx, []byte(`{}`), device)
|
_, errRes := uia.Verify(ctx, []byte(`{}`))
|
||||||
if errRes == nil {
|
if errRes == nil {
|
||||||
t.Fatalf("Verify succeeded with {} but expected failure")
|
t.Fatalf("Verify succeeded with {} but expected failure")
|
||||||
}
|
}
|
||||||
|
|
@ -100,7 +95,7 @@ func TestUserInteractivePasswordLogin(t *testing.T) {
|
||||||
}`),
|
}`),
|
||||||
}
|
}
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
_, errRes := uia.Verify(ctx, tc, device)
|
_, errRes := uia.Verify(ctx, tc)
|
||||||
if errRes != nil {
|
if errRes != nil {
|
||||||
t.Errorf("Verify failed but expected success for request: %s - got %+v", string(tc), errRes)
|
t.Errorf("Verify failed but expected success for request: %s - got %+v", string(tc), errRes)
|
||||||
}
|
}
|
||||||
|
|
@ -181,7 +176,7 @@ func TestUserInteractivePasswordBadLogin(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
_, errRes := uia.Verify(ctx, tc.body, device)
|
_, errRes := uia.Verify(ctx, tc.body)
|
||||||
if errRes == nil {
|
if errRes == nil {
|
||||||
t.Errorf("Verify succeeded but expected failure for request: %s", string(tc.body))
|
t.Errorf("Verify succeeded but expected failure for request: %s", string(tc.body))
|
||||||
continue
|
continue
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ func Deactivate(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
login, errRes := userInteractiveAuth.Verify(ctx, bodyBytes, deviceAPI)
|
login, errRes := userInteractiveAuth.Verify(ctx, bodyBytes)
|
||||||
if errRes != nil {
|
if errRes != nil {
|
||||||
return *errRes
|
return *errRes
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -198,7 +198,7 @@ func DeleteDeviceById(
|
||||||
sessionID = s
|
sessionID = s
|
||||||
}
|
}
|
||||||
|
|
||||||
login, errRes := userInteractiveAuth.Verify(ctx, bodyBytes, device)
|
login, errRes := userInteractiveAuth.Verify(ctx, bodyBytes)
|
||||||
if errRes != nil {
|
if errRes != nil {
|
||||||
switch data := errRes.JSON.(type) {
|
switch data := errRes.JSON.(type) {
|
||||||
case auth.Challenge:
|
case auth.Challenge:
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,8 @@ package config
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/matrix-org/dendrite/clientapi/auth/authtypes"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ClientAPI struct {
|
type ClientAPI struct {
|
||||||
|
|
@ -160,3 +162,44 @@ func (r *RateLimiting) Defaults() {
|
||||||
r.Threshold = 5
|
r.Threshold = 5
|
||||||
r.CooloffMS = 500
|
r.CooloffMS = 500
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ethereumAuthParams struct {
|
||||||
|
Version uint32 `json:"version"`
|
||||||
|
ChainIDs []string `json:"chain_ids"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ethereumAuthConfig struct {
|
||||||
|
Enabled bool `yaml:"enabled"`
|
||||||
|
Version uint32 `yaml:"version"`
|
||||||
|
ChainIDs []string `yaml:"chain_ids"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type publicKeyAuthentication struct {
|
||||||
|
Ethereum ethereumAuthConfig `yaml:"ethereum"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pk *publicKeyAuthentication) Enabled() bool {
|
||||||
|
return pk.Ethereum.Enabled
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pk *publicKeyAuthentication) GetPublicKeyRegistrationFlows() []authtypes.Flow {
|
||||||
|
var flows []authtypes.Flow
|
||||||
|
if pk.Ethereum.Enabled {
|
||||||
|
flows = append(flows, authtypes.Flow{Stages: []authtypes.LoginType{authtypes.LoginTypePublicKeyEthereum}})
|
||||||
|
}
|
||||||
|
|
||||||
|
return flows
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pk *publicKeyAuthentication) GetPublicKeyRegistrationParams() map[string]interface{} {
|
||||||
|
params := make(map[string]interface{})
|
||||||
|
if pk.Ethereum.Enabled {
|
||||||
|
p := ethereumAuthParams{
|
||||||
|
Version: pk.Ethereum.Version,
|
||||||
|
ChainIDs: pk.Ethereum.ChainIDs,
|
||||||
|
}
|
||||||
|
params[authtypes.LoginTypePublicKeyEthereum] = p
|
||||||
|
}
|
||||||
|
|
||||||
|
return params
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -300,10 +300,10 @@ func Test_UserStatistics(t *testing.T) {
|
||||||
},
|
},
|
||||||
R30UsersV2: map[string]int64{
|
R30UsersV2: map[string]int64{
|
||||||
"ios": 0,
|
"ios": 0,
|
||||||
"android": 0,
|
"android": 1,
|
||||||
"web": 0,
|
"web": 1,
|
||||||
"electron": 0,
|
"electron": 0,
|
||||||
"all": 0,
|
"all": 2,
|
||||||
},
|
},
|
||||||
AllUsers: 6,
|
AllUsers: 6,
|
||||||
NonBridgedUsers: 5,
|
NonBridgedUsers: 5,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue