diff --git a/dataprovider/bolt.go b/dataprovider/bolt.go
index a9b84036..ced30801 100644
--- a/dataprovider/bolt.go
+++ b/dataprovider/bolt.go
@@ -118,7 +118,7 @@ func (p *BoltProvider) validateAdminAndPass(username, password, ip string) (Admi
 	return admin, err
 }
 
-func (p *BoltProvider) validateUserAndPubKey(username string, pubKey []byte) (User, string, error) {
+func (p *BoltProvider) validateUserAndPubKey(username string, pubKey []byte, isSSHCert bool) (User, string, error) {
 	var user User
 	if len(pubKey) == 0 {
 		return user, "", errors.New("credentials cannot be null or empty")
@@ -128,7 +128,7 @@ func (p *BoltProvider) validateUserAndPubKey(username string, pubKey []byte) (Us
 		providerLog(logger.LevelWarn, "error authenticating user %#v: %v", username, err)
 		return user, "", err
 	}
-	return checkUserAndPubKey(&user, pubKey)
+	return checkUserAndPubKey(&user, pubKey, isSSHCert)
 }
 
 func (p *BoltProvider) updateAPIKeyLastUse(keyID string) error {
diff --git a/dataprovider/dataprovider.go b/dataprovider/dataprovider.go
index 97c3a673..57e03130 100644
--- a/dataprovider/dataprovider.go
+++ b/dataprovider/dataprovider.go
@@ -615,7 +615,7 @@ func HasUsersBaseDir() bool {
 // Provider defines the interface that data providers must implement.
 type Provider interface {
 	validateUserAndPass(username, password, ip, protocol string) (User, error)
-	validateUserAndPubKey(username string, pubKey []byte) (User, string, error)
+	validateUserAndPubKey(username string, pubKey []byte, isSSHCert bool) (User, string, error)
 	validateUserAndTLSCert(username, protocol string, tlsCert *x509.Certificate) (User, error)
 	updateQuota(username string, filesAdd int, sizeAdd int64, reset bool) error
 	updateTransferQuota(username string, uploadSize, downloadSize int64, reset bool) error
@@ -1054,30 +1054,30 @@ func CheckUserAndPass(username, password, ip, protocol string) (User, error) {
 }
 
 // CheckUserAndPubKey retrieves the SFTP user with the given username and public key if a match is found or an error
-func CheckUserAndPubKey(username string, pubKey []byte, ip, protocol string) (User, string, error) {
+func CheckUserAndPubKey(username string, pubKey []byte, ip, protocol string, isSSHCert bool) (User, string, error) {
 	username = config.convertName(username)
 	if plugin.Handler.HasAuthScope(plugin.AuthScopePublicKey) {
 		user, err := doPluginAuth(username, "", pubKey, ip, protocol, nil, plugin.AuthScopePublicKey)
 		if err != nil {
 			return user, "", err
 		}
-		return checkUserAndPubKey(&user, pubKey)
+		return checkUserAndPubKey(&user, pubKey, isSSHCert)
 	}
 	if config.ExternalAuthHook != "" && (config.ExternalAuthScope == 0 || config.ExternalAuthScope&2 != 0) {
 		user, err := doExternalAuth(username, "", pubKey, "", ip, protocol, nil)
 		if err != nil {
 			return user, "", err
 		}
-		return checkUserAndPubKey(&user, pubKey)
+		return checkUserAndPubKey(&user, pubKey, isSSHCert)
 	}
 	if config.PreLoginHook != "" {
 		user, err := executePreLoginHook(username, SSHLoginMethodPublicKey, ip, protocol)
 		if err != nil {
 			return user, "", err
 		}
-		return checkUserAndPubKey(&user, pubKey)
+		return checkUserAndPubKey(&user, pubKey, isSSHCert)
 	}
-	return provider.validateUserAndPubKey(username, pubKey)
+	return provider.validateUserAndPubKey(username, pubKey, isSSHCert)
 }
 
 // CheckKeyboardInteractiveAuth checks the keyboard interactive authentication and returns
@@ -2178,9 +2178,10 @@ func validateBaseParams(user *User) error {
 	if user.HomeDir == "" {
 		return util.NewValidationError("home_dir is mandatory")
 	}
-	if user.Password == "" && len(user.PublicKeys) == 0 {
+	// we can have users with no passwords and public keys, they can authenticate via SSH user certs or OIDC
+	/*if user.Password == "" && len(user.PublicKeys) == 0 {
 		return util.NewValidationError("please set a password or at least a public_key")
-	}
+	}*/
 	if !filepath.IsAbs(user.HomeDir) {
 		return util.NewValidationError(fmt.Sprintf("home_dir must be an absolute path, actual value: %v", user.HomeDir))
 	}
@@ -2429,28 +2430,25 @@ func checkUserPasscode(user *User, password, protocol string) (string, error) {
 	return password, nil
 }
 
-func checkUserAndPubKey(user *User, pubKey []byte) (User, string, error) {
+func checkUserAndPubKey(user *User, pubKey []byte, isSSHCert bool) (User, string, error) {
 	err := user.CheckLoginConditions()
 	if err != nil {
 		return *user, "", err
 	}
+	if isSSHCert {
+		return *user, "", nil
+	}
 	if len(user.PublicKeys) == 0 {
 		return *user, "", ErrInvalidCredentials
 	}
 	for i, k := range user.PublicKeys {
 		storedPubKey, comment, _, _, err := ssh.ParseAuthorizedKey([]byte(k))
 		if err != nil {
-			providerLog(logger.LevelError, "error parsing stored public key %d for user %v: %v", i, user.Username, err)
+			providerLog(logger.LevelError, "error parsing stored public key %d for user %s: %v", i, user.Username, err)
 			return *user, "", err
 		}
 		if bytes.Equal(storedPubKey.Marshal(), pubKey) {
-			certInfo := ""
-			cert, ok := storedPubKey.(*ssh.Certificate)
-			if ok {
-				certInfo = fmt.Sprintf(" %v ID: %v Serial: %v CA: %v", cert.Type(), cert.KeyId, cert.Serial,
-					ssh.FingerprintSHA256(cert.SignatureKey))
-			}
-			return *user, fmt.Sprintf("%s:%s%s", ssh.FingerprintSHA256(storedPubKey), comment, certInfo), nil
+			return *user, fmt.Sprintf("%s:%s", ssh.FingerprintSHA256(storedPubKey), comment), nil
 		}
 	}
 	return *user, "", ErrInvalidCredentials
diff --git a/dataprovider/memory.go b/dataprovider/memory.go
index 9bdad0bb..355c02ad 100644
--- a/dataprovider/memory.go
+++ b/dataprovider/memory.go
@@ -126,7 +126,7 @@ func (p *MemoryProvider) validateUserAndPass(username, password, ip, protocol st
 	return checkUserAndPass(&user, password, ip, protocol)
 }
 
-func (p *MemoryProvider) validateUserAndPubKey(username string, pubKey []byte) (User, string, error) {
+func (p *MemoryProvider) validateUserAndPubKey(username string, pubKey []byte, isSSHCert bool) (User, string, error) {
 	var user User
 	if len(pubKey) == 0 {
 		return user, "", errors.New("credentials cannot be null or empty")
@@ -136,7 +136,7 @@ func (p *MemoryProvider) validateUserAndPubKey(username string, pubKey []byte) (
 		providerLog(logger.LevelWarn, "error authenticating user %#v: %v", username, err)
 		return user, "", err
 	}
-	return checkUserAndPubKey(&user, pubKey)
+	return checkUserAndPubKey(&user, pubKey, isSSHCert)
 }
 
 func (p *MemoryProvider) validateAdminAndPass(username, password, ip string) (Admin, error) {
diff --git a/dataprovider/mysql.go b/dataprovider/mysql.go
index 9b9da95a..3ab8c6a9 100644
--- a/dataprovider/mysql.go
+++ b/dataprovider/mysql.go
@@ -203,8 +203,8 @@ func (p *MySQLProvider) validateUserAndTLSCert(username, protocol string, tlsCer
 	return sqlCommonValidateUserAndTLSCertificate(username, protocol, tlsCert, p.dbHandle)
 }
 
-func (p *MySQLProvider) validateUserAndPubKey(username string, publicKey []byte) (User, string, error) {
-	return sqlCommonValidateUserAndPubKey(username, publicKey, p.dbHandle)
+func (p *MySQLProvider) validateUserAndPubKey(username string, publicKey []byte, isSSHCert bool) (User, string, error) {
+	return sqlCommonValidateUserAndPubKey(username, publicKey, isSSHCert, p.dbHandle)
 }
 
 func (p *MySQLProvider) updateTransferQuota(username string, uploadSize, downloadSize int64, reset bool) error {
diff --git a/dataprovider/pgsql.go b/dataprovider/pgsql.go
index 02493ce1..91d35d7e 100644
--- a/dataprovider/pgsql.go
+++ b/dataprovider/pgsql.go
@@ -179,8 +179,8 @@ func (p *PGSQLProvider) validateUserAndTLSCert(username, protocol string, tlsCer
 	return sqlCommonValidateUserAndTLSCertificate(username, protocol, tlsCert, p.dbHandle)
 }
 
-func (p *PGSQLProvider) validateUserAndPubKey(username string, publicKey []byte) (User, string, error) {
-	return sqlCommonValidateUserAndPubKey(username, publicKey, p.dbHandle)
+func (p *PGSQLProvider) validateUserAndPubKey(username string, publicKey []byte, isSSHCert bool) (User, string, error) {
+	return sqlCommonValidateUserAndPubKey(username, publicKey, isSSHCert, p.dbHandle)
 }
 
 func (p *PGSQLProvider) updateTransferQuota(username string, uploadSize, downloadSize int64, reset bool) error {
diff --git a/dataprovider/sqlcommon.go b/dataprovider/sqlcommon.go
index 107e4f42..bd40bc9b 100644
--- a/dataprovider/sqlcommon.go
+++ b/dataprovider/sqlcommon.go
@@ -620,7 +620,7 @@ func sqlCommonValidateUserAndTLSCertificate(username, protocol string, tlsCert *
 	return checkUserAndTLSCertificate(&user, protocol, tlsCert)
 }
 
-func sqlCommonValidateUserAndPubKey(username string, pubKey []byte, dbHandle *sql.DB) (User, string, error) {
+func sqlCommonValidateUserAndPubKey(username string, pubKey []byte, isSSHCert bool, dbHandle *sql.DB) (User, string, error) {
 	var user User
 	if len(pubKey) == 0 {
 		return user, "", errors.New("credentials cannot be null or empty")
@@ -630,7 +630,7 @@ func sqlCommonValidateUserAndPubKey(username string, pubKey []byte, dbHandle *sq
 		providerLog(logger.LevelWarn, "error authenticating user %#v: %v", username, err)
 		return user, "", err
 	}
-	return checkUserAndPubKey(&user, pubKey)
+	return checkUserAndPubKey(&user, pubKey, isSSHCert)
 }
 
 func sqlCommonCheckAvailability(dbHandle *sql.DB) error {
diff --git a/dataprovider/sqlite.go b/dataprovider/sqlite.go
index d18861a1..5ba82c1c 100644
--- a/dataprovider/sqlite.go
+++ b/dataprovider/sqlite.go
@@ -153,8 +153,8 @@ func (p *SQLiteProvider) validateUserAndTLSCert(username, protocol string, tlsCe
 	return sqlCommonValidateUserAndTLSCertificate(username, protocol, tlsCert, p.dbHandle)
 }
 
-func (p *SQLiteProvider) validateUserAndPubKey(username string, publicKey []byte) (User, string, error) {
-	return sqlCommonValidateUserAndPubKey(username, publicKey, p.dbHandle)
+func (p *SQLiteProvider) validateUserAndPubKey(username string, publicKey []byte, isSSHCert bool) (User, string, error) {
+	return sqlCommonValidateUserAndPubKey(username, publicKey, isSSHCert, p.dbHandle)
 }
 
 func (p *SQLiteProvider) updateTransferQuota(username string, uploadSize, downloadSize int64, reset bool) error {
diff --git a/httpd/httpd_test.go b/httpd/httpd_test.go
index cf758d8d..391a53b0 100644
--- a/httpd/httpd_test.go
+++ b/httpd/httpd_test.go
@@ -1583,7 +1583,13 @@ func TestAddUserNoCredentials(t *testing.T) {
 	u := getTestUser()
 	u.Password = ""
 	u.PublicKeys = []string{}
-	_, _, err := httpdtest.AddUser(u, http.StatusBadRequest)
+	user, _, err := httpdtest.AddUser(u, http.StatusCreated)
+	assert.NoError(t, err)
+	// this user cannot login with an empty password but it still can use an SSH cert
+	_, err = getJWTAPITokenFromTestServer(defaultTokenAuthUser, "")
+	assert.Error(t, err)
+
+	_, err = httpdtest.RemoveUser(user, http.StatusOK)
 	assert.NoError(t, err)
 }
 
diff --git a/sftpd/server.go b/sftpd/server.go
index e5fb509e..3417af4b 100644
--- a/sftpd/server.go
+++ b/sftpd/server.go
@@ -885,6 +885,13 @@ func (c *Configuration) validatePublicKeyCredentials(conn ssh.ConnMetadata, pubK
 			updateLoginMetrics(&user, ipAddr, method, err)
 			return nil, err
 		}
+		if len(cert.ValidPrincipals) == 0 {
+			err = fmt.Errorf("ssh: certificate %s has no valid principals, user: \"%s\"",
+				ssh.FingerprintSHA256(pubKey), conn.User())
+			user.Username = conn.User()
+			updateLoginMetrics(&user, ipAddr, method, err)
+			return nil, err
+		}
 		if err := c.certChecker.CheckCert(conn.User(), cert); err != nil {
 			user.Username = conn.User()
 			updateLoginMetrics(&user, ipAddr, method, err)
@@ -892,7 +899,11 @@ func (c *Configuration) validatePublicKeyCredentials(conn ssh.ConnMetadata, pubK
 		}
 		certPerm = &cert.Permissions
 	}
-	if user, keyID, err = dataprovider.CheckUserAndPubKey(conn.User(), pubKey.Marshal(), ipAddr, common.ProtocolSSH); err == nil {
+	if user, keyID, err = dataprovider.CheckUserAndPubKey(conn.User(), pubKey.Marshal(), ipAddr, common.ProtocolSSH, ok); err == nil {
+		if ok {
+			keyID = fmt.Sprintf("%s: ID: %s, serial: %v, CA %s %s", ssh.FingerprintSHA256(pubKey),
+				cert.KeyId, cert.Serial, cert.Type(), ssh.FingerprintSHA256(cert.SignatureKey))
+		}
 		if user.IsPartialAuth(method) {
 			logger.Debug(logSender, connectionID, "user %#v authenticated with partial success", conn.User())
 			return certPerm, ssh.ErrPartialSuccess
diff --git a/sftpd/sftpd_test.go b/sftpd/sftpd_test.go
index c00d9146..0e875cb3 100644
--- a/sftpd/sftpd_test.go
+++ b/sftpd/sftpd_test.go
@@ -116,10 +116,13 @@ iixITGvaNZh/tjAAAACW5pY29sYUBwMQE=
 	// this is testPubKey signed using testCAUserKey but expired.
 	// % ssh-keygen -s ca_user_key -I test_user_sftp -n test_user_sftp -V 20100101123000:20110101123000 -z 4 /tmp/test.pub
 	testCertExpired = "ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgU3TLP5285k20fBSsdZioI78oJUpaRXFlgx5IPg6gWg8AAAADAQABAAABgQC03jj0D+djk7pxIf/0OhrxrchJTRZklofJ1NoIu4752Sq02mdXmarMVsqJ1cAjV5LBVy3D1F5U6XW4rppkXeVtd04Pxb09ehtH0pRRPaoHHlALiJt8CoMpbKYMA8b3KXPPriGxgGomvtU2T2RMURSwOZbMtpsugfjYSWenyYX+VORYhylWnSXL961LTyC21ehd6d6QnW9G7E5hYMITMY9TuQZz3bROYzXiTsgN0+g6Hn7exFQp50p45StUMfV/SftCMdCxlxuyGny2CrN/vfjO7xxOo2uv7q1qm10Q46KPWJQv+pgZ/OfL+EDjy07n5QVSKHlbx+2nT4Q0EgOSQaCTYwn3YjtABfIxWwgAFdyj6YlPulCL22qU4MYhDcA6PSBwDdf8hvxBfvsiHdM+JcSHvv8/VeJhk6CmnZxGY0fxBupov27z3yEO8nAg8k+6PaUiW1MSUfuGMF/ktB8LOstXsEPXSszuyXiOv4DaryOXUiSn7bmRqKcEFlJusO6aZP0AAAAAAAAABAAAAAEAAAAOdGVzdF91c2VyX3NmdHAAAAASAAAADnRlc3RfdXNlcl9zZnRwAAAAAEs93LgAAAAATR8QOAAAAAAAAACCAAAAFXBlcm1pdC1YMTEtZm9yd2FyZGluZwAAAAAAAAAXcGVybWl0LWFnZW50LWZvcndhcmRpbmcAAAAAAAAAFnBlcm1pdC1wb3J0LWZvcndhcmRpbmcAAAAAAAAACnBlcm1pdC1wdHkAAAAAAAAADnBlcm1pdC11c2VyLXJjAAAAAAAAAAAAAAGXAAAAB3NzaC1yc2EAAAADAQABAAABgQDF5fcwZHiyixmnE6IlOZJpZhWXoh62gN+yadAA0GJ509SAEaZVLPDP8S5RsE8mUikR3wxynVshxHeqMhrkS+RlNbhSlOXDdNg94yTrq/xF8Z/PgKRInvef74k5i7bAIytza7jERzFJ/ujTEy3537T5k5EYQJ15ZQGuvzynSdv+6o99SjI4jFplyQOZ2QcYbEAmhHm5GgQlIiEFG/RlDtLksOulKZxOY3qPzP0AyQxtZJXn/5vG40aW9LTbwxCJqWlgrkFXMqAAVCbuU5YspwhiXmKt1PsldiXw23oloa4caCKN1jzbFiGuZNXEU2Ebx7JIvjQCPaUYwLjEbkRDxDqN/vmwZqBuKYiuG9Eafx+nFSQkr7QYb5b+mT+/1IFHnmeRGn38731kBqtH7tpzC/t+soRX9p2HtJM+9MYhblO2OqTSPGTlxihWUkyiRBekpAhaiHld16TsG+A3bOJHrojGcX+5g6oGarKGLAMcykL1X+rZqT993Mo6d2Z7q43MOXEAAAGUAAAADHJzYS1zaGEyLTUxMgAAAYAlH3hhj8J6xLyVpeLZjblzwDKrxp/MWiH30hQ965ExPrPRcoAZFEKVqOYdj6bp4Q19Q4Yzqdobg3aN5ym2iH0b2TlOY0mM901CAoHbNJyiLs+0KiFRoJ+30EDj/hcKusg6v8ln2yixPagAyQu3zyiWo4t1ZuO3I86xchGlptStxSdHAHPFCfpbhcnzWFZctiMqUutl82C4ROWyjOZcRzdVdWHeN5h8wnooXuvba2VkT8QPmjYYyRGuQ3Hg+ySdh8Tel4wiix1Dg5MX7Wjh4hKEx80No9UPy+0iyZMNc07lsWAtrY6NRxGM5CzB6mklscB8TzFrVSnIl9u3bquLfaCrFt/Mft5dR7Yy4jmF+zUhjia6h6giCZ91J+FZ4hV+WkBtPCvTfrGWoA1BgEB/iI2xOq/NPqJ7UXRoMXk/l0NPgRPT2JS1adegqnt4ddr6IlmPyZxaSEvXhanjKdfMlEFYO1wz7ouqpYUozQVy4KXBlzFlNwyD1hI+k4+/A6AIYeI= nicola@p1"
-	configDir       = ".."
-	osWindows       = "windows"
-	testFileName    = "test_file_sftp.dat"
-	testDLFileName  = "test_download_sftp.dat"
+	// this is testPubKey signed without a principal
+	// ssh-keygen -s ca_user_key -I test_user_sftp -V always:forever -O source-address=127.0.0.1 -z 1 /tmp/test.pub
+	testCertNoPrincipals = "ssh-rsa-cert-v01@openssh.com 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 nicola@p1"
+	configDir            = ".."
+	osWindows            = "windows"
+	testFileName         = "test_file_sftp.dat"
+	testDLFileName       = "test_download_sftp.dat"
 )
 
 var (
@@ -1788,7 +1791,6 @@ func TestLogin(t *testing.T) {
 
 func TestLoginUserCert(t *testing.T) {
 	u := getTestUser(true)
-	u.PublicKeys = []string{testCertValid, testCertUntrustedCA, testHostCert, testCertOtherSourceAddress, testCertExpired}
 	user, _, err := httpdtest.AddUser(u, http.StatusCreated)
 	assert.NoError(t, err)
 	// try login using a cert signed from a trusted CA
@@ -1832,11 +1834,28 @@ func TestLoginUserCert(t *testing.T) {
 		client.Close()
 		conn.Close()
 	}
+	// try login using a certificate with no principals
+	signer, err = getSignerForUserCert([]byte(testCertNoPrincipals))
+	assert.NoError(t, err)
+	conn, client, err = getCustomAuthSftpClient(user, []ssh.AuthMethod{ssh.PublicKeys(signer)}, "")
+	if !assert.Error(t, err) {
+		client.Close()
+		conn.Close()
+	}
 	_, err = httpdtest.RemoveUser(user, http.StatusOK)
 	assert.NoError(t, err)
 	err = os.RemoveAll(user.GetHomeDir())
 	assert.NoError(t, err)
 
+	// the user does not exist
+	signer, err = getSignerForUserCert([]byte(testCertValid))
+	assert.NoError(t, err)
+	conn, client, err = getCustomAuthSftpClient(user, []ssh.AuthMethod{ssh.PublicKeys(signer)}, "")
+	if !assert.Error(t, err) {
+		client.Close()
+		conn.Close()
+	}
+
 	// now login with a username not in the set of valid principals for the given certificate
 	u.Username += "1"
 	user, _, err = httpdtest.AddUser(u, http.StatusCreated)
@@ -1989,7 +2008,6 @@ func TestMultiStepLoginKeyAndKeyInt(t *testing.T) {
 func TestMultiStepLoginCertAndPwd(t *testing.T) {
 	u := getTestUser(true)
 	u.Password = defaultPassword
-	u.PublicKeys = []string{testCertValid, testCertOtherSourceAddress}
 	u.Filters.DeniedLoginMethods = append(u.Filters.DeniedLoginMethods, []string{
 		dataprovider.SSHLoginMethodKeyAndKeyboardInt,
 		dataprovider.SSHLoginMethodPublicKey,