feat: Added basic user authorization
This commit is contained in:
3
modules/auth/auth.go
Normal file
3
modules/auth/auth.go
Normal file
@@ -0,0 +1,3 @@
|
||||
package auth
|
||||
|
||||
const BCRYPT_COST = 13
|
||||
36
modules/auth/plain.go
Normal file
36
modules/auth/plain.go
Normal file
@@ -0,0 +1,36 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"git.ostiwe.com/ostiwe-com/status/modules/jwt"
|
||||
"git.ostiwe.com/ostiwe-com/status/repository"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
)
|
||||
|
||||
type Module struct {
|
||||
userRepository repository.User
|
||||
}
|
||||
|
||||
func New() Module {
|
||||
return Module{
|
||||
userRepository: repository.NewUserRepository(),
|
||||
}
|
||||
}
|
||||
|
||||
func (m *Module) Proceed(login, password string) (*string, error) {
|
||||
lightweightUser, err := m.userRepository.FindByLogin(login)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = bcrypt.CompareHashAndPassword([]byte(lightweightUser.Password), []byte(password))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
jwtString, err := jwt.CreateByUser(lightweightUser)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &jwtString, nil
|
||||
}
|
||||
38
modules/jwt/claims.go
Normal file
38
modules/jwt/claims.go
Normal file
@@ -0,0 +1,38 @@
|
||||
package jwt
|
||||
|
||||
import (
|
||||
"os"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
)
|
||||
|
||||
type Claims struct {
|
||||
*jwt.RegisteredClaims
|
||||
|
||||
UserID uint64 `json:"userId"`
|
||||
}
|
||||
|
||||
func NewClaims() *Claims {
|
||||
c := &Claims{
|
||||
RegisteredClaims: &jwt.RegisteredClaims{},
|
||||
}
|
||||
|
||||
var (
|
||||
trustedHosts = os.Getenv("JWT_TRUSTED_HOSTS")
|
||||
audienceList []string
|
||||
)
|
||||
|
||||
c.Issuer = os.Getenv("APP_HOST")
|
||||
|
||||
audienceList = append(audienceList, strings.Split(trustedHosts, ",")...)
|
||||
audienceList = append(audienceList, c.Issuer)
|
||||
audienceList = slices.DeleteFunc(audienceList, func(s string) bool {
|
||||
return s == ""
|
||||
})
|
||||
|
||||
c.Audience = audienceList
|
||||
|
||||
return c
|
||||
}
|
||||
83
modules/jwt/jwt.go
Normal file
83
modules/jwt/jwt.go
Normal file
@@ -0,0 +1,83 @@
|
||||
package jwt
|
||||
|
||||
import (
|
||||
"crypto/ed25519"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"git.ostiwe.com/ostiwe-com/status/model"
|
||||
"git.ostiwe.com/ostiwe-com/status/settings"
|
||||
"github.com/go-chi/jwtauth/v5"
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
"github.com/lestrrat-go/jwx/v2/jwa"
|
||||
)
|
||||
|
||||
var (
|
||||
signKey *ed25519.PrivateKey
|
||||
publicSignKey *ed25519.PublicKey
|
||||
signMethod jwt.SigningMethod
|
||||
|
||||
TokenAuth *jwtauth.JWTAuth
|
||||
)
|
||||
|
||||
func init() {
|
||||
jwtPublicKeyPath := os.Getenv("JWT_SIGN_PUBLIC_KEY_PATH")
|
||||
if !strings.HasPrefix(jwtPublicKeyPath, "/") {
|
||||
jwtPublicKeyPath = settings.WorkingDir + "/" + jwtPublicKeyPath
|
||||
}
|
||||
|
||||
jwtPrivateKeyPath := os.Getenv("JWT_SIGN_PRIVATE_KEY_PATH")
|
||||
if !strings.HasPrefix(jwtPrivateKeyPath, "/") {
|
||||
jwtPrivateKeyPath = settings.WorkingDir + "/" + jwtPrivateKeyPath
|
||||
}
|
||||
|
||||
publicFile, err := os.ReadFile(jwtPublicKeyPath)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
privateFile, err := os.ReadFile(jwtPrivateKeyPath)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
privateKey, err := jwt.ParseEdPrivateKeyFromPEM(privateFile)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
publicKey, err := jwt.ParseEdPublicKeyFromPEM(publicFile)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
pk, ok := privateKey.(ed25519.PrivateKey)
|
||||
if !ok {
|
||||
panic("invalid ed25519 private key")
|
||||
}
|
||||
|
||||
k, ok := publicKey.(ed25519.PublicKey)
|
||||
if !ok {
|
||||
panic("invalid ed25519 public key")
|
||||
}
|
||||
|
||||
signKey = &pk
|
||||
publicSignKey = &k
|
||||
signMethod = jwt.SigningMethodEdDSA
|
||||
|
||||
TokenAuth = jwtauth.New(string(jwa.EdDSA), signKey, publicSignKey)
|
||||
}
|
||||
|
||||
func CreateByUser(user *model.User) (string, error) {
|
||||
claims := NewClaims()
|
||||
claims.Subject = user.Login
|
||||
claims.UserID = user.ID
|
||||
|
||||
claims.IssuedAt = jwt.NewNumericDate(time.Now())
|
||||
claims.ExpiresAt = jwt.NewNumericDate(time.Now().Add(time.Hour * 24 * 2))
|
||||
|
||||
token := jwt.NewWithClaims(signMethod, claims)
|
||||
|
||||
return token.SignedString(signKey)
|
||||
}
|
||||
Reference in New Issue
Block a user