diff --git a/cmd/budgeteer/main.go b/cmd/budgeteer/main.go index af132b3..71b6eb1 100644 --- a/cmd/budgeteer/main.go +++ b/cmd/budgeteer/main.go @@ -1,6 +1,7 @@ package main import ( + "fmt" "io/fs" "log" "net/http" @@ -29,11 +30,14 @@ func main() { panic("couldn't open static files") } + tokenVerifier, err := jwt.NewTokenVerifier(cfg.SessionSecret) + if err != nil { + panic(fmt.Errorf("couldn't create token verifier: %w", err)) + } + handler := &server.Handler{ - Service: queries, - TokenVerifier: &jwt.TokenVerifier{ - Secret: cfg.SessionSecret, - }, + Service: queries, + TokenVerifier: tokenVerifier, CredentialsVerifier: &bcrypt.Verifier{}, StaticFS: http.FS(static), } diff --git a/jwt/login.go b/jwt/login.go index bbb44c8..190ebd7 100644 --- a/jwt/login.go +++ b/jwt/login.go @@ -12,7 +12,19 @@ import ( // TokenVerifier verifies Tokens. type TokenVerifier struct { - Secret string + secret string +} + +var ErrEmptySecret = fmt.Errorf("secret is required") + +func NewTokenVerifier(secret string) (*TokenVerifier, error) { + if secret == "" { + return nil, ErrEmptySecret + } + + return &TokenVerifier{ + secret: secret, + }, nil } // Token contains everything to authenticate a user. @@ -29,6 +41,10 @@ const ( // CreateToken creates a new token from username and name. func (tv *TokenVerifier) CreateToken(user *postgres.User) (string, error) { + if tv.secret == "" { + return "", ErrEmptySecret + } + token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{ "usr": user.Email, "name": user.Name, @@ -37,7 +53,7 @@ func (tv *TokenVerifier) CreateToken(user *postgres.User) (string, error) { }) // Generate encoded token and send it as response. - t, err := token.SignedString([]byte(tv.Secret)) + t, err := token.SignedString([]byte(tv.secret)) if err != nil { return "", fmt.Errorf("create token: %w", err) } @@ -53,11 +69,15 @@ var ( // VerifyToken verifys a given string-token. func (tv *TokenVerifier) VerifyToken(tokenString string) (budgeteer.Token, error) { //nolint:ireturn + if tv.secret == "" { + return nil, ErrEmptySecret + } + token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) { if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok { return nil, fmt.Errorf("method '%v': %w", token.Header["alg"], ErrUnexpectedSigningMethod) } - return []byte(tv.Secret), nil + return []byte(tv.secret), nil }) if err != nil { return nil, fmt.Errorf("parse jwt: %w", err) diff --git a/server/account_test.go b/server/account_test.go index 1af33c1..061b1bd 100644 --- a/server/account_test.go +++ b/server/account_test.go @@ -28,11 +28,10 @@ func TestRegisterUser(t *testing.T) { //nolint:funlen return } + tokenVerifier, _ := jwt.NewTokenVerifier("this_is_my_demo_secret_for_unit_tests") h := Handler{ - Service: database, - TokenVerifier: &jwt.TokenVerifier{ - Secret: "this_is_my_demo_secret_for_unit_tests", - }, + Service: database, + TokenVerifier: tokenVerifier, CredentialsVerifier: &bcrypt.Verifier{}, } diff --git a/web/src/components/Button.vue b/web/src/components/Button.vue index c7c16a0..9491068 100644 --- a/web/src/components/Button.vue +++ b/web/src/components/Button.vue @@ -3,7 +3,7 @@