Program.cs 3.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. using Fido2NetLib;
  2. using Microsoft.AspNetCore.Authentication.JwtBearer;
  3. using Microsoft.AspNetCore.Mvc;
  4. using Microsoft.IdentityModel.Tokens;
  5. using Passwordless;
  6. // TODO: RoslynPad code for key generation
  7. var jwk = JsonWebKey.Create(File.ReadAllText("./demo-jwk.json"));
  8. var builder = WebApplication.CreateBuilder(args);
  9. // Add services to the container.
  10. // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
  11. builder.Services.AddEndpointsApiExplorer();
  12. builder.Services.AddSwaggerGen();
  13. builder.Services.AddFido2(options =>
  14. {
  15. options.ServerDomain = "localhost";
  16. options.ServerName = "FIDO2 Test";
  17. options.Origins = ["http://localhost:5172"];
  18. options.TimestampDriftTolerance = 300000;
  19. });
  20. builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
  21. .AddJwtBearer(options =>
  22. {
  23. options.Events = new JwtBearerEvents()
  24. {
  25. OnAuthenticationFailed = ctx =>
  26. {
  27. Console.WriteLine(ctx.Exception);
  28. return Task.CompletedTask;
  29. },
  30. OnTokenValidated = ctx =>
  31. {
  32. Console.WriteLine($"Valid token from {ctx.SecurityToken.Issuer}");
  33. return Task.CompletedTask;
  34. }
  35. };
  36. options.RequireHttpsMetadata = false; // dev only!!!
  37. options.Authority = "http://localhost:5172";
  38. options.TokenValidationParameters = new TokenValidationParameters
  39. {
  40. IssuerSigningKey = jwk,
  41. ValidIssuer = "http://localhost:5172",
  42. ValidAudience = "http://localhost:5172"
  43. };
  44. });
  45. builder.Services.AddAuthorization(authorizationOptions =>
  46. {
  47. authorizationOptions.AddPolicy("MagicClaim", policyBuilder => policyBuilder.RequireClaim("permissions", "MagicClaim"));
  48. });
  49. builder.Services.AddMemoryCache();
  50. builder.Services.Configure<JwtConfig>(config => config.Key = jwk);
  51. builder.Services.AddTransient<OptionsCache>();
  52. builder.Services.AddTransient<CredentialManager>();
  53. var app = builder.Build();
  54. // Configure the HTTP request pipeline.
  55. if (app.Environment.IsDevelopment())
  56. {
  57. app.UseSwagger();
  58. app.UseSwaggerUI();
  59. }
  60. app.UseStaticFiles();
  61. app.UseHttpsRedirection();
  62. app.UseAuthorization();
  63. app.MapGet("/buildCredentialOptions", ([FromQuery] string login, CredentialManager credMan) =>
  64. credMan.BuildCredentialOptions(login))
  65. .WithName("BuildCredentialOptions")
  66. .WithOpenApi();
  67. app.MapPost("/registerCredential", async ([FromQuery] string login, [FromBody] AuthenticatorAttestationRawResponse attestationResponse, CredentialManager credMan) =>
  68. await credMan.RegisterCredential(login, attestationResponse))
  69. .WithName("RegisterCredential")
  70. .WithOpenApi();
  71. app.MapGet("/buildAssertionOptions", async ([FromQuery] string login, CredentialManager credMan) =>
  72. await credMan.BuildAssertionOptions(login))
  73. .WithName("BuildAssertionOptions")
  74. .WithOpenApi();
  75. app.MapPost("/verifyCredential", async ([FromBody] AuthenticatorAssertionRawResponse assertionResponse, CredentialManager credMan) =>
  76. Results.Json(await credMan.VerifyCredential(assertionResponse)))
  77. .WithName("VerifyCredential")
  78. .WithOpenApi();
  79. app.MapGet("/protected", () => Results.Json("Success!")).WithName("Protected").RequireAuthorization(policy =>
  80. {
  81. policy.RequireAuthenticatedUser();
  82. //policy.RequireClaim("MagicClaim");
  83. });
  84. app.Run();