forked from hailey.at/cocoon
An atproto PDS written in Go

implement 2fa on creating a session

Signed-off-by: Will Andrews <did:plc:dadhhalkfcq3gucaq25hjqon>

Changed files
+35
server
+35
server/handle_server_create_session.go
··· 2 2 3 3 import ( 4 4 "errors" 5 + "fmt" 5 6 "strings" 7 + "time" 6 8 7 9 "github.com/Azure/go-autorest/autorest/to" 8 10 "github.com/bluesky-social/indigo/atproto/syntax" ··· 81 83 82 84 s.logger.Error("erorr looking up repo", "endpoint", "com.atproto.server.createSession", "error", err) 83 85 return helpers.ServerError(e, nil) 86 + } 87 + 88 + // if repo requires auth factor token and one hasn't been provided, return error prompting for one 89 + if repo.EmailAuthFactor && (req.AuthFactorToken == nil || *req.AuthFactorToken == "") { 90 + code := fmt.Sprintf("%s-%s", helpers.RandomVarchar(5), helpers.RandomVarchar(5)) 91 + eat := time.Now().Add(10 * time.Minute).UTC() 92 + 93 + if err := s.db.Exec(ctx, "UPDATE repos SET email_update_code = ?, email_update_code_expires_at = ? WHERE did = ?", nil, code, eat, repo.Repo.Did).Error; err != nil { 94 + s.logger.Error("error updating repo", "error", err) 95 + return helpers.ServerError(e, nil) 96 + } 97 + 98 + if err := s.sendEmailUpdate(repo.Email, repo.Handle, code); err != nil { 99 + s.logger.Error("error sending email", "error", err) 100 + return helpers.ServerError(e, nil) 101 + } 102 + 103 + return helpers.InputError(e, to.StringPtr("AuthFactorTokenRequired")) 104 + } 105 + 106 + // if auth factor is required, now check that the one provided is valid 107 + if repo.EmailAuthFactor { 108 + if repo.EmailUpdateCode == nil || repo.EmailUpdateCodeExpiresAt == nil { 109 + return helpers.InvalidTokenError(e) 110 + } 111 + 112 + if *repo.EmailUpdateCode != *req.AuthFactorToken { 113 + return helpers.InvalidTokenError(e) 114 + } 115 + 116 + if time.Now().UTC().After(*repo.EmailUpdateCodeExpiresAt) { 117 + return helpers.ExpiredTokenError(e) 118 + } 84 119 } 85 120 86 121 if err := bcrypt.CompareHashAndPassword([]byte(repo.Password), []byte(req.Password)); err != nil {