Gate password sign-in on email verification

Unverified password identities were able to open sessions after
signing out. Reject sign-in with EMAIL_NOT_VERIFIED and add a
resend-confirmation flow so users can complete verification.

Signed-off-by: Émile Ré <emile@probo.com>
This commit is contained in:
Émile Ré
2026-07-28 10:15:25 +02:00
parent bb9fb22913
commit 5d0882778f
19 changed files with 621 additions and 60 deletions

View File

@@ -111,6 +111,7 @@ func (b *Builder) Build() (*probodconfig.FullConfig, error) {
InvitationConfirmationTokenValidity: b.resolver.getEnvIntOrDefault("PROBOD_AUTH_INVITATION_TOKEN_VALIDITY", 3600),
PasswordResetTokenValidity: b.resolver.getEnvIntOrDefault("PROBOD_AUTH_PASSWORD_RESET_TOKEN_VALIDITY", 3600),
MagicLinkTokenValidity: b.resolver.getEnvIntOrDefault("PROBOD_AUTH_MAGIC_LINK_TOKEN_VALIDITY", 900),
EmailConfirmationTokenValidity: b.resolver.getEnvIntOrDefault("PROBOD_AUTH_EMAIL_CONFIRMATION_TOKEN_VALIDITY", 3600),
Cookie: probodconfig.CookieConfig{
Name: b.resolver.getEnv("PROBOD_AUTH_COOKIE_NAME"),
Domain: b.resolver.getEnv("PROBOD_AUTH_COOKIE_DOMAIN"),

View File

@@ -175,6 +175,7 @@ func TestBuilder_Build_Defaults(t *testing.T) {
assert.Equal(t, 3600, cfg.Probod.Auth.InvitationConfirmationTokenValidity)
assert.Equal(t, 3600, cfg.Probod.Auth.PasswordResetTokenValidity)
assert.Equal(t, 900, cfg.Probod.Auth.MagicLinkTokenValidity)
assert.Equal(t, 3600, cfg.Probod.Auth.EmailConfirmationTokenValidity)
assert.Empty(t, cfg.Probod.Auth.Cookie.Name)
assert.Empty(t, cfg.Probod.Auth.Cookie.Domain)
assert.Equal(t, 24, cfg.Probod.Auth.Cookie.Duration)
@@ -331,6 +332,7 @@ func TestBuilder_Build_CustomValues(t *testing.T) {
env["PROBOD_AUTH_INVITATION_TOKEN_VALIDITY"] = "7200"
env["PROBOD_AUTH_PASSWORD_RESET_TOKEN_VALIDITY"] = "1800"
env["PROBOD_AUTH_MAGIC_LINK_TOKEN_VALIDITY"] = "600"
env["PROBOD_AUTH_EMAIL_CONFIRMATION_TOKEN_VALIDITY"] = "43200"
env["PROBOD_AUTH_COOKIE_DOMAIN"] = ".example.com"
env["PROBOD_AUTH_COOKIE_DURATION"] = "48"
// SAML
@@ -466,6 +468,7 @@ func TestBuilder_Build_CustomValues(t *testing.T) {
assert.Equal(t, 7200, cfg.Probod.Auth.InvitationConfirmationTokenValidity)
assert.Equal(t, 1800, cfg.Probod.Auth.PasswordResetTokenValidity)
assert.Equal(t, 600, cfg.Probod.Auth.MagicLinkTokenValidity)
assert.Equal(t, 43200, cfg.Probod.Auth.EmailConfirmationTokenValidity)
assert.Equal(t, ".example.com", cfg.Probod.Auth.Cookie.Domain)
assert.Equal(t, 48, cfg.Probod.Auth.Cookie.Duration)
// SAML