Skip to content
This repository was archived by the owner on Nov 25, 2024. It is now read-only.
This repository was archived by the owner on Nov 25, 2024. It is now read-only.

Login: Implement Token-based authentication #403

@anoadragon453

Description

@anoadragon453

Spec URL: https://matrix.org/docs/spec/client_server/r0.3.0.html#post-matrix-client-r0-login https://matrix.org/docs/spec/client_server/r0.5.0#token-based

Difficulty: Medium

// Login implements GET and POST /login
func Login(
req *http.Request, accountDB *accounts.Database, deviceDB *devices.Database,
cfg config.Dendrite,
) util.JSONResponse {
if req.Method == "GET" { // TODO: support other forms of login other than password, depending on config options
return util.JSONResponse{
Code: 200,
JSON: passwordLogin(),
}
} else if req.Method == "POST" {
var r passwordRequest
resErr := httputil.UnmarshalJSONRequest(req, &r)
if resErr != nil {
return *resErr
}
if r.User == "" {
return util.JSONResponse{
Code: 400,
JSON: jsonerror.BadJSON("'user' must be supplied."),
}
}
util.GetLogger(req.Context()).WithField("user", r.User).Info("Processing login request")
// r.User can either be a user ID or just the localpart... or other things maybe.
localpart := r.User
if strings.HasPrefix(r.User, "@") {
var domain gomatrixserverlib.ServerName
var err error
localpart, domain, err = gomatrixserverlib.SplitID('@', r.User)
if err != nil {
return util.JSONResponse{
Code: 400,
JSON: jsonerror.InvalidUsername("Invalid username"),
}
}
if domain != cfg.Matrix.ServerName {
return util.JSONResponse{
Code: 400,
JSON: jsonerror.InvalidUsername("User ID not ours"),
}
}
}
acc, err := accountDB.GetAccountByPassword(req.Context(), localpart, r.Password)
if err != nil {
// Technically we could tell them if the user does not exist by checking if err == sql.ErrNoRows
// but that would leak the existence of the user.
return util.JSONResponse{
Code: 403,
JSON: jsonerror.Forbidden("username or password was incorrect, or the accouqnt does not exist"),
}
}
token, err := auth.GenerateAccessToken()
if err != nil {
httputil.LogThenError(req, err)
}
// TODO: Use the device ID in the request
dev, err := deviceDB.CreateDevice(
req.Context(), acc.Localpart, nil, token, r.InitialDisplayName,
)
if err != nil {
return util.JSONResponse{
Code: 500,
JSON: jsonerror.Unknown("failed to create device: " + err.Error()),
}
}
return util.JSONResponse{
Code: 200,
JSON: loginResponse{
UserID: dev.UserID,
AccessToken: dev.AccessToken,
HomeServer: cfg.Matrix.ServerName,
DeviceID: dev.ID,
},
}
}
return util.JSONResponse{
Code: 405,
JSON: jsonerror.NotFound("Bad method"),
}
}

We currently only allow password-based authentication for login. Token-based authentication will be necessary for basic operation with clients. Currently users have tokens generated for them, we just need to check them on login.

Summary:

  • Differentiate between "type": "m.login.token" and "m.login.password" in request body
  • Authenticate user based on token and device ID. Relationship between access tokens and devices
  • Create test case(s) for logging in with access token

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions