-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathProgram.cs
More file actions
148 lines (119 loc) · 4.55 KB
/
Program.cs
File metadata and controls
148 lines (119 loc) · 4.55 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.IdentityModel.Tokens;
using skipper_paste;
using System.Text;
using System.Text.Json;
var builder = WebApplication.CreateBuilder(args);
builder.Logging.AddConfiguration(builder.Configuration.GetSection("Logging"));
#if DEBUG
builder.Logging.ClearProviders();
builder.Logging.AddSimpleConsole();
builder.Logging.SetMinimumLevel(LogLevel.Trace);
#endif
// Add services to the container.
// Learn more about configuring OpenAPI at https://aka.ms/aspnet/openapi
builder.Services.AddOpenApi();
builder.Services.AddCors();
builder.Services.AddAuthentication();
builder.Services.AddAuthorizationBuilder()
.AddPolicy("PasteScope", policy =>
{
policy.RequireAuthenticatedUser();
policy.RequireClaim("scope", "paste");
});
var config = builder.Configuration.GetSection("Paste");
var domain = config.GetValue<string>("Domain", "localhost:5001");
var port = config.GetValue<int?>("Port", 5001);
var secret = config.GetValue<string>("Secret", "this_is_a_secret_key_for_jwt_validation");
var pasteDirectory = config.GetValue<string>("Directory", Path.Combine(AppContext.BaseDirectory, "paste-data"));
if (args.Length == 1 && args[0] == "new-token")
{
Console.WriteLine("Generating new token...");
//generate new JWT token based on configuration
var claims = new[]
{
new System.Security.Claims.Claim("scope", "paste"),
new System.Security.Claims.Claim(System.Security.Claims.ClaimTypes.Name, "paste-user")
};
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(secret));
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
var token = new System.IdentityModel.Tokens.Jwt.JwtSecurityToken(
issuer: $"https://{domain}",
audience: "paste",
claims: claims,
expires: DateTime.UtcNow.AddYears(2),
signingCredentials: creds
);
var tokenString = new System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler().WriteToken(token);
Console.WriteLine("JWT Token:");
Console.WriteLine(tokenString);
return;
}
//add jwt token validation with secret configured from startup
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.Authority = $"https://{domain}";
options.Audience = "paste";
options.RequireHttpsMetadata = false; // For development purposes only,
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
NameClaimType = System.Security.Claims.ClaimTypes.Name,
ValidIssuer = $"https://{domain}",
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(secret))
};
});
var app = builder.Build();
app.UseCors();
app.UseAuthentication();
app.UseAuthorization();
app.Logger.LogInformation("Checking paste directory at {directory}", pasteDirectory);
if (!Directory.Exists(pasteDirectory))
{
app.Logger.LogInformation("Paste directory at {directory} doesn't exist!", pasteDirectory);
Directory.CreateDirectory(pasteDirectory);
}
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.MapOpenApi();
}
app.UseHttpsRedirection();
app.UseAuthentication();
app.UseAuthentication();
app.MapPost("/paste", (PasteData data, HttpRequest request) =>
{
var pasteId = RandomNameGenerator.GenerateRandomName(5);
File.WriteAllText(Path.Combine(pasteDirectory, pasteId + ".json"), JsonSerializer.Serialize(data));
return Results.Ok(new PasteLink(pasteId, $"{(request.IsHttps ? "https" : "http")}://{domain}/get/{pasteId}"));
})
.WithName("PasteJson")
.RequireAuthorization();
app.MapGet("/get/{id}", (string id) =>
{
id = CheckPasteId(id);
// Logic to retrieve the paste by id
var pasteFile = Path.Combine(pasteDirectory, id + ".json");
if (File.Exists(pasteFile))
{
return Results.Ok(JsonSerializer.Deserialize<PasteData>(File.ReadAllText(pasteFile)));
}
else
{
return Results.NotFound("Paste not found");
}
});
//.RequireRateLimiting();
app.Logger.LogInformation("Starting main http work...");
app.Run();
string CheckPasteId(string id)
{
return new string([.. id.Where(c => char.IsNumber(c) || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'))]);
}
public record PasteData(string Content, string Note);
public record PasteLink(string Name, string Link);