Forge
csharp4405de34
1using System.Text;
2using IntercomService.Auth;
3using IntercomService.Data;
4using IntercomService.Endpoints;
5using IntercomService.Options;
6using IntercomService.Services;
7using Microsoft.AspNetCore.Authentication.JwtBearer;
8using Microsoft.EntityFrameworkCore;
9using Microsoft.IdentityModel.Tokens;
10using OutWit.Database.EntityFramework.Extensions;
11
12var builder = WebApplication.CreateBuilder(args);
13
14builder.Services.Configure<IntercomOptions>(builder.Configuration.GetSection(IntercomOptions.SectionName));
15builder.Services.Configure<JwtOptions>(builder.Configuration.GetSection(JwtOptions.SectionName));
16builder.Services.Configure<GitHubAuthOptions>(builder.Configuration.GetSection(GitHubAuthOptions.SectionName));
17builder.Services.Configure<OidcAuthOptions>(builder.Configuration.GetSection(OidcAuthOptions.SectionName));
18builder.Services.Configure<DevAuthOptions>(builder.Configuration.GetSection(DevAuthOptions.SectionName));
19
20var intercom = builder.Configuration.GetSection(IntercomOptions.SectionName).Get<IntercomOptions>() ?? new IntercomOptions();
21var dataDir = Path.IsPathRooted(intercom.DataDirectory)
22 ? intercom.DataDirectory
23 : Path.Combine(builder.Environment.ContentRootPath, intercom.DataDirectory);
24Directory.CreateDirectory(dataDir);
25var dbPath = Path.Combine(dataDir, intercom.DatabaseFileName);
26
27builder.Services.AddDbContext<IntercomDbContext>(options =>
28 options.UseWitDb($"Data Source={dbPath}"));
29
30builder.Services.AddHttpClient();
31builder.Services.AddSingleton<SseEventHub>();
32builder.Services.AddScoped<JwtTokenService>();
33builder.Services.AddScoped<TransportEventService>();
34builder.Services.AddScoped<TeamInviteService>();
35builder.Services.AddScoped<AgentAccountService>();
36builder.Services.AddScoped<WorkspaceResolveService>();
37builder.Services.AddSingleton<AuthProviderRegistry>();
38builder.Services.AddScoped<TeamMembershipService>();
39builder.Services.AddScoped<GitHubAuthService>();
40builder.Services.AddScoped<OidcAuthService>();
41
42var jwt = builder.Configuration.GetSection(JwtOptions.SectionName).Get<JwtOptions>() ?? new JwtOptions();
43if (string.IsNullOrWhiteSpace(jwt.SigningKey) || jwt.SigningKey.Length < 32)
44{
45 if (builder.Environment.IsDevelopment())
46 jwt.SigningKey = "dev-signing-key-change-me-32chars-min!!";
47 else
48 throw new InvalidOperationException("Jwt:SigningKey must be at least 32 characters.");
49}
50
51builder.Services
52 .AddAuthentication(options =>
53 {
54 options.DefaultAuthenticateScheme = "Smart";
55 options.DefaultChallengeScheme = "Smart";
56 })
57 .AddPolicyScheme("Smart", "Smart", options =>
58 {
59 options.ForwardDefaultSelector = context =>
60 {
61 var header = context.Request.Headers.Authorization.ToString();
62 if (builder.Environment.IsDevelopment()
63 && header.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
64 {
65 var token = header["Bearer ".Length..].Trim();
66 var dev = context.RequestServices.GetRequiredService<Microsoft.Extensions.Options.IOptions<DevAuthOptions>>().Value;
67 if (!string.IsNullOrWhiteSpace(dev.TeamToken)
68 && string.Equals(token, dev.TeamToken, StringComparison.Ordinal))
69 return DevBearerAuthenticationHandler.SchemeName;
70 }
71
72 return JwtBearerDefaults.AuthenticationScheme;
73 };
74 })
75 .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, options =>
76 {
77 options.TokenValidationParameters = new TokenValidationParameters
78 {
79 ValidateIssuer = true,
80 ValidateAudience = true,
81 ValidateLifetime = true,
82 ValidateIssuerSigningKey = true,
83 ValidIssuer = jwt.Issuer,
84 ValidAudience = jwt.Audience,
85 IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwt.SigningKey)),
86 ClockSkew = TimeSpan.FromMinutes(1),
87 };
88 })
89 .AddScheme<Microsoft.AspNetCore.Authentication.AuthenticationSchemeOptions, DevBearerAuthenticationHandler>(
90 DevBearerAuthenticationHandler.SchemeName,
91 _ => { });
92
93builder.Services.AddAuthorization();
94
95var app = builder.Build();
96
97using (var scope = app.Services.CreateScope())
98{
99 var db = scope.ServiceProvider.GetRequiredService<IntercomDbContext>();
100 var intercomOpts = scope.ServiceProvider.GetRequiredService<Microsoft.Extensions.Options.IOptions<IntercomOptions>>().Value;
101 if (intercomOpts.RecreateDatabaseOnStart)
102 db.Database.EnsureDeleted();
103 db.Database.EnsureCreated();
104}
105
106app.UseAuthentication();
107app.UseAuthorization();
108
109app.MapIntercomApi();
110
111app.Run();
112
113public partial class Program;
114
View only · write via MCP/CIDE