diff --git a/Auths.sln b/Auths.sln index 02b112d..90c565c 100644 --- a/Auths.sln +++ b/Auths.sln @@ -16,6 +16,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RsaKeyLoader", "RsaKeyLoade EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jwt.Application", "Jwt.Application\Jwt.Application.csproj", "{E1DC6422-489C-424C-BC3A-3844599B43C9}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "OAuth", "OAuth", "{DF15C7CD-6348-49E9-8FEB-ACA68F530044}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OAuth.Authentik", "OAuth.Authentik\OAuth.Authentik.csproj", "{1996966F-793B-4FFD-8664-E73690350FDE}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -46,6 +50,10 @@ Global {E1DC6422-489C-424C-BC3A-3844599B43C9}.Debug|Any CPU.Build.0 = Debug|Any CPU {E1DC6422-489C-424C-BC3A-3844599B43C9}.Release|Any CPU.ActiveCfg = Release|Any CPU {E1DC6422-489C-424C-BC3A-3844599B43C9}.Release|Any CPU.Build.0 = Release|Any CPU + {1996966F-793B-4FFD-8664-E73690350FDE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1996966F-793B-4FFD-8664-E73690350FDE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1996966F-793B-4FFD-8664-E73690350FDE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1996966F-793B-4FFD-8664-E73690350FDE}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(NestedProjects) = preSolution {3684B6DC-9301-496C-9832-FFC26084C496} = {A7B682CD-CF61-4684-977B-82E48A4051D8} @@ -53,5 +61,6 @@ Global {BAD4810F-B60A-42F1-8176-649855B93794} = {29AFF1AF-FE18-491A-AFE1-CE2786187166} {579C8783-7E95-40F3-96F4-BEBFB40F2D38} = {29AFF1AF-FE18-491A-AFE1-CE2786187166} {E1DC6422-489C-424C-BC3A-3844599B43C9} = {29AFF1AF-FE18-491A-AFE1-CE2786187166} + {1996966F-793B-4FFD-8664-E73690350FDE} = {DF15C7CD-6348-49E9-8FEB-ACA68F530044} EndGlobalSection EndGlobal diff --git a/Cookie.Basic/Program.cs b/Cookie.Basic/Program.cs index 2a2b993..12e8306 100644 --- a/Cookie.Basic/Program.cs +++ b/Cookie.Basic/Program.cs @@ -9,7 +9,7 @@ var builder = WebApplication.CreateBuilder(args); // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); - +builder.Services.AddDataProtection(); var app = builder.Build(); // Configure the HTTP request pipeline. @@ -65,7 +65,7 @@ app.MapGet("/login-user", (HttpContext ctx) => #region Secured //todo: add to services -//builder.Services.AddDataProtection(); + const string DataProtectorName = "cookie-protector"; // https://learn.microsoft.com/ru-ru/dotnet/api/microsoft.aspnetcore.dataprotection.idataprotector?view=aspnetcore-8.0 @@ -113,37 +113,37 @@ app.MapGet("/secured-method-protected", (HttpContext ctx, [FromServices] IDataPr //todo: uncomment // -// app.Use((ctx,next) => -// { -// var protector = ctx.RequestServices.GetService(); -// var dp = protector.CreateProtector(DataProtectorName); -// -// // authentication -// if (ctx.Request.Cookies.ContainsKey(AuthCookie)) -// { -// var cookie = ctx.Request.Cookies[AuthCookie]!; -// -// var cookieUnprotected = dp.Unprotect(cookie); -// -// var parts = cookieUnprotected.Split("&").ToList(); -// var entityType = parts[1].Split(":")[1]; -// var entityName = parts[0].Split(":")[1]; -// -// // authorization -// var claims = new List(); -// claims.Add(new Claim("Type", entityType)); -// claims.Add(new Claim("Name", entityName)); -// -// var identity = new ClaimsIdentity(claims); -// var user = new ClaimsPrincipal(identity); -// ctx.User = user; -// -// return next(); -// } -// -// ctx.Response.StatusCode = StatusCodes.Status401Unauthorized; -// return Task.CompletedTask; -// }); +app.Use((ctx,next) => +{ + var protector = ctx.RequestServices.GetService(); + var dp = protector.CreateProtector(DataProtectorName); + + // authentication + if (ctx.Request.Cookies.ContainsKey(AuthCookie)) + { + var cookie = ctx.Request.Cookies[AuthCookie]!; + + var cookieUnprotected = dp.Unprotect(cookie); + + var parts = cookieUnprotected.Split("&").ToList(); + var entityType = parts[1].Split(":")[1]; + var entityName = parts[0].Split(":")[1]; + + // authorization + var claims = new List(); + claims.Add(new Claim("Type", entityType)); + claims.Add(new Claim("Name", entityName)); + + var identity = new ClaimsIdentity(claims); + var user = new ClaimsPrincipal(identity); + ctx.User = user; + + return next(); + } + + ctx.Response.StatusCode = StatusCodes.Status401Unauthorized; + return Task.CompletedTask; +}); app.MapGet("/login-user-claims", (HttpContext ctx, [FromServices] IDataProtectionProvider protector) => { diff --git a/Cookie.Basic/Properties/launchSettings.json b/Cookie.Basic/Properties/launchSettings.json index 6a8edba..7cd8b00 100644 --- a/Cookie.Basic/Properties/launchSettings.json +++ b/Cookie.Basic/Properties/launchSettings.json @@ -12,8 +12,7 @@ "http": { "commandName": "Project", "dotnetRunMessages": true, - "launchBrowser": true, - "launchUrl": "swagger", + "applicationUrl": "http://localhost:5163", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" @@ -22,8 +21,7 @@ "https": { "commandName": "Project", "dotnetRunMessages": true, - "launchBrowser": true, - "launchUrl": "swagger", + "applicationUrl": "https://localhost:7254;http://localhost:5163", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" diff --git a/Cookie.BuiltIn/Program.cs b/Cookie.BuiltIn/Program.cs index 7609209..caae517 100644 --- a/Cookie.BuiltIn/Program.cs +++ b/Cookie.BuiltIn/Program.cs @@ -12,9 +12,10 @@ builder.Services.AddSwaggerGen(); builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme) .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options => { - options.LoginPath = "/login"; + //options.Events + //options.LoginPath = "/login"; }); -// builder.Services.AddAuthorization(); +builder.Services.AddAuthorization(); var app = builder.Build(); @@ -27,8 +28,9 @@ if (app.Environment.IsDevelopment()) app.UseHttpsRedirection(); app.UseAuthentication(); -// app.UseAuthorization(); -app.MapGet("/secured-method", /*[Authorize]*/ (HttpContext ctx) => +app.UseAuthorization(); + +app.MapGet("/secured-method", [Authorize] (HttpContext ctx) => { var user = ctx.User?.FindFirst("Name"); if (user == null) diff --git a/Cookie.BuiltIn/Properties/launchSettings.json b/Cookie.BuiltIn/Properties/launchSettings.json index e898fce..c1b3221 100644 --- a/Cookie.BuiltIn/Properties/launchSettings.json +++ b/Cookie.BuiltIn/Properties/launchSettings.json @@ -12,8 +12,6 @@ "http": { "commandName": "Project", "dotnetRunMessages": true, - "launchBrowser": true, - "launchUrl": "swagger", "applicationUrl": "http://localhost:5209", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" @@ -22,8 +20,6 @@ "https": { "commandName": "Project", "dotnetRunMessages": true, - "launchBrowser": true, - "launchUrl": "swagger", "applicationUrl": "https://localhost:7089;http://localhost:5209", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" diff --git a/Jwt.Application/Properties/launchSettings.json b/Jwt.Application/Properties/launchSettings.json index bb99045..10983d8 100644 --- a/Jwt.Application/Properties/launchSettings.json +++ b/Jwt.Application/Properties/launchSettings.json @@ -12,8 +12,7 @@ "http": { "commandName": "Project", "dotnetRunMessages": true, - "launchBrowser": true, - "launchUrl": "swagger", + "applicationUrl": "http://localhost:7001", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" @@ -22,8 +21,7 @@ "https": { "commandName": "Project", "dotnetRunMessages": true, - "launchBrowser": true, - "launchUrl": "swagger", + "applicationUrl": "https://localhost:7000;http://localhost:7001", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" diff --git a/Jwt.Server/Program.cs b/Jwt.Server/Program.cs index 965eefc..56f92c6 100644 --- a/Jwt.Server/Program.cs +++ b/Jwt.Server/Program.cs @@ -41,18 +41,18 @@ builder.Services.AddAuthentication() } }; - // b.Events = new JwtBearerEvents() - // { - // OnMessageReceived = (ctx) => - // { - // if (ctx.Request.Query.ContainsKey("token")) - // { - // ctx.Token = ctx.Request.Query["token"]; - // } - // - // return Task.CompletedTask; - // } - // }; + b.Events = new JwtBearerEvents() + { + OnMessageReceived = (ctx) => + { + if (ctx.Request.Query.ContainsKey("token")) + { + ctx.Token = ctx.Request.Query["token"]; + } + + return Task.CompletedTask; + } + }; }); builder.Services.AddAuthorization(); diff --git a/Jwt.Server/Properties/launchSettings.json b/Jwt.Server/Properties/launchSettings.json index 7fb8b23..dd7f31c 100644 --- a/Jwt.Server/Properties/launchSettings.json +++ b/Jwt.Server/Properties/launchSettings.json @@ -12,8 +12,7 @@ "http": { "commandName": "Project", "dotnetRunMessages": true, - "launchBrowser": true, - "launchUrl": "swagger", + "applicationUrl": "http://localhost:5001", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" @@ -22,8 +21,7 @@ "https": { "commandName": "Project", "dotnetRunMessages": true, - "launchBrowser": true, - "launchUrl": "swagger", + "applicationUrl": "https://localhost:5000;http://localhost:5001", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" diff --git a/OAuth.Authentik/OAuth.Authentik.csproj b/OAuth.Authentik/OAuth.Authentik.csproj new file mode 100644 index 0000000..36d8999 --- /dev/null +++ b/OAuth.Authentik/OAuth.Authentik.csproj @@ -0,0 +1,16 @@ + + + + net8.0 + enable + enable + + + + + + + + + + diff --git a/OAuth.Authentik/OAuth.Authentik.http b/OAuth.Authentik/OAuth.Authentik.http new file mode 100644 index 0000000..f22a9e0 --- /dev/null +++ b/OAuth.Authentik/OAuth.Authentik.http @@ -0,0 +1,6 @@ +@OAuth.Authentik_HostAddress = http://localhost:5127 + +GET {{OAuth.Authentik_HostAddress}}/weatherforecast/ +Accept: application/json + +### diff --git a/OAuth.Authentik/Program.cs b/OAuth.Authentik/Program.cs new file mode 100644 index 0000000..630092c --- /dev/null +++ b/OAuth.Authentik/Program.cs @@ -0,0 +1,90 @@ +using Microsoft.AspNetCore.Authentication.Cookies; + +var builder = WebApplication.CreateBuilder(args); + +// Add services to the container. +// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle +builder.Services.AddEndpointsApiExplorer(); +builder.Services.AddSwaggerGen(); +builder.Services.AddAuthentication(options => + { + options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme; + options.DefaultChallengeScheme = "oidc"; + }) + .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme) + .AddOpenIdConnect("oidc", options => + { + options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme; + + + + options.Authority = "https://oauth.e1lama.ru/application/o/asp_net"; + options.ClientId = ""; + // Securely store and load this value + options.ClientSecret = ""; + options.ResponseType = "code"; + options.SaveTokens = true; + + options.Scope.Add("openid"); + options.Scope.Add("profile"); + options.Scope.Add("email"); + + options.GetClaimsFromUserInfoEndpoint = true; + + options.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters + { + NameClaimType = "name" + }; + + // Optionally handle events + options.Events = new Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectEvents + { + OnAuthenticationFailed = context => + { + // Log or handle authentication failures + return Task.CompletedTask; + }, + OnTokenValidated = context => + { + // Additional token validation can go here + return Task.CompletedTask; + } + }; + }); +builder.Services.AddAuthorization(); + +var app = builder.Build(); + +// Configure the HTTP request pipeline. +if (app.Environment.IsDevelopment()) +{ + app.UseSwagger(); + app.UseSwaggerUI(); +} + +app.UseHttpsRedirection(); +app.UseAuthentication(); +app.UseAuthorization(); + +var summaries = new[] +{ + "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" +}; + +app.MapGet("/me", (HttpContext ctx) => + { + return ctx.User.Claims.Select(x => (x.Type, x.Value)); + }) + .RequireAuthorization() + .WithOpenApi(); + +app.MapGet("/login", () => +{ + return Results.Challenge(authenticationSchemes: new List(){"oidc"}); +}); +app.Run(); + +record WeatherForecast(DateOnly Date, int TemperatureC, string? Summary) +{ + public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); +} \ No newline at end of file diff --git a/OAuth.Authentik/Properties/launchSettings.json b/OAuth.Authentik/Properties/launchSettings.json new file mode 100644 index 0000000..08c524f --- /dev/null +++ b/OAuth.Authentik/Properties/launchSettings.json @@ -0,0 +1,39 @@ +{ + "$schema": "http://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:46291", + "sslPort": 44372 + } + }, + "profiles": { + "http": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "swagger", + "applicationUrl": "http://localhost:5001", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "https": { + "commandName": "Project", + "dotnetRunMessages": true, + "applicationUrl": "https://localhost:5000;http://localhost:5001", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/OAuth.Authentik/appsettings.Development.json b/OAuth.Authentik/appsettings.Development.json new file mode 100644 index 0000000..0c208ae --- /dev/null +++ b/OAuth.Authentik/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/OAuth.Authentik/appsettings.json b/OAuth.Authentik/appsettings.json new file mode 100644 index 0000000..10f68b8 --- /dev/null +++ b/OAuth.Authentik/appsettings.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*" +}