Mercurial > gemma
annotate pkg/controllers/pwreset.go @ 3956:4f9a1ff2c2ee pwreset-rework
Reworked password reset to be single mailed.
author | Sascha L. Teichmann <sascha.teichmann@intevation.de> |
---|---|
date | Tue, 16 Jul 2019 12:38:44 +0200 |
parents | ed4820efb7e6 |
children | 6dd9741d6ff7 |
rev | line source |
---|---|
1017
a244b18cb916
Added GNU Affero General Public License.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
1001
diff
changeset
|
1 // This is Free Software under GNU Affero General Public License v >= 3.0 |
a244b18cb916
Added GNU Affero General Public License.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
1001
diff
changeset
|
2 // without warranty, see README.md and license for details. |
a244b18cb916
Added GNU Affero General Public License.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
1001
diff
changeset
|
3 // |
a244b18cb916
Added GNU Affero General Public License.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
1001
diff
changeset
|
4 // SPDX-License-Identifier: AGPL-3.0-or-later |
a244b18cb916
Added GNU Affero General Public License.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
1001
diff
changeset
|
5 // License-Filename: LICENSES/AGPL-3.0.txt |
a244b18cb916
Added GNU Affero General Public License.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
1001
diff
changeset
|
6 // |
a244b18cb916
Added GNU Affero General Public License.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
1001
diff
changeset
|
7 // Copyright (C) 2018 by via donau |
a244b18cb916
Added GNU Affero General Public License.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
1001
diff
changeset
|
8 // – Österreichische Wasserstraßen-Gesellschaft mbH |
a244b18cb916
Added GNU Affero General Public License.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
1001
diff
changeset
|
9 // Software engineering by Intevation GmbH |
a244b18cb916
Added GNU Affero General Public License.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
1001
diff
changeset
|
10 // |
a244b18cb916
Added GNU Affero General Public License.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
1001
diff
changeset
|
11 // Author(s): |
a244b18cb916
Added GNU Affero General Public License.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
1001
diff
changeset
|
12 // * Sascha L. Teichmann <sascha.teichmann@intevation.de> |
a244b18cb916
Added GNU Affero General Public License.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
1001
diff
changeset
|
13 // * Bernhard E. Reiter <bernhard.reiter@intevation.de> |
1317
5443f5c9154c
Added missing authors names in Go files.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
1017
diff
changeset
|
14 // * Tom Gottfried <tom.gottfried.intevation.de> |
1017
a244b18cb916
Added GNU Affero General Public License.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
1001
diff
changeset
|
15 |
302
0777aa6de45b
Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
16 package controllers |
0777aa6de45b
Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
17 |
0777aa6de45b
Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
18 import ( |
310
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
19 "bytes" |
501
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
20 "context" |
302
0777aa6de45b
Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
21 "database/sql" |
0777aa6de45b
Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
22 "encoding/hex" |
535
da5f47a0941c
Password reset: Reduce the risk of timing attacks and being a user oracle when requesting resets.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
521
diff
changeset
|
23 "errors" |
3956
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
24 "io" |
302
0777aa6de45b
Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
25 "log" |
0777aa6de45b
Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
26 "net/http" |
310
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
27 "os/exec" |
511
b96b1b258cfa
Use already declared password length in reset password.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
501
diff
changeset
|
28 "strconv" |
302
0777aa6de45b
Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
29 "strings" |
304
69e291f26bbd
Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
302
diff
changeset
|
30 "time" |
302
0777aa6de45b
Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
31 |
3956
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
32 htmlTemplate "html/template" |
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
33 textTemplate "text/template" |
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
34 |
339
33b59c848771
Factored out some miscellaneous code into own package.
Sascha L. Teichmann <teichmann@intevation.de>
parents:
332
diff
changeset
|
35 "github.com/gorilla/mux" |
33b59c848771
Factored out some miscellaneous code into own package.
Sascha L. Teichmann <teichmann@intevation.de>
parents:
332
diff
changeset
|
36 |
414
c1047fd04a3a
Moved project specific Go packages to new pkg folder.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
408
diff
changeset
|
37 "gemma.intevation.de/gemma/pkg/auth" |
c1047fd04a3a
Moved project specific Go packages to new pkg folder.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
408
diff
changeset
|
38 "gemma.intevation.de/gemma/pkg/common" |
1001
e2860eff5d03
Wait in PW reset clean up code until config is loaded.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
562
diff
changeset
|
39 "gemma.intevation.de/gemma/pkg/config" |
414
c1047fd04a3a
Moved project specific Go packages to new pkg folder.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
408
diff
changeset
|
40 "gemma.intevation.de/gemma/pkg/misc" |
442
fc37e7072022
Moved some models used in controllers to to model package because they may be needed elsewhere (e.g. GeoServer config).
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
438
diff
changeset
|
41 "gemma.intevation.de/gemma/pkg/models" |
302
0777aa6de45b
Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
42 ) |
0777aa6de45b
Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
43 |
0777aa6de45b
Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
44 const ( |
478
3af7ca761f6a
Purge password reset role
Tom Gottfried <tom@intevation.de>
parents:
442
diff
changeset
|
45 insertRequestSQL = `INSERT INTO sys_admin.password_reset_requests |
3956
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
46 (hash, username) VALUES ($1, $2) |
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
47 ON CONFLICT (username) DO UPDATE SET hash = $1` |
321
974a5e4c0055
Persist password reset requests in database.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
319
diff
changeset
|
48 |
478
3af7ca761f6a
Purge password reset role
Tom Gottfried <tom@intevation.de>
parents:
442
diff
changeset
|
49 countRequestsSQL = `SELECT count(*) FROM sys_admin.password_reset_requests` |
321
974a5e4c0055
Persist password reset requests in database.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
319
diff
changeset
|
50 |
478
3af7ca761f6a
Purge password reset role
Tom Gottfried <tom@intevation.de>
parents:
442
diff
changeset
|
51 deleteRequestSQL = `DELETE FROM sys_admin.password_reset_requests |
321
974a5e4c0055
Persist password reset requests in database.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
319
diff
changeset
|
52 WHERE hash = $1` |
974a5e4c0055
Persist password reset requests in database.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
319
diff
changeset
|
53 |
3956
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
54 findRequestSQL = `SELECT lu.username |
478
3af7ca761f6a
Purge password reset role
Tom Gottfried <tom@intevation.de>
parents:
442
diff
changeset
|
55 FROM sys_admin.password_reset_requests prr |
3af7ca761f6a
Purge password reset role
Tom Gottfried <tom@intevation.de>
parents:
442
diff
changeset
|
56 JOIN users.list_users lu on prr.username = lu.username |
321
974a5e4c0055
Persist password reset requests in database.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
319
diff
changeset
|
57 WHERE prr.hash = $1` |
974a5e4c0055
Persist password reset requests in database.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
319
diff
changeset
|
58 |
478
3af7ca761f6a
Purge password reset role
Tom Gottfried <tom@intevation.de>
parents:
442
diff
changeset
|
59 cleanupRequestsSQL = `DELETE FROM sys_admin.password_reset_requests |
321
974a5e4c0055
Persist password reset requests in database.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
319
diff
changeset
|
60 WHERE issued < $1` |
974a5e4c0055
Persist password reset requests in database.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
319
diff
changeset
|
61 |
302
0777aa6de45b
Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
62 userExistsSQL = `SELECT email_address |
478
3af7ca761f6a
Purge password reset role
Tom Gottfried <tom@intevation.de>
parents:
442
diff
changeset
|
63 FROM users.list_users WHERE username = $1` |
310
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
64 |
478
3af7ca761f6a
Purge password reset role
Tom Gottfried <tom@intevation.de>
parents:
442
diff
changeset
|
65 updatePasswordSQL = `UPDATE users.list_users |
310
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
66 SET pw = $1 WHERE username = $2` |
3956
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
67 |
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
68 deletePasswordResetRequestSQL = ` |
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
69 DELETE FROM sys_admin.password_reset_requests |
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
70 WHERE username = $1` |
302
0777aa6de45b
Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
71 ) |
0777aa6de45b
Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
72 |
0777aa6de45b
Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
73 const ( |
321
974a5e4c0055
Persist password reset requests in database.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
319
diff
changeset
|
74 hashLength = 16 |
974a5e4c0055
Persist password reset requests in database.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
319
diff
changeset
|
75 passwordLength = 20 |
974a5e4c0055
Persist password reset requests in database.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
319
diff
changeset
|
76 passwordResetValid = 12 * time.Hour |
304
69e291f26bbd
Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
302
diff
changeset
|
77 maxPasswordResets = 1000 |
69e291f26bbd
Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
302
diff
changeset
|
78 maxPasswordRequestsPerUser = 5 |
321
974a5e4c0055
Persist password reset requests in database.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
319
diff
changeset
|
79 cleanupPause = 15 * time.Minute |
304
69e291f26bbd
Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
302
diff
changeset
|
80 ) |
69e291f26bbd
Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
302
diff
changeset
|
81 |
478
3af7ca761f6a
Purge password reset role
Tom Gottfried <tom@intevation.de>
parents:
442
diff
changeset
|
82 const pwResetRole = "sys_admin" |
438
ffdb507d5b42
Removed db service user. Use an impersonated metamorph user instead.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
414
diff
changeset
|
83 |
310
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
84 var ( |
3956
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
85 errTooMuchPasswordResets = errors.New("Too many password resets") |
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
86 errNoSuchUser = errors.New("User does not exist") |
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
87 errInvalidUser = errors.New("Invalid user") |
535
da5f47a0941c
Password reset: Reduce the risk of timing attacks and being a user oracle when requesting resets.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
521
diff
changeset
|
88 ) |
da5f47a0941c
Password reset: Reduce the risk of timing attacks and being a user oracle when requesting resets.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
521
diff
changeset
|
89 |
da5f47a0941c
Password reset: Reduce the risk of timing attacks and being a user oracle when requesting resets.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
521
diff
changeset
|
90 var ( |
3956
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
91 passwordResetRequestMailTmpl = textTemplate.Must( |
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
92 textTemplate.New("request").Parse(`You or someone else has requested a password change |
310
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
93 for your account {{ .User }} on |
3956
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
94 {{ .Server }} |
302
0777aa6de45b
Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
95 |
3956
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
96 Please follow this link to have a new password generated: |
302
0777aa6de45b
Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
97 |
3956
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
98 {{ .Server }}/api/users/passwordreset/{{ .Hash }} |
302
0777aa6de45b
Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
99 |
321
974a5e4c0055
Persist password reset requests in database.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
319
diff
changeset
|
100 The link is only valid for 12 hours. |
302
0777aa6de45b
Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
101 |
516
9b3db1d7a7eb
proxy: improve texts for password reset mails.
Bernhard Reiter <bernhard@intevation.de>
parents:
511
diff
changeset
|
102 If you did not initiate this password reset or do not want to reset the |
9b3db1d7a7eb
proxy: improve texts for password reset mails.
Bernhard Reiter <bernhard@intevation.de>
parents:
511
diff
changeset
|
103 password, just ignore this email. |
9b3db1d7a7eb
proxy: improve texts for password reset mails.
Bernhard Reiter <bernhard@intevation.de>
parents:
511
diff
changeset
|
104 |
302
0777aa6de45b
Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
105 Best regards |
310
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
106 Your service team`)) |
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
107 |
3956
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
108 passwordResetPage = htmlTemplate.Must( |
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
109 htmlTemplate.New("page").Parse(`<!DOCTYPE html> |
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
110 <html lang="en"> |
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
111 <head> |
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
112 <meta charset="utf-8" /> |
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
113 <title>Password reset done</title> |
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
114 </head> |
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
115 <body> |
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
116 <p>The password reset for user <strong><tt>{{ .User }}</tt></strong> successfully done.</p> |
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
117 <p>New password: <strong><tt>{{ .Password }}</tt></strong></p> |
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
118 <p><a href="/">Go to login page.</a></p> |
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
119 </body> |
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
120 </html> |
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
121 `)) |
302
0777aa6de45b
Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
122 ) |
0777aa6de45b
Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
123 |
321
974a5e4c0055
Persist password reset requests in database.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
319
diff
changeset
|
124 func init() { |
974a5e4c0055
Persist password reset requests in database.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
319
diff
changeset
|
125 go removeOutdated() |
304
69e291f26bbd
Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
302
diff
changeset
|
126 } |
69e291f26bbd
Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
302
diff
changeset
|
127 |
321
974a5e4c0055
Persist password reset requests in database.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
319
diff
changeset
|
128 func removeOutdated() { |
1001
e2860eff5d03
Wait in PW reset clean up code until config is loaded.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
562
diff
changeset
|
129 config.WaitReady() |
321
974a5e4c0055
Persist password reset requests in database.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
319
diff
changeset
|
130 for { |
974a5e4c0055
Persist password reset requests in database.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
319
diff
changeset
|
131 time.Sleep(cleanupPause) |
1327
cabf4789e02b
To make golint happier made context.Context to be the first argument of auth.RunAs.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
1317
diff
changeset
|
132 ctx := context.Background() |
501
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
133 err := auth.RunAs( |
1327
cabf4789e02b
To make golint happier made context.Context to be the first argument of auth.RunAs.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
1317
diff
changeset
|
134 ctx, pwResetRole, |
501
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
135 func(conn *sql.Conn) error { |
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
136 good := time.Now().Add(-passwordResetValid) |
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
137 _, err := conn.ExecContext( |
1327
cabf4789e02b
To make golint happier made context.Context to be the first argument of auth.RunAs.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
1317
diff
changeset
|
138 ctx, cleanupRequestsSQL, good) |
501
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
139 return err |
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
140 }) |
321
974a5e4c0055
Persist password reset requests in database.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
319
diff
changeset
|
141 if err != nil { |
974a5e4c0055
Persist password reset requests in database.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
319
diff
changeset
|
142 log.Printf("error: %v\n", err) |
304
69e291f26bbd
Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
302
diff
changeset
|
143 } |
69e291f26bbd
Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
302
diff
changeset
|
144 } |
69e291f26bbd
Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
302
diff
changeset
|
145 } |
69e291f26bbd
Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
302
diff
changeset
|
146 |
3956
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
147 func requestMessageBody(user, hash, server string) string { |
310
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
148 var content = struct { |
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
149 User string |
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
150 Server string |
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
151 Hash string |
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
152 }{ |
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
153 User: user, |
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
154 Server: server, |
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
155 Hash: hash, |
302
0777aa6de45b
Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
156 } |
310
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
157 var buf bytes.Buffer |
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
158 if err := passwordResetRequestMailTmpl.Execute(&buf, &content); err != nil { |
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
159 log.Printf("error: %v\n", err) |
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
160 } |
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
161 return buf.String() |
302
0777aa6de45b
Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
162 } |
0777aa6de45b
Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
163 |
3956
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
164 func changedMessageBody(w io.Writer, user, password string) error { |
310
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
165 var content = struct { |
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
166 User string |
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
167 Password string |
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
168 }{ |
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
169 User: user, |
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
170 Password: password, |
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
171 } |
3956
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
172 return passwordResetPage.Execute(w, &content) |
310
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
173 } |
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
174 |
302
0777aa6de45b
Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
175 func generateHash() string { |
408
ac23905e64b1
Improve WFS proxy a lot. It now generates signed re-writings.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
339
diff
changeset
|
176 return hex.EncodeToString(common.GenerateRandomKey(hashLength)) |
310
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
177 } |
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
178 |
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
179 func generateNewPassword() string { |
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
180 // First try pwgen |
511
b96b1b258cfa
Use already declared password length in reset password.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
501
diff
changeset
|
181 out, err := exec.Command( |
b96b1b258cfa
Use already declared password length in reset password.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
501
diff
changeset
|
182 "pwgen", "-y", strconv.Itoa(passwordLength), "1").Output() |
310
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
183 if err == nil { |
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
184 return strings.TrimSpace(string(out)) |
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
185 } |
317
5cb18bedb3a9
Simplified internal password generator.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
316
diff
changeset
|
186 // Use internal generator. |
511
b96b1b258cfa
Use already declared password length in reset password.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
501
diff
changeset
|
187 return common.RandomString(passwordLength) |
310
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
188 } |
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
189 |
3956
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
190 func backgroundRequest(host string, user *models.PWResetUser) error { |
302
0777aa6de45b
Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
191 |
0777aa6de45b
Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
192 if user.User == "" { |
535
da5f47a0941c
Password reset: Reduce the risk of timing attacks and being a user oracle when requesting resets.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
521
diff
changeset
|
193 return errInvalidUser |
302
0777aa6de45b
Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
194 } |
0777aa6de45b
Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
195 |
321
974a5e4c0055
Persist password reset requests in database.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
319
diff
changeset
|
196 var hash, email string |
974a5e4c0055
Persist password reset requests in database.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
319
diff
changeset
|
197 |
535
da5f47a0941c
Password reset: Reduce the risk of timing attacks and being a user oracle when requesting resets.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
521
diff
changeset
|
198 ctx := context.Background() |
521
139214cecc8f
backend: add FIXMEs to password reset.
Bernhard Reiter <bernhard@intevation.de>
parents:
516
diff
changeset
|
199 |
535
da5f47a0941c
Password reset: Reduce the risk of timing attacks and being a user oracle when requesting resets.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
521
diff
changeset
|
200 if err := auth.RunAs( |
1327
cabf4789e02b
To make golint happier made context.Context to be the first argument of auth.RunAs.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
1317
diff
changeset
|
201 ctx, pwResetRole, |
501
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
202 func(conn *sql.Conn) error { |
302
0777aa6de45b
Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
203 |
501
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
204 var count int64 |
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
205 if err := conn.QueryRowContext( |
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
206 ctx, countRequestsSQL).Scan(&count); err != nil { |
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
207 return err |
321
974a5e4c0055
Persist password reset requests in database.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
319
diff
changeset
|
208 } |
302
0777aa6de45b
Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
209 |
501
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
210 // Limit total number of password requests. |
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
211 if count >= maxPasswordResets { |
535
da5f47a0941c
Password reset: Reduce the risk of timing attacks and being a user oracle when requesting resets.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
521
diff
changeset
|
212 return errTooMuchPasswordResets |
501
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
213 } |
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
214 |
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
215 err := conn.QueryRowContext(ctx, userExistsSQL, user.User).Scan(&email) |
302
0777aa6de45b
Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
216 |
501
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
217 switch { |
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
218 case err == sql.ErrNoRows: |
535
da5f47a0941c
Password reset: Reduce the risk of timing attacks and being a user oracle when requesting resets.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
521
diff
changeset
|
219 return errNoSuchUser |
501
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
220 case err != nil: |
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
221 return err |
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
222 } |
304
69e291f26bbd
Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
302
diff
changeset
|
223 |
501
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
224 hash = generateHash() |
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
225 _, err = conn.ExecContext(ctx, insertRequestSQL, hash, user.User) |
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
226 return err |
535
da5f47a0941c
Password reset: Reduce the risk of timing attacks and being a user oracle when requesting resets.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
521
diff
changeset
|
227 }, |
da5f47a0941c
Password reset: Reduce the risk of timing attacks and being a user oracle when requesting resets.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
521
diff
changeset
|
228 ); err != nil { |
da5f47a0941c
Password reset: Reduce the risk of timing attacks and being a user oracle when requesting resets.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
521
diff
changeset
|
229 return err |
da5f47a0941c
Password reset: Reduce the risk of timing attacks and being a user oracle when requesting resets.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
521
diff
changeset
|
230 } |
da5f47a0941c
Password reset: Reduce the risk of timing attacks and being a user oracle when requesting resets.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
521
diff
changeset
|
231 |
3956
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
232 body := requestMessageBody(user.User, hash, host) |
535
da5f47a0941c
Password reset: Reduce the risk of timing attacks and being a user oracle when requesting resets.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
521
diff
changeset
|
233 |
da5f47a0941c
Password reset: Reduce the risk of timing attacks and being a user oracle when requesting resets.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
521
diff
changeset
|
234 return misc.SendMail(email, "Password Reset Link", body) |
da5f47a0941c
Password reset: Reduce the risk of timing attacks and being a user oracle when requesting resets.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
521
diff
changeset
|
235 } |
da5f47a0941c
Password reset: Reduce the risk of timing attacks and being a user oracle when requesting resets.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
521
diff
changeset
|
236 |
da5f47a0941c
Password reset: Reduce the risk of timing attacks and being a user oracle when requesting resets.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
521
diff
changeset
|
237 func passwordResetRequest( |
da5f47a0941c
Password reset: Reduce the risk of timing attacks and being a user oracle when requesting resets.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
521
diff
changeset
|
238 input interface{}, |
da5f47a0941c
Password reset: Reduce the risk of timing attacks and being a user oracle when requesting resets.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
521
diff
changeset
|
239 req *http.Request, |
da5f47a0941c
Password reset: Reduce the risk of timing attacks and being a user oracle when requesting resets.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
521
diff
changeset
|
240 _ *sql.Conn, |
da5f47a0941c
Password reset: Reduce the risk of timing attacks and being a user oracle when requesting resets.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
521
diff
changeset
|
241 ) (jr JSONResult, err error) { |
302
0777aa6de45b
Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
242 |
535
da5f47a0941c
Password reset: Reduce the risk of timing attacks and being a user oracle when requesting resets.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
521
diff
changeset
|
243 // We do the checks and the emailing in background |
da5f47a0941c
Password reset: Reduce the risk of timing attacks and being a user oracle when requesting resets.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
521
diff
changeset
|
244 // no reduce the risks of timing attacks. |
3956
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
245 go func(user *models.PWResetUser) { |
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
246 config.WaitReady() |
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
247 host := config.ExternalURL() |
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
248 if err := backgroundRequest(host, user); err != nil { |
535
da5f47a0941c
Password reset: Reduce the risk of timing attacks and being a user oracle when requesting resets.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
521
diff
changeset
|
249 log.Printf("error: %v\n", err) |
321
974a5e4c0055
Persist password reset requests in database.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
319
diff
changeset
|
250 } |
3956
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
251 }(input.(*models.PWResetUser)) |
535
da5f47a0941c
Password reset: Reduce the risk of timing attacks and being a user oracle when requesting resets.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
521
diff
changeset
|
252 |
da5f47a0941c
Password reset: Reduce the risk of timing attacks and being a user oracle when requesting resets.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
521
diff
changeset
|
253 // Send a neutral message to avoid being an user oracle. |
da5f47a0941c
Password reset: Reduce the risk of timing attacks and being a user oracle when requesting resets.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
521
diff
changeset
|
254 const neutralMessage = "If this account exists, a reset link will be mailed." |
da5f47a0941c
Password reset: Reduce the risk of timing attacks and being a user oracle when requesting resets.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
521
diff
changeset
|
255 |
da5f47a0941c
Password reset: Reduce the risk of timing attacks and being a user oracle when requesting resets.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
521
diff
changeset
|
256 jr.Result = &struct { |
da5f47a0941c
Password reset: Reduce the risk of timing attacks and being a user oracle when requesting resets.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
521
diff
changeset
|
257 Message string `json:"message"` |
da5f47a0941c
Password reset: Reduce the risk of timing attacks and being a user oracle when requesting resets.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
521
diff
changeset
|
258 }{neutralMessage} |
da5f47a0941c
Password reset: Reduce the risk of timing attacks and being a user oracle when requesting resets.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
521
diff
changeset
|
259 |
302
0777aa6de45b
Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
260 return |
0777aa6de45b
Password reset. Part I
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
261 } |
304
69e291f26bbd
Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
302
diff
changeset
|
262 |
3721
ed4820efb7e6
Password reset: Send redirect to server starting page when reset succeeded.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
1327
diff
changeset
|
263 func passwordReset(rw http.ResponseWriter, req *http.Request) { |
304
69e291f26bbd
Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
302
diff
changeset
|
264 |
69e291f26bbd
Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
302
diff
changeset
|
265 hash := mux.Vars(req)["hash"] |
3721
ed4820efb7e6
Password reset: Send redirect to server starting page when reset succeeded.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
1327
diff
changeset
|
266 if _, err := hex.DecodeString(hash); err != nil { |
ed4820efb7e6
Password reset: Send redirect to server starting page when reset succeeded.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
1327
diff
changeset
|
267 http.Error(rw, "invalid hash", http.StatusBadRequest) |
304
69e291f26bbd
Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
302
diff
changeset
|
268 return |
69e291f26bbd
Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
302
diff
changeset
|
269 } |
69e291f26bbd
Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
302
diff
changeset
|
270 |
3956
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
271 var user, password string |
310
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
272 |
501
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
273 ctx := req.Context() |
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
274 |
3956
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
275 err := auth.RunAs( |
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
276 ctx, pwResetRole, |
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
277 func(conn *sql.Conn) error { |
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
278 tx, err := conn.BeginTx(ctx, nil) |
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
279 if err != nil { |
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
280 return err |
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
281 } |
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
282 defer tx.Rollback() |
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
283 |
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
284 err = tx.QueryRowContext(ctx, findRequestSQL, hash).Scan(&user) |
501
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
285 switch { |
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
286 case err == sql.ErrNoRows: |
3956
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
287 return errors.New("No such hash") |
501
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
288 case err != nil: |
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
289 return err |
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
290 } |
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
291 password = generateNewPassword() |
3956
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
292 res, err := tx.ExecContext(ctx, updatePasswordSQL, password, user) |
501
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
293 if err != nil { |
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
294 return err |
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
295 } |
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
296 if n, err2 := res.RowsAffected(); err2 == nil && n == 0 { |
3956
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
297 return errors.New("User not found") |
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
298 } |
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
299 if _, err = tx.ExecContext(ctx, deleteRequestSQL, hash); err != nil { |
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
300 return err |
501
c10c76c92797
Use metamorphic database connections for auth.RunAs().
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
301 } |
3956
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
302 return tx.Commit() |
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
303 }, |
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
304 ) |
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
305 |
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
306 switch { |
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
307 case err == sql.ErrNoRows: |
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
308 http.Error(rw, "No such request", http.StatusNotFound) |
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
309 return |
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
310 case err != nil: |
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
311 http.Error(rw, "Error: "+err.Error(), http.StatusInternalServerError) |
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
312 return |
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
313 } |
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
314 |
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
315 if err := changedMessageBody(rw, user, password); err != nil { |
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
316 log.Printf("error: %v\n", err) |
310
4bee4ba6dc58
Password reset: Part III
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
304
diff
changeset
|
317 } |
304
69e291f26bbd
Password reset: Part II.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
302
diff
changeset
|
318 } |
3956
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
319 |
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
320 func deletePasswordResetRequest(user string) { |
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
321 ctx := context.Background() |
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
322 if err := auth.RunAs( |
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
323 ctx, |
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
324 pwResetRole, |
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
325 func(conn *sql.Conn) error { |
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
326 _, err := conn.ExecContext(ctx, deletePasswordResetRequestSQL, user) |
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
327 return err |
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
328 }, |
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
329 ); err != nil { |
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
330 log.Printf("error: %v\n", err) |
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
331 } |
4f9a1ff2c2ee
Reworked password reset to be single mailed.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
3721
diff
changeset
|
332 } |