+13
internal/helpers/helpers.go
+13
internal/helpers/helpers.go
···
7
"math/rand"
8
"net/url"
9
10
+
"github.com/Azure/go-autorest/autorest/to"
11
"github.com/labstack/echo/v4"
12
"github.com/lestrrat-go/jwx/v2/jwk"
13
)
···
30
msg += ". " + *suffix
31
}
32
return genericError(e, 400, msg)
33
+
}
34
+
35
+
func InvalidTokenError(e echo.Context) error {
36
+
return InputError(e, to.StringPtr("InvalidToken"))
37
+
}
38
+
39
+
func ExpiredTokenError(e echo.Context) error {
40
+
// WARN: See https://github.com/bluesky-social/atproto/discussions/3319
41
+
return e.JSON(400, map[string]string{
42
+
"error": "ExpiredToken",
43
+
"message": "*",
44
+
})
45
}
46
47
func genericError(e echo.Context, code int, msg string) error {
+2
-2
server/handle_server_confirm_email.go
+2
-2
server/handle_server_confirm_email.go
···
28
}
29
30
if urepo.EmailVerificationCode == nil || urepo.EmailVerificationCodeExpiresAt == nil {
31
-
return helpers.InputError(e, to.StringPtr("ExpiredToken"))
32
}
33
34
if *urepo.EmailVerificationCode != req.Token {
···
36
}
37
38
if time.Now().UTC().After(*urepo.EmailVerificationCodeExpiresAt) {
39
-
return helpers.InputError(e, to.StringPtr("ExpiredToken"))
40
}
41
42
now := time.Now().UTC()
···
28
}
29
30
if urepo.EmailVerificationCode == nil || urepo.EmailVerificationCodeExpiresAt == nil {
31
+
return helpers.ExpiredTokenError(e)
32
}
33
34
if *urepo.EmailVerificationCode != req.Token {
···
36
}
37
38
if time.Now().UTC().After(*urepo.EmailVerificationCodeExpiresAt) {
39
+
return helpers.ExpiredTokenError(e)
40
}
41
42
now := time.Now().UTC()
+2
-2
server/handle_server_reset_password.go
+2
-2
server/handle_server_reset_password.go
···
33
}
34
35
if *urepo.PasswordResetCode != req.Token {
36
-
return helpers.InputError(e, to.StringPtr("InvalidToken"))
37
}
38
39
if time.Now().UTC().After(*urepo.PasswordResetCodeExpiresAt) {
40
-
return helpers.InputError(e, to.StringPtr("ExpiredToken"))
41
}
42
43
hash, err := bcrypt.GenerateFromPassword([]byte(req.Password), 10)
+3
-4
server/handle_server_update_email.go
+3
-4
server/handle_server_update_email.go
···
3
import (
4
"time"
5
6
-
"github.com/Azure/go-autorest/autorest/to"
7
"github.com/haileyok/cocoon/internal/helpers"
8
"github.com/haileyok/cocoon/models"
9
"github.com/labstack/echo/v4"
···
29
}
30
31
if urepo.EmailUpdateCode == nil || urepo.EmailUpdateCodeExpiresAt == nil {
32
-
return helpers.InputError(e, to.StringPtr("InvalidToken"))
33
}
34
35
if *urepo.EmailUpdateCode != req.Token {
36
-
return helpers.InputError(e, to.StringPtr("InvalidToken"))
37
}
38
39
if time.Now().UTC().After(*urepo.EmailUpdateCodeExpiresAt) {
40
-
return helpers.InputError(e, to.StringPtr("ExpiredToken"))
41
}
42
43
if err := s.db.Exec("UPDATE repos SET email_update_code = NULL, email_update_code_expires_at = NULL, email_confirmed_at = NULL, email = ? WHERE did = ?", nil, req.Email, urepo.Repo.Did).Error; err != nil {
···
3
import (
4
"time"
5
6
"github.com/haileyok/cocoon/internal/helpers"
7
"github.com/haileyok/cocoon/models"
8
"github.com/labstack/echo/v4"
···
28
}
29
30
if urepo.EmailUpdateCode == nil || urepo.EmailUpdateCodeExpiresAt == nil {
31
+
return helpers.InvalidTokenError(e)
32
}
33
34
if *urepo.EmailUpdateCode != req.Token {
35
+
return helpers.InvalidTokenError(e)
36
}
37
38
if time.Now().UTC().After(*urepo.EmailUpdateCodeExpiresAt) {
39
+
return helpers.ExpiredTokenError(e)
40
}
41
42
if err := s.db.Exec("UPDATE repos SET email_update_code = NULL, email_update_code_expires_at = NULL, email_confirmed_at = NULL, email = ? WHERE did = ?", nil, req.Email, urepo.Repo.Did).Error; err != nil {
+11
-12
server/middleware.go
+11
-12
server/middleware.go
···
54
token, _, err := new(jwt.Parser).ParseUnverified(tokenstr, jwt.MapClaims{})
55
claims, ok := token.Claims.(jwt.MapClaims)
56
if !ok {
57
-
return helpers.InputError(e, to.StringPtr("InvalidToken"))
58
}
59
60
var did string
···
93
})
94
if err != nil {
95
s.logger.Error("error parsing jwt", "error", err)
96
-
// NOTE: https://github.com/bluesky-social/atproto/discussions/3319
97
-
return e.JSON(400, map[string]string{"error": "ExpiredToken", "message": "token has expired"})
98
}
99
100
if !token.Valid {
101
-
return helpers.InputError(e, to.StringPtr("InvalidToken"))
102
}
103
} else {
104
kpts := strings.Split(tokenstr, ".")
···
143
scope, _ := claims["scope"].(string)
144
145
if isRefresh && scope != "com.atproto.refresh" {
146
-
return helpers.InputError(e, to.StringPtr("InvalidToken"))
147
} else if !hasLxm && !isRefresh && scope != "com.atproto.access" {
148
-
return helpers.InputError(e, to.StringPtr("InvalidToken"))
149
}
150
151
table := "tokens"
···
160
var result Result
161
if err := s.db.Raw("SELECT EXISTS(SELECT 1 FROM "+table+" WHERE token = ?) AS found", nil, tokenstr).Scan(&result).Error; err != nil {
162
if err == gorm.ErrRecordNotFound {
163
-
return helpers.InputError(e, to.StringPtr("InvalidToken"))
164
}
165
166
s.logger.Error("error getting token from db", "error", err)
···
168
}
169
170
if !result.Found {
171
-
return helpers.InputError(e, to.StringPtr("InvalidToken"))
172
}
173
}
174
···
179
}
180
181
if exp < float64(time.Now().UTC().Unix()) {
182
-
return helpers.InputError(e, to.StringPtr("ExpiredToken"))
183
}
184
185
if repo == nil {
···
197
e.Set("token", tokenstr)
198
199
if err := next(e); err != nil {
200
-
e.Error(err)
201
}
202
203
return nil
···
241
}
242
243
if oauthToken.Token == "" {
244
-
return helpers.InputError(e, to.StringPtr("InvalidToken"))
245
}
246
247
if *oauthToken.Parameters.DpopJkt != proof.JKT {
···
250
}
251
252
if time.Now().After(oauthToken.ExpiresAt) {
253
-
return e.JSON(400, map[string]string{"error": "ExpiredToken", "message": "token has expired"})
254
}
255
256
repo, err := s.getRepoActorByDid(oauthToken.Sub)
···
54
token, _, err := new(jwt.Parser).ParseUnverified(tokenstr, jwt.MapClaims{})
55
claims, ok := token.Claims.(jwt.MapClaims)
56
if !ok {
57
+
return helpers.InvalidTokenError(e)
58
}
59
60
var did string
···
93
})
94
if err != nil {
95
s.logger.Error("error parsing jwt", "error", err)
96
+
return helpers.ExpiredTokenError(e)
97
}
98
99
if !token.Valid {
100
+
return helpers.InvalidTokenError(e)
101
}
102
} else {
103
kpts := strings.Split(tokenstr, ".")
···
142
scope, _ := claims["scope"].(string)
143
144
if isRefresh && scope != "com.atproto.refresh" {
145
+
return helpers.InvalidTokenError(e)
146
} else if !hasLxm && !isRefresh && scope != "com.atproto.access" {
147
+
return helpers.InvalidTokenError(e)
148
}
149
150
table := "tokens"
···
159
var result Result
160
if err := s.db.Raw("SELECT EXISTS(SELECT 1 FROM "+table+" WHERE token = ?) AS found", nil, tokenstr).Scan(&result).Error; err != nil {
161
if err == gorm.ErrRecordNotFound {
162
+
return helpers.InvalidTokenError(e)
163
}
164
165
s.logger.Error("error getting token from db", "error", err)
···
167
}
168
169
if !result.Found {
170
+
return helpers.InvalidTokenError(e)
171
}
172
}
173
···
178
}
179
180
if exp < float64(time.Now().UTC().Unix()) {
181
+
return helpers.ExpiredTokenError(e)
182
}
183
184
if repo == nil {
···
196
e.Set("token", tokenstr)
197
198
if err := next(e); err != nil {
199
+
return helpers.InvalidTokenError(e)
200
}
201
202
return nil
···
240
}
241
242
if oauthToken.Token == "" {
243
+
return helpers.InvalidTokenError(e)
244
}
245
246
if *oauthToken.Parameters.DpopJkt != proof.JKT {
···
249
}
250
251
if time.Now().After(oauthToken.ExpiresAt) {
252
+
return helpers.ExpiredTokenError(e)
253
}
254
255
repo, err := s.getRepoActorByDid(oauthToken.Sub)