>();
-
- // Start validate user is existed and not expired.
- var u = await db.FindByIdAsync(id!);
- if (u == null) throw new SecurityTokenExpiredException("User is not existed in db.");
- if (u.SecurityStamp != stamp) throw new SecurityTokenExpiredException("SecurityStamp is mismatched.");
-
- context.HttpContext.User = p;
- context.Success();
- }
- }
+ OnAuthenticationFailed = OnAuthenticationFailedAsync,
+ OnTokenValidated = OnTokenValidatedAsync
};
});
- // builder.Services.AddAuthorization(opt =>
- // {
- // opt.DefaultPolicy =
- // })
}
private static void SetupWebApplication(WebApplication app)
@@ -170,4 +141,45 @@ public static class Program
app.MapGet("/", () => "Please use client app to open this server.
");
}
}
+
+ private static async Task OnTokenValidatedAsync(TokenValidatedContext context)
+ {
+ if (context.Principal != null)
+ {
+ var p = context.Principal!;
+ var auth = context.HttpContext.GetEndpoint()?.Metadata.GetOrderedMetadata();
+
+ if (auth?.Any() ?? false)
+ {
+ var id = p.FindFirst(ClaimTypes.NameIdentifier)?.Value;
+ if (id == null) throw new SecurityTokenExpiredException("User is not defined in the token!");
+
+ var stamp = p.FindFirst(FlawlessClaimsType.SecurityStamp)?.Value;
+ if (stamp == null) throw new SecurityTokenExpiredException("No valid SecurityStamp found.");
+
+ // Validate user status
+ var db = context.HttpContext.RequestServices.GetRequiredService>();
+
+ var u = await db.FindByIdAsync(id!);
+ if (u == null) throw new SecurityTokenExpiredException("User is not existed.");
+
+ if (u.SecurityStamp != stamp) throw new SecurityTokenExpiredException("SecurityStamp is mismatched.");
+ if (u.LockoutEnabled) throw new SecurityTokenExpiredException("User has been locked.");
+ }
+
+ // Extract user info into HttpContext
+ context.HttpContext.User = p;
+ context.Success();
+ }
+ }
+
+ private static Task OnAuthenticationFailedAsync(AuthenticationFailedContext context)
+ {
+ if (context.Exception.GetType() == typeof(SecurityTokenExpiredException))
+ {
+ context.Response.Headers.Append("Token-Expired", "true");
+ }
+
+ return Task.CompletedTask;
+ }
}
\ No newline at end of file
diff --git a/Flawless.Server/Services/AppDbContext.cs b/Flawless.Server/Services/AppDbContext.cs
index 1fe39a5..eae992e 100644
--- a/Flawless.Server/Services/AppDbContext.cs
+++ b/Flawless.Server/Services/AppDbContext.cs
@@ -9,4 +9,5 @@ public class AppDbContext(DbContextOptions options)
: IdentityDbContext, Guid>(options)
{
public DbSet RefreshTokens { get; set; }
+
}
\ No newline at end of file
diff --git a/Flawless.Server/appsettings.Development.json b/Flawless.Server/appsettings.Development.json
index d4ee3dc..5b1be17 100644
--- a/Flawless.Server/appsettings.Development.json
+++ b/Flawless.Server/appsettings.Development.json
@@ -11,7 +11,7 @@
},
"LocalStoragePath": "./data/development",
"User": {
- "PublicRegister": false
+ "PublicRegister": true
},
"Jwt": {
"SecretKey": "your_256bit_security_key_at_here_otherwise_not_bootable",