hash pin and password

This commit is contained in:
pascal
2026-02-11 11:48:15 +01:00
parent 5ae15b3af3
commit cfe6753349
3 changed files with 74 additions and 3 deletions

View File

@@ -148,6 +148,10 @@ func (m *managerImpl) CreateReverseProxy(ctx context.Context, accountID, userID
reverseProxy.AccountID = accountID
reverseProxy.ProxyCluster = proxyCluster
reverseProxy.InitNewRecord()
err = reverseProxy.Auth.HashSecrets()
if err != nil {
return nil, fmt.Errorf("hash secrets: %w", err)
}
// Generate session JWT signing keys
keyPair, err := sessionkey.GenerateKeyPair()
@@ -215,6 +219,11 @@ func (m *managerImpl) UpdateReverseProxy(ctx context.Context, accountID, userID
var domainChanged bool
var reverseProxyEnabledChanged bool
err = reverseProxy.Auth.HashSecrets()
if err != nil {
return nil, fmt.Errorf("hash secrets: %w", err)
}
err = m.store.ExecuteInTransaction(ctx, func(transaction store.Store) error {
existingReverseProxy, err := transaction.GetReverseProxyByID(ctx, store.LockingStrengthUpdate, accountID, reverseProxy.ID)
if err != nil {
@@ -246,6 +255,18 @@ func (m *managerImpl) UpdateReverseProxy(ctx context.Context, accountID, userID
reverseProxy.ProxyCluster = existingReverseProxy.ProxyCluster
}
if reverseProxy.Auth.PasswordAuth != nil && reverseProxy.Auth.PasswordAuth.Enabled &&
existingReverseProxy.Auth.PasswordAuth != nil && existingReverseProxy.Auth.PasswordAuth.Enabled &&
reverseProxy.Auth.PasswordAuth.Password == "" {
reverseProxy.Auth.PasswordAuth = existingReverseProxy.Auth.PasswordAuth
}
if reverseProxy.Auth.PinAuth != nil && reverseProxy.Auth.PinAuth.Enabled &&
existingReverseProxy.Auth.PinAuth != nil && existingReverseProxy.Auth.PinAuth.Enabled &&
reverseProxy.Auth.PinAuth.Pin == "" {
reverseProxy.Auth.PinAuth = existingReverseProxy.Auth.PinAuth
}
reverseProxy.Meta = existingReverseProxy.Meta
reverseProxy.SessionPrivateKey = existingReverseProxy.SessionPrivateKey
reverseProxy.SessionPublicKey = existingReverseProxy.SessionPublicKey

View File

@@ -10,6 +10,7 @@ import (
"github.com/rs/xid"
log "github.com/sirupsen/logrus"
"golang.org/x/crypto/bcrypt"
"github.com/netbirdio/netbird/util/crypt"
@@ -75,6 +76,35 @@ type AuthConfig struct {
BearerAuth *BearerAuthConfig `json:"bearer_auth,omitempty" gorm:"serializer:json"`
}
func (a *AuthConfig) HashSecrets() error {
if a.PasswordAuth != nil && a.PasswordAuth.Enabled && a.PasswordAuth.Password != "" {
hash, err := bcrypt.GenerateFromPassword([]byte(a.PasswordAuth.Password), 12)
if err != nil {
return err
}
a.PasswordAuth.Password = string(hash)
}
if a.PinAuth != nil && a.PinAuth.Enabled && a.PinAuth.Pin != "" {
hash, err := bcrypt.GenerateFromPassword([]byte(a.PinAuth.Pin), 12)
if err != nil {
return err
}
a.PinAuth.Pin = string(hash)
}
return nil
}
func (a *AuthConfig) ClearSecrets() {
if a.PasswordAuth != nil {
a.PasswordAuth.Password = ""
}
if a.PinAuth != nil {
a.PinAuth.Pin = ""
}
}
type OIDCValidationConfig struct {
Issuer string
Audiences []string
@@ -133,6 +163,8 @@ func (r *ReverseProxy) InitNewRecord() {
}
func (r *ReverseProxy) ToAPIResponse() *api.ReverseProxy {
r.Auth.ClearSecrets()
authConfig := api.ReverseProxyAuthConfig{}
if r.Auth.PasswordAuth != nil {

View File

@@ -4,7 +4,6 @@ import (
"context"
"crypto/hmac"
"crypto/sha256"
"crypto/subtle"
"encoding/base64"
"encoding/hex"
"errors"
@@ -17,6 +16,7 @@ import (
"github.com/coreos/go-oidc/v3/oidc"
log "github.com/sirupsen/logrus"
"golang.org/x/crypto/bcrypt"
"golang.org/x/oauth2"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/peer"
@@ -441,7 +441,16 @@ func (s *ProxyServiceServer) Authenticate(ctx context.Context, req *proto.Authen
// Break here and use the default authenticated == false.
break
}
authenticated = subtle.ConstantTimeCompare([]byte(auth.Pin), []byte(v.Pin.GetPin())) == 1
err = bcrypt.CompareHashAndPassword([]byte(auth.Pin), []byte(v.Pin.GetPin()))
if err != nil {
if errors.Is(err, bcrypt.ErrMismatchedHashAndPassword) {
log.WithContext(ctx).Tracef("PIN authentication failed: invalid PIN")
} else {
log.WithContext(ctx).Errorf("PIN authentication error: %v", err)
}
break
}
authenticated = true
userId = "pin-user"
method = proxyauth.MethodPIN
case *proto.AuthenticateRequest_Password:
@@ -451,7 +460,16 @@ func (s *ProxyServiceServer) Authenticate(ctx context.Context, req *proto.Authen
// Break here and use the default authenticated == false.
break
}
authenticated = subtle.ConstantTimeCompare([]byte(auth.Password), []byte(v.Password.GetPassword())) == 1
err = bcrypt.CompareHashAndPassword([]byte(auth.Password), []byte(v.Password.GetPassword()))
if err != nil {
if errors.Is(err, bcrypt.ErrMismatchedHashAndPassword) {
log.WithContext(ctx).Tracef("Password authentication failed: invalid password")
} else {
log.WithContext(ctx).Errorf("Password authentication error: %v", err)
}
break
}
authenticated = true
userId = "password-user"
method = proxyauth.MethodPassword
}