MCPcopy Index your code
hub / github.com/coder/coder / loginRequest

Method loginRequest

coderd/userauth.go:564–641  ·  view source on GitHub ↗

loginRequest will process a LoginWithPasswordRequest and return the user if the credentials are correct. If 'false' is returned, the authentication failed and the appropriate error will be written to the ResponseWriter. The user struct is always returned, even if authentication failed. This is to s

(ctx context.Context, rw http.ResponseWriter, req codersdk.LoginWithPasswordRequest)

Source from the content-addressed store, hash-verified

562// The user struct is always returned, even if authentication failed. This is
563// to support knowing what user attempted to login.
564func (api *API) loginRequest(ctx context.Context, rw http.ResponseWriter, req codersdk.LoginWithPasswordRequest) (database.User, rbac.Subject, bool) {
565 logger := api.Logger.Named(userAuthLoggerName)
566
567 //nolint:gocritic // In order to login, we need to get the user first!
568 user, err := api.Database.GetUserByEmailOrUsername(dbauthz.AsSystemRestricted(ctx), database.GetUserByEmailOrUsernameParams{
569 Email: req.Email,
570 })
571 if err != nil && !xerrors.Is(err, sql.ErrNoRows) {
572 logger.Error(ctx, "unable to fetch user by email", slog.Error(err))
573 httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
574 Message: "Internal error.",
575 })
576 return user, rbac.Subject{}, false
577 }
578
579 // If the user doesn't exist, it will be a default struct.
580 equal, err := userpassword.Compare(string(user.HashedPassword), req.Password)
581 if err != nil {
582 logger.Error(ctx, "unable to compare passwords", slog.Error(err))
583 httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
584 Message: "Internal error.",
585 })
586 return user, rbac.Subject{}, false
587 }
588
589 if !equal {
590 // This message is the same as above to remove ease in detecting whether
591 // users are registered or not. Attackers still could with a timing attack.
592 httpapi.Write(ctx, rw, http.StatusUnauthorized, codersdk.Response{
593 Message: "Incorrect email or password.",
594 })
595 return user, rbac.Subject{}, false
596 }
597
598 // If password authentication is disabled and the user does not have the
599 // owner role, block the request.
600 if api.DeploymentValues.DisablePasswordAuth {
601 httpapi.Write(ctx, rw, http.StatusForbidden, codersdk.Response{
602 Message: "Password authentication is disabled.",
603 })
604 return user, rbac.Subject{}, false
605 }
606
607 if user.LoginType != database.LoginTypePassword {
608 httpapi.Write(ctx, rw, http.StatusForbidden, codersdk.Response{
609 Message: fmt.Sprintf("Incorrect login type, attempting to use %q but user is of login type %q", database.LoginTypePassword, user.LoginType),
610 })
611 return user, rbac.Subject{}, false
612 }
613
614 user, err = ActivateDormantUser(api.Logger, &api.Auditor, api.Database)(ctx, user)
615 if err != nil {
616 httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
617 Message: "Internal error.",
618 Detail: err.Error(),
619 })
620 return user, rbac.Subject{}, false
621 }

Callers 2

postConvertLoginTypeMethod · 0.95
postLoginMethod · 0.95

Calls 9

AsSystemRestrictedFunction · 0.92
WriteFunction · 0.92
CompareFunction · 0.92
UserRBACSubjectFunction · 0.92
ActivateDormantUserFunction · 0.85
NamedMethod · 0.80
IsMethod · 0.45
ErrorMethod · 0.45

Tested by

no test coverage detected