aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--pkg/ext/auth.go72
-rw-r--r--pkg/ext/auth_test.go40
-rw-r--r--pkg/ext/middleware.go9
-rw-r--r--pkg/service/auth.go73
-rw-r--r--pkg/service/auth_test.go33
5 files changed, 107 insertions, 120 deletions
diff --git a/pkg/ext/auth.go b/pkg/ext/auth.go
deleted file mode 100644
index ed122bb..0000000
--- a/pkg/ext/auth.go
+++ /dev/null
@@ -1,72 +0,0 @@
-package ext
-
-import (
- "bytes"
- "crypto/aes"
- "crypto/cipher"
- "crypto/rand"
- "encoding/gob"
- "errors"
- "io"
-)
-
-type Token struct {
- UserID uint
- Username string
-}
-
-func ReadToken(data []byte, key []byte) (*Token, error) {
- block, err := aes.NewCipher(key)
- if err != nil {
- return nil, err
- }
-
- aesgcm, err := cipher.NewGCM(block)
- if err != nil {
- panic(err.Error())
- }
-
- nonceSize := aesgcm.NonceSize()
- if len(data) < nonceSize {
- return nil, errors.New("nonce size greater than data's size")
- }
-
- nonce, ciphertext := data[:nonceSize], data[nonceSize:]
- plaintext, err := aesgcm.Open(nil, nonce, ciphertext, nil)
- if err != nil {
- return nil, err
- }
-
- r := bytes.NewReader(plaintext)
- var token Token
- dec := gob.NewDecoder(r)
- if err = dec.Decode(&token); err != nil {
- return nil, err
- }
- return &token, nil
-}
-
-func WriteToken(token *Token, key []byte) ([]byte, error) {
- block, err := aes.NewCipher(key)
- if err != nil {
- return nil, err
- }
-
- aesgcm, err := cipher.NewGCM(block)
- if err != nil {
- return nil, err
- }
-
- var buffer bytes.Buffer
- enc := gob.NewEncoder(&buffer)
- if err := enc.Encode(token); err != nil {
- return nil, err
- }
- nonce := make([]byte, aesgcm.NonceSize())
- if _, err = io.ReadFull(rand.Reader, nonce); err != nil {
- return nil, err
- }
-
- ciphertext := aesgcm.Seal(nonce, nonce, buffer.Bytes(), nil)
- return ciphertext, nil
-}
diff --git a/pkg/ext/auth_test.go b/pkg/ext/auth_test.go
deleted file mode 100644
index dc72a0c..0000000
--- a/pkg/ext/auth_test.go
+++ /dev/null
@@ -1,40 +0,0 @@
-//go:build unit
-
-package ext
-
-import (
- "testing"
-
- "git.sr.ht/~gabrielgio/img/pkg/testkit"
-)
-
-func TestReadWriteToken(t *testing.T) {
- t.Parallel()
-
- testCases := []struct {
- name string
- key []byte
- token *Token
- }{
- {
- name: "Normal write",
- key: []byte("AES256Key-32Characters1234567890"),
- token: &Token{
- UserID: 3,
- Username: "username",
- },
- },
- }
-
- for _, tc := range testCases {
- t.Run(tc.name, func(t *testing.T) {
- data, err := WriteToken(tc.token, tc.key)
- testkit.TestFatalError(t, "WriteToken", err)
-
- token, err := ReadToken(data, tc.key)
- testkit.TestFatalError(t, "ReadToken", err)
-
- testkit.TestValue(t, "ReadWriteToken", token, tc.token)
- })
- }
-}
diff --git a/pkg/ext/middleware.go b/pkg/ext/middleware.go
index 2dd1cca..bcc6c5f 100644
--- a/pkg/ext/middleware.go
+++ b/pkg/ext/middleware.go
@@ -8,6 +8,7 @@ import (
"github.com/valyala/fasthttp"
"git.sr.ht/~gabrielgio/img/pkg/database/repository"
+ "git.sr.ht/~gabrielgio/img/pkg/service"
)
func HTML(next fasthttp.RequestHandler) fasthttp.RequestHandler {
@@ -77,7 +78,7 @@ func (a *AuthMiddleware) LoggedIn(next fasthttp.RequestHandler) fasthttp.Request
return
}
- token, err := ReadToken(auth, a.key)
+ token, err := service.ReadToken(auth, a.key)
if err != nil {
a.entry.Error(err)
ctx.Redirect(redirectLogin, 307)
@@ -92,9 +93,9 @@ func (a *AuthMiddleware) LoggedIn(next fasthttp.RequestHandler) fasthttp.Request
}
}
-func GetTokenFromCtx(ctx *fasthttp.RequestCtx) *Token {
+func GetTokenFromCtx(ctx *fasthttp.RequestCtx) *service.Token {
tokenValue := ctx.UserValue("token")
- if token, ok := tokenValue.(*Token); ok {
+ if token, ok := tokenValue.(*service.Token); ok {
return token
}
return nil
@@ -113,7 +114,7 @@ func NewInitialSetupMiddleware(userRepository repository.UserRepository) *Initia
func (i *InitialSetupMiddleware) Check(next fasthttp.RequestHandler) fasthttp.RequestHandler {
return func(ctx *fasthttp.RequestCtx) {
// if user has been set to context it is logged in already
- _, ok := ctx.UserValue("token").(*Token)
+ _, ok := ctx.UserValue("token").(*service.Token)
if ok {
next(ctx)
return
diff --git a/pkg/service/auth.go b/pkg/service/auth.go
index 761c70b..1966e70 100644
--- a/pkg/service/auth.go
+++ b/pkg/service/auth.go
@@ -1,12 +1,18 @@
package service
import (
+ "bytes"
"context"
+ "crypto/aes"
+ "crypto/cipher"
+ "crypto/rand"
+ "encoding/gob"
+ "errors"
+ "io"
"golang.org/x/crypto/bcrypt"
"git.sr.ht/~gabrielgio/img/pkg/database/repository"
- "git.sr.ht/~gabrielgio/img/pkg/ext"
)
type AuthController struct {
@@ -42,11 +48,11 @@ func (c *AuthController) Login(ctx context.Context, username, password []byte) (
return nil, err
}
- token := &ext.Token{
+ token := &Token{
UserID: id,
Username: string(username),
}
- return ext.WriteToken(token, c.key)
+ return WriteToken(token, c.key)
}
// InitialRegister register a initial user, it will validate if there is another
@@ -75,3 +81,64 @@ func (c *AuthController) InitialRegister(ctx context.Context, username, password
return err
}
+
+type Token struct {
+ UserID uint
+ Username string
+}
+
+func ReadToken(data []byte, key []byte) (*Token, error) {
+ block, err := aes.NewCipher(key)
+ if err != nil {
+ return nil, err
+ }
+
+ aesgcm, err := cipher.NewGCM(block)
+ if err != nil {
+ panic(err.Error())
+ }
+
+ nonceSize := aesgcm.NonceSize()
+ if len(data) < nonceSize {
+ return nil, errors.New("nonce size greater than data's size")
+ }
+
+ nonce, ciphertext := data[:nonceSize], data[nonceSize:]
+ plaintext, err := aesgcm.Open(nil, nonce, ciphertext, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ r := bytes.NewReader(plaintext)
+ var token Token
+ dec := gob.NewDecoder(r)
+ if err = dec.Decode(&token); err != nil {
+ return nil, err
+ }
+ return &token, nil
+}
+
+func WriteToken(token *Token, key []byte) ([]byte, error) {
+ block, err := aes.NewCipher(key)
+ if err != nil {
+ return nil, err
+ }
+
+ aesgcm, err := cipher.NewGCM(block)
+ if err != nil {
+ return nil, err
+ }
+
+ var buffer bytes.Buffer
+ enc := gob.NewEncoder(&buffer)
+ if err := enc.Encode(token); err != nil {
+ return nil, err
+ }
+ nonce := make([]byte, aesgcm.NonceSize())
+ if _, err = io.ReadFull(rand.Reader, nonce); err != nil {
+ return nil, err
+ }
+
+ ciphertext := aesgcm.Seal(nonce, nonce, buffer.Bytes(), nil)
+ return ciphertext, nil
+}
diff --git a/pkg/service/auth_test.go b/pkg/service/auth_test.go
index 35b2475..7083d0c 100644
--- a/pkg/service/auth_test.go
+++ b/pkg/service/auth_test.go
@@ -64,7 +64,7 @@ func TestInitialRegisterAndLogin(t *testing.T) {
auth, err := scene.controller.Login(scene.ctx, []byte(tc.username), tc.password)
testkit.TestFatalError(t, "Login", err)
- token, err := ext.ReadToken(auth, key)
+ token, err := ReadToken(auth, key)
testkit.TestFatalError(t, "Login", err)
testkit.TestValue(t, "Login", tc.username, token.Username)
@@ -76,3 +76,34 @@ func TestInitialRegisterAndLogin(t *testing.T) {
func remove[T any](slice []T, s int) []T {
return append(slice[:s], slice[s+1:]...)
}
+
+func TestReadWriteToken(t *testing.T) {
+ t.Parallel()
+
+ testCases := []struct {
+ name string
+ key []byte
+ token *Token
+ }{
+ {
+ name: "Normal write",
+ key: []byte("AES256Key-32Characters1234567890"),
+ token: &Token{
+ UserID: 3,
+ Username: "username",
+ },
+ },
+ }
+
+ for _, tc := range testCases {
+ t.Run(tc.name, func(t *testing.T) {
+ data, err := WriteToken(tc.token, tc.key)
+ testkit.TestFatalError(t, "WriteToken", err)
+
+ token, err := ReadToken(data, tc.key)
+ testkit.TestFatalError(t, "ReadToken", err)
+
+ testkit.TestValue(t, "ReadWriteToken", token, tc.token)
+ })
+ }
+}