Skip to content

Commit d4623ac

Browse files
committed
Add two-factor auth
1 parent 8d6221e commit d4623ac

File tree

2 files changed

+67
-7
lines changed

2 files changed

+67
-7
lines changed

blog.go

+33-1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ import (
2323
"github.com/volatiletech/authboss/lock"
2424
_ "github.com/volatiletech/authboss/logout"
2525
aboauth "github.com/volatiletech/authboss/oauth2"
26+
"github.com/volatiletech/authboss/otp/twofactor"
27+
"github.com/volatiletech/authboss/otp/twofactor/sms2fa"
28+
"github.com/volatiletech/authboss/otp/twofactor/totp2fa"
2629
_ "github.com/volatiletech/authboss/recover"
2730
_ "github.com/volatiletech/authboss/register"
2831
"github.com/volatiletech/authboss/remember"
@@ -104,6 +107,10 @@ func setupAuthboss() {
104107
// to type them again)
105108
ab.Config.Modules.RegisterPreserveFields = []string{"email", "name"}
106109

110+
// TOTP2FAIssuer is the name of the issuer we use for totp 2fa
111+
ab.Config.Modules.TOTP2FAIssuer = "ABBlog"
112+
ab.Config.Modules.TwoFactorRedirectOnUnauthed = true
113+
107114
// This instantiates and uses every default implementation
108115
// in the Config.Core area that exist in the defaults package.
109116
// Just a convenient helper if you don't want to do anything fancy.
@@ -148,6 +155,22 @@ func setupAuthboss() {
148155
ClientSecret string `toml:"client_secret"`
149156
}{}
150157

158+
// Set up 2fa
159+
twofaRecovery := &twofactor.Recovery{Authboss: ab}
160+
if err := twofaRecovery.Setup(); err != nil {
161+
panic(err)
162+
}
163+
164+
totp := &totp2fa.TOTP{Authboss: ab}
165+
if err := totp.Setup(); err != nil {
166+
panic(err)
167+
}
168+
169+
sms := &sms2fa.SMS{Authboss: ab, Sender: smsLogSender{}}
170+
if err := sms.Setup(); err != nil {
171+
panic(err)
172+
}
173+
151174
// Set up Google OAuth2 if we have credentials in the
152175
// file oauth2.toml for it.
153176
_, err := toml.DecodeFile("oauth2.toml", &oauthcreds)
@@ -225,7 +248,7 @@ func main() {
225248

226249
// Authed routes
227250
mux.Group(func(mux chi.Router) {
228-
mux.Use(authboss.Middleware(ab, true, false), lock.Middleware(ab), confirm.Middleware(ab))
251+
mux.Use(authboss.Middleware(ab, true, false, true), lock.Middleware(ab), confirm.Middleware(ab))
229252
mux.MethodFunc("GET", "/blogs/new", newblog)
230253
mux.MethodFunc("GET", "/blogs/{id}/edit", edit)
231254
mux.MethodFunc("POST", "/blogs/{id}/edit", update)
@@ -503,3 +526,12 @@ func badRequest(w http.ResponseWriter, err error) bool {
503526
fmt.Fprintln(w, "Bad request:", err)
504527
return true
505528
}
529+
530+
type smsLogSender struct {
531+
}
532+
533+
// Send an SMS
534+
func (s smsLogSender) Send(number, text string) error {
535+
fmt.Println("sms sent to:", number, "contents:", text)
536+
return nil
537+
}

storer.go

+34-6
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import (
88
"github.com/pkg/errors"
99
"github.com/volatiletech/authboss"
1010
aboauth "github.com/volatiletech/authboss/oauth2"
11+
"github.com/volatiletech/authboss/otp/twofactor/sms2fa"
12+
"github.com/volatiletech/authboss/otp/twofactor/totp2fa"
1113
)
1214

1315
var nextUserID int
@@ -45,6 +47,11 @@ type User struct {
4547
OAuth2RefreshToken string
4648
OAuth2Expiry time.Time
4749

50+
// 2fa
51+
TOTPSecretKey string
52+
SMSPhoneNumber string
53+
RecoveryCodes string
54+
4855
// Remember is in another table
4956
}
5057

@@ -61,6 +68,9 @@ var (
6168
_ authboss.RecoverableUser = assertUser
6269
_ authboss.ArbitraryUser = assertUser
6370

71+
_ totp2fa.User = assertUser
72+
_ sms2fa.User = assertUser
73+
6474
_ authboss.CreatingServerStorer = assertStorer
6575
_ authboss.ConfirmingServerStorer = assertStorer
6676
_ authboss.RecoveringServerStorer = assertStorer
@@ -103,6 +113,15 @@ func (u *User) PutRecoverVerifier(token string) { u.RecoverVerifier = token }
103113
// PutRecoverExpiry into user
104114
func (u *User) PutRecoverExpiry(expiry time.Time) { u.RecoverTokenExpiry = expiry }
105115

116+
// PutTOTPSecretKey into user
117+
func (u *User) PutTOTPSecretKey(key string) { u.TOTPSecretKey = key }
118+
119+
// PutSMSPhoneNumber into user
120+
func (u *User) PutSMSPhoneNumber(key string) { u.SMSPhoneNumber = key }
121+
122+
// PutRecoveryCodes into user
123+
func (u *User) PutRecoveryCodes(key string) { u.RecoveryCodes = key }
124+
106125
// PutOAuth2UID into user
107126
func (u *User) PutOAuth2UID(uid string) { u.OAuth2UID = uid }
108127

@@ -161,12 +180,14 @@ func (u User) GetRecoverVerifier() string { return u.RecoverVerifier }
161180
// GetRecoverExpiry from user
162181
func (u User) GetRecoverExpiry() time.Time { return u.RecoverTokenExpiry }
163182

164-
// GetArbitrary from user
165-
func (u User) GetArbitrary() map[string]string {
166-
return map[string]string{
167-
"name": u.Name,
168-
}
169-
}
183+
// GetTOTPSecretKey from user
184+
func (u User) GetTOTPSecretKey() string { return u.TOTPSecretKey }
185+
186+
// GetSMSPhoneNumber from user
187+
func (u User) GetSMSPhoneNumber() string { return u.SMSPhoneNumber }
188+
189+
// GetRecoveryCodes from user
190+
func (u User) GetRecoveryCodes() string { return u.RecoveryCodes }
170191

171192
// IsOAuth2User returns true if the user was created with oauth2
172193
func (u User) IsOAuth2User() bool { return len(u.OAuth2UID) != 0 }
@@ -186,6 +207,13 @@ func (u User) GetOAuth2RefreshToken() (refreshToken string) { return u.OAuth2Ref
186207
// GetOAuth2Expiry from user
187208
func (u User) GetOAuth2Expiry() (expiry time.Time) { return u.OAuth2Expiry }
188209

210+
// GetArbitrary from user
211+
func (u User) GetArbitrary() map[string]string {
212+
return map[string]string{
213+
"name": u.Name,
214+
}
215+
}
216+
189217
// MemStorer stores users in memory
190218
type MemStorer struct {
191219
Users map[string]User

0 commit comments

Comments
 (0)