+56
-9
server/handle_account_signin.go
+56
-9
server/handle_account_signin.go
···
2
3
import (
4
"errors"
5
"strings"
6
7
"github.com/bluesky-social/indigo/atproto/syntax"
8
"github.com/gorilla/sessions"
···
15
)
16
17
type OauthSigninInput struct {
18
-
Username string `form:"username"`
19
-
Password string `form:"password"`
20
-
QueryParams string `form:"query_params"`
21
}
22
23
func (s *Server) getSessionRepoOrErr(e echo.Context) (*models.RepoActor, *sessions.Session, error) {
···
44
func getFlashesFromSession(e echo.Context, sess *sessions.Session) map[string]any {
45
defer sess.Save(e.Request(), e.Response())
46
return map[string]any{
47
-
"errors": sess.Flashes("error"),
48
-
"successes": sess.Flashes("success"),
49
}
50
}
51
···
82
idtype = "email"
83
}
84
85
// TODO: we should make this a helper since we do it for the base create_session as well
86
var repo models.RepoActor
87
var err error
···
100
sess.AddFlash("Something went wrong!", "error")
101
}
102
sess.Save(e.Request(), e.Response())
103
-
return e.Redirect(303, "/account/signin")
104
}
105
106
if err := bcrypt.CompareHashAndPassword([]byte(repo.Password), []byte(req.Password)); err != nil {
···
110
sess.AddFlash("Something went wrong!", "error")
111
}
112
sess.Save(e.Request(), e.Response())
113
-
return e.Redirect(303, "/account/signin")
114
}
115
116
sess.Options = &sessions.Options{
···
126
return err
127
}
128
129
-
if req.QueryParams != "" {
130
-
return e.Redirect(303, "/oauth/authorize?"+req.QueryParams)
131
} else {
132
return e.Redirect(303, "/account")
133
}
···
2
3
import (
4
"errors"
5
+
"fmt"
6
"strings"
7
+
"time"
8
9
"github.com/bluesky-social/indigo/atproto/syntax"
10
"github.com/gorilla/sessions"
···
17
)
18
19
type OauthSigninInput struct {
20
+
Username string `form:"username"`
21
+
Password string `form:"password"`
22
+
AuthFactorToken string `form:"token"`
23
+
QueryParams string `form:"query_params"`
24
}
25
26
func (s *Server) getSessionRepoOrErr(e echo.Context) (*models.RepoActor, *sessions.Session, error) {
···
47
func getFlashesFromSession(e echo.Context, sess *sessions.Session) map[string]any {
48
defer sess.Save(e.Request(), e.Response())
49
return map[string]any{
50
+
"errors": sess.Flashes("error"),
51
+
"successes": sess.Flashes("success"),
52
+
"tokenrequired": sess.Flashes("tokenrequired"),
53
}
54
}
55
···
86
idtype = "email"
87
}
88
89
+
queryParams := ""
90
+
if req.QueryParams != "" {
91
+
queryParams = fmt.Sprintf("?%s", req.QueryParams)
92
+
}
93
+
94
// TODO: we should make this a helper since we do it for the base create_session as well
95
var repo models.RepoActor
96
var err error
···
109
sess.AddFlash("Something went wrong!", "error")
110
}
111
sess.Save(e.Request(), e.Response())
112
+
return e.Redirect(303, "/account/signin"+queryParams)
113
}
114
115
if err := bcrypt.CompareHashAndPassword([]byte(repo.Password), []byte(req.Password)); err != nil {
···
119
sess.AddFlash("Something went wrong!", "error")
120
}
121
sess.Save(e.Request(), e.Response())
122
+
return e.Redirect(303, "/account/signin"+queryParams)
123
+
}
124
+
125
+
// if repo requires auth factor token and one hasn't been provided, return error prompting for one
126
+
if repo.EmailAuthFactor && req.AuthFactorToken == "" {
127
+
err = s.createAndSendAuthCode(ctx, repo)
128
+
if err != nil {
129
+
sess.AddFlash("Something went wrong!", "error")
130
+
sess.Save(e.Request(), e.Response())
131
+
return e.Redirect(303, "/account/signin"+queryParams)
132
+
}
133
+
134
+
sess.AddFlash("requires 2FA token", "tokenrequired")
135
+
sess.Save(e.Request(), e.Response())
136
+
return e.Redirect(303, "/account/signin"+queryParams)
137
+
}
138
+
139
+
// if auth factor is required, now check that the one provided is valid
140
+
if repo.EmailAuthFactor {
141
+
if repo.AuthCode == nil || repo.AuthCodeExpiresAt == nil {
142
+
err = s.createAndSendAuthCode(ctx, repo)
143
+
if err != nil {
144
+
sess.AddFlash("Something went wrong!", "error")
145
+
sess.Save(e.Request(), e.Response())
146
+
return e.Redirect(303, "/account/signin"+queryParams)
147
+
}
148
+
149
+
sess.AddFlash("requires 2FA token", "tokenrequired")
150
+
sess.Save(e.Request(), e.Response())
151
+
return e.Redirect(303, "/account/signin"+queryParams)
152
+
}
153
+
154
+
if *repo.AuthCode != req.AuthFactorToken {
155
+
return helpers.InvalidTokenError(e)
156
+
}
157
+
158
+
if time.Now().UTC().After(*repo.AuthCodeExpiresAt) {
159
+
return helpers.ExpiredTokenError(e)
160
+
}
161
}
162
163
sess.Options = &sessions.Options{
···
173
return err
174
}
175
176
+
if queryParams != "" {
177
+
return e.Redirect(303, "/oauth/authorize"+queryParams)
178
} else {
179
return e.Redirect(303, "/account")
180
}
+7
-7
server/handle_server_create_session.go
+7
-7
server/handle_server_create_session.go
···
86
return helpers.ServerError(e, nil)
87
}
88
89
// if repo requires auth factor token and one hasn't been provided, return error prompting for one
90
if repo.EmailAuthFactor && (req.AuthFactorToken == nil || *req.AuthFactorToken == "") {
91
err = s.createAndSendAuthCode(ctx, repo)
···
116
if time.Now().UTC().After(*repo.AuthCodeExpiresAt) {
117
return helpers.ExpiredTokenError(e)
118
}
119
-
}
120
-
121
-
if err := bcrypt.CompareHashAndPassword([]byte(repo.Password), []byte(req.Password)); err != nil {
122
-
if err != bcrypt.ErrMismatchedHashAndPassword {
123
-
s.logger.Error("erorr comparing hash and password", "error", err)
124
-
}
125
-
return helpers.InputError(e, to.StringPtr("InvalidRequest"))
126
}
127
128
sess, err := s.createSession(ctx, &repo.Repo)
···
86
return helpers.ServerError(e, nil)
87
}
88
89
+
if err := bcrypt.CompareHashAndPassword([]byte(repo.Password), []byte(req.Password)); err != nil {
90
+
if err != bcrypt.ErrMismatchedHashAndPassword {
91
+
s.logger.Error("erorr comparing hash and password", "error", err)
92
+
}
93
+
return helpers.InputError(e, to.StringPtr("InvalidRequest"))
94
+
}
95
+
96
// if repo requires auth factor token and one hasn't been provided, return error prompting for one
97
if repo.EmailAuthFactor && (req.AuthFactorToken == nil || *req.AuthFactorToken == "") {
98
err = s.createAndSendAuthCode(ctx, repo)
···
123
if time.Now().UTC().After(*repo.AuthCodeExpiresAt) {
124
return helpers.ExpiredTokenError(e)
125
}
126
}
127
128
sess, err := s.createSession(ctx, &repo.Repo)
+4
server/templates/signin.html
+4
server/templates/signin.html
···
26
type="password"
27
placeholder="Password"
28
/>
29
+
{{ if .flashes.tokenrequired }}
30
+
<br />
31
+
<input name="token" id="token" placeholder="Enter your 2FA token" />
32
+
{{ end }}
33
<input name="query_params" type="hidden" value="{{ .QueryParams }}" />
34
<button class="primary" type="submit" value="Login">Login</button>
35
</form>