-
Notifications
You must be signed in to change notification settings - Fork 5
/
auth_credentials.go
92 lines (79 loc) · 2.87 KB
/
auth_credentials.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
package controllers
import (
"net/http"
"time"
"github.com/labstack/echo/v4"
"github.com/lachlan2k/phatcrack/api/internal/auth"
"github.com/lachlan2k/phatcrack/api/internal/config"
"github.com/lachlan2k/phatcrack/api/internal/db"
"github.com/lachlan2k/phatcrack/api/internal/roles"
"github.com/lachlan2k/phatcrack/api/internal/util"
"github.com/lachlan2k/phatcrack/common/pkg/apitypes"
log "github.com/sirupsen/logrus"
"golang.org/x/crypto/bcrypt"
)
func handleCredentialLogin(sessHandler auth.SessionHandler) echo.HandlerFunc {
return func(c echo.Context) error {
if !isCredentialAuthAllowed() {
return echo.NewHTTPError(http.StatusBadRequest, "Credential auth is not enabled")
}
req, err := util.BindAndValidate[apitypes.AuthLoginRequestDTO](c)
if err != nil {
return err
}
minTime := time.After(250 * time.Millisecond)
defer func() { <-minTime }()
user, err := db.GetUserByUsername(req.Username)
if err == db.ErrNotFound {
return echo.NewHTTPError(http.StatusUnauthorized, "Invalid credentials")
} else if err != nil {
return util.ServerError("Internal error", err)
}
if user.IsPasswordLocked() {
AuditLog(c, log.Fields{
"attempted_username": user.Username,
}, "User attempted to log in with credentials, but password is locked")
return echo.NewHTTPError(http.StatusUnauthorized, "Invalid credentials")
}
hashingTest := bcrypt.CompareHashAndPassword([]byte(user.PasswordHash), []byte(req.Password))
if hashingTest == bcrypt.ErrMismatchedHashAndPassword {
AuditLog(c, log.Fields{
"attempted_username": user.Username,
}, "Incorrect password submitted")
return echo.NewHTTPError(http.StatusUnauthorized, "Invalid credentials")
}
if hashingTest != nil {
return util.ServerError("Internal error", hashingTest)
}
sessHandler.Start(c, auth.SessionData{
UserID: user.ID.String(),
HasCompletedMFA: false,
})
response := apitypes.AuthLoginResponseDTO{
User: apitypes.AuthCurrentUserDTO{
ID: user.ID.String(),
Username: user.Username,
Roles: user.Roles,
IsPasswordLocked: user.IsPasswordLocked(),
},
IsAwaitingMFA: user.HasRole(roles.RoleMFAEnrolled),
RequiresPasswordChange: user.HasRole(roles.RoleRequiresPasswordChange),
RequiresMFAEnrollment: config.Get().Auth.General.IsMFARequired && !user.HasRole(roles.RoleMFAEnrolled) && !user.HasRole(roles.RoleMFAExempt),
}
logMessage := "Session started"
if response.IsAwaitingMFA {
logMessage += ", user needs to complete MFA"
}
if response.RequiresPasswordChange {
logMessage += ", user needs to change password"
}
if response.RequiresMFAEnrollment {
logMessage += ", user needs to enroll MFA"
}
AuditLog(c, log.Fields{
"authenticated_username": user.Username,
"auth_type": "credentials",
}, logMessage)
return c.JSON(http.StatusOK, response)
}
}