diff options
| author | Gabriel Arakaki Giovanini <mail@gabrielgio.me> | 2023-07-19 21:01:23 +0200 | 
|---|---|---|
| committer | Gabriel Arakaki Giovanini <mail@gabrielgio.me> | 2023-07-19 21:01:23 +0200 | 
| commit | fbcac585cf626917e2baf1d0065c7b632341ba01 (patch) | |
| tree | 82a0ca1812f92500588c0503cc80b23cffd159e8 /pkg | |
| parent | 52276ba99540d6c61195772ccdd50944e96f4959 (diff) | |
| download | lens-fbcac585cf626917e2baf1d0065c7b632341ba01.tar.gz lens-fbcac585cf626917e2baf1d0065c7b632341ba01.tar.bz2 lens-fbcac585cf626917e2baf1d0065c7b632341ba01.zip | |
ref: Move auth functions to service
Diffstat (limited to 'pkg')
| -rw-r--r-- | pkg/ext/auth.go | 72 | ||||
| -rw-r--r-- | pkg/ext/auth_test.go | 40 | ||||
| -rw-r--r-- | pkg/ext/middleware.go | 9 | ||||
| -rw-r--r-- | pkg/service/auth.go | 73 | ||||
| -rw-r--r-- | pkg/service/auth_test.go | 33 | 
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) +		}) +	} +} | 
