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

Login: Implement Token-based authentication #403

Closed
3 tasks
anoadragon453 opened this issue Mar 2, 2018 · 3 comments · Fixed by #2014
Closed
3 tasks

Login: Implement Token-based authentication #403

anoadragon453 opened this issue Mar 2, 2018 · 3 comments · Fixed by #2014

Comments

@anoadragon453
Copy link
Member

anoadragon453 commented Mar 2, 2018

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
@APwhitehat
Copy link
Contributor

@anoadragon453 This is phase 1 as well, may I take this up ?

@anoadragon453
Copy link
Member Author

@APwhitehat Certainly!

@tommie
Copy link
Contributor

tommie commented Sep 26, 2021

I'm forking #1374 and splitting apart the login stuff to be PRd separately first.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
4 participants