commit 572ec9b0338454b1ff72e9824ff743dbf62bdcf3 Author: HiveBeats Date: Sat Oct 12 23:50:49 2024 +0700 feat: cookies diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..add57be --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +bin/ +obj/ +/packages/ +riderModule.iml +/_ReSharper.Caches/ \ No newline at end of file diff --git a/.idea/.idea.Auths/.idea/.gitignore b/.idea/.idea.Auths/.idea/.gitignore new file mode 100644 index 0000000..fbd2fc4 --- /dev/null +++ b/.idea/.idea.Auths/.idea/.gitignore @@ -0,0 +1,13 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Rider ignored files +/modules.xml +/contentModel.xml +/projectSettingsUpdater.xml +/.idea.Auths.iml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/.idea.Auths/.idea/encodings.xml b/.idea/.idea.Auths/.idea/encodings.xml new file mode 100644 index 0000000..df87cf9 --- /dev/null +++ b/.idea/.idea.Auths/.idea/encodings.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/.idea/.idea.Auths/.idea/indexLayout.xml b/.idea/.idea.Auths/.idea/indexLayout.xml new file mode 100644 index 0000000..7b08163 --- /dev/null +++ b/.idea/.idea.Auths/.idea/indexLayout.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/.idea.Auths/.idea/vcs.xml b/.idea/.idea.Auths/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/.idea.Auths/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Auths.sln b/Auths.sln new file mode 100644 index 0000000..e6a3afd --- /dev/null +++ b/Auths.sln @@ -0,0 +1,28 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Auths", "Auths\Auths.csproj", "{72E18756-5750-453E-B022-73EB71741490}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Cookie.Basic", "Cookie.Basic\Cookie.Basic.csproj", "{3684B6DC-9301-496C-9832-FFC26084C496}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Cookie.BuiltIn", "Cookie.BuiltIn\Cookie.BuiltIn.csproj", "{63CE5DC9-F976-430B-8B12-50FB3DA3F872}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {72E18756-5750-453E-B022-73EB71741490}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {72E18756-5750-453E-B022-73EB71741490}.Debug|Any CPU.Build.0 = Debug|Any CPU + {72E18756-5750-453E-B022-73EB71741490}.Release|Any CPU.ActiveCfg = Release|Any CPU + {72E18756-5750-453E-B022-73EB71741490}.Release|Any CPU.Build.0 = Release|Any CPU + {3684B6DC-9301-496C-9832-FFC26084C496}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3684B6DC-9301-496C-9832-FFC26084C496}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3684B6DC-9301-496C-9832-FFC26084C496}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3684B6DC-9301-496C-9832-FFC26084C496}.Release|Any CPU.Build.0 = Release|Any CPU + {63CE5DC9-F976-430B-8B12-50FB3DA3F872}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {63CE5DC9-F976-430B-8B12-50FB3DA3F872}.Debug|Any CPU.Build.0 = Debug|Any CPU + {63CE5DC9-F976-430B-8B12-50FB3DA3F872}.Release|Any CPU.ActiveCfg = Release|Any CPU + {63CE5DC9-F976-430B-8B12-50FB3DA3F872}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection +EndGlobal diff --git a/Auths/Auths.csproj b/Auths/Auths.csproj new file mode 100644 index 0000000..2f4fc77 --- /dev/null +++ b/Auths/Auths.csproj @@ -0,0 +1,10 @@ + + + + Exe + net8.0 + enable + enable + + + diff --git a/Auths/Program.cs b/Auths/Program.cs new file mode 100644 index 0000000..e5dff12 --- /dev/null +++ b/Auths/Program.cs @@ -0,0 +1,3 @@ +// See https://aka.ms/new-console-template for more information + +Console.WriteLine("Hello, World!"); \ No newline at end of file diff --git a/Cookie.Basic/Cookie.Basic.csproj b/Cookie.Basic/Cookie.Basic.csproj new file mode 100644 index 0000000..48e39a5 --- /dev/null +++ b/Cookie.Basic/Cookie.Basic.csproj @@ -0,0 +1,14 @@ + + + + net8.0 + enable + enable + + + + + + + + diff --git a/Cookie.Basic/Cookie.Basic.http b/Cookie.Basic/Cookie.Basic.http new file mode 100644 index 0000000..d1e0a97 --- /dev/null +++ b/Cookie.Basic/Cookie.Basic.http @@ -0,0 +1,6 @@ +@Cookie.Basic_HostAddress = http://localhost:5163 + +GET {{Cookie.Basic_HostAddress}}/weatherforecast/ +Accept: application/json + +### diff --git a/Cookie.Basic/Program.cs b/Cookie.Basic/Program.cs new file mode 100644 index 0000000..2a2b993 --- /dev/null +++ b/Cookie.Basic/Program.cs @@ -0,0 +1,174 @@ +using System.Net; +using System.Security.Claims; +using Microsoft.AspNetCore.DataProtection; +using Microsoft.AspNetCore.Mvc; + +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(); + +var app = builder.Build(); + +// Configure the HTTP request pipeline. +if (app.Environment.IsDevelopment()) +{ + app.UseSwagger(); + app.UseSwaggerUI(); +} + +app.UseHttpsRedirection(); + +#region Basic + +const string AuthCookie = "auth"; + +app.MapGet("/secured-method", (HttpContext ctx) => +{ + // authentication + if (ctx.Request.Cookies.ContainsKey(AuthCookie)) + { + var cookie = ctx.Request.Cookies[AuthCookie]; + var parts = cookie!.Split("&").ToList(); + var entityType = parts[1].Split(":")[1]; + + // authorization + if (entityType == "admin") + { + return "secured message"; + } + else if (entityType == "user") + { + return "common message"; + } + } + + ctx.Response.StatusCode = StatusCodes.Status401Unauthorized; + return "Unauthorized"; +}); + +app.MapGet("/login-admin", (HttpContext ctx) => +{ + var cookie = "user:ivan&type:admin"; + ctx.Response.Headers["set-cookie"] = $"{AuthCookie}={cookie}"; +}); + +app.MapGet("/login-user", (HttpContext ctx) => +{ + var cookie = "user:danil&type:user"; + ctx.Response.Headers["set-cookie"] = $"{AuthCookie}={cookie}"; +}); + +#endregion + +#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 + + +app.MapGet("/login-user-protected", (HttpContext ctx, [FromServices] IDataProtectionProvider protector) => +{ + var dp = protector.CreateProtector(DataProtectorName); + var cookieProtected = dp.Protect("user:danil&type:user"); + ctx.Response.Headers["set-cookie"] = $"{AuthCookie}={cookieProtected}"; +}); + +app.MapGet("/secured-method-protected", (HttpContext ctx, [FromServices] IDataProtectionProvider protector) => +{ + 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]; + + // authorization + if (entityType == "admin") + { + return "secured message"; + } + else if (entityType == "user") + { + return "common message"; + } + } + + ctx.Response.StatusCode = StatusCodes.Status401Unauthorized; + return "Unauthorized"; +}); + +#endregion + +#region Claims + +//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.MapGet("/login-user-claims", (HttpContext ctx, [FromServices] IDataProtectionProvider protector) => +{ + var dp = protector.CreateProtector(DataProtectorName); + var cookieProtected = dp.Protect("user:danil&type:user"); + ctx.Response.Headers["set-cookie"] = $"{AuthCookie}={cookieProtected}"; +}); + +app.MapGet("/secured-method-claims", (HttpContext ctx, [FromServices] IDataProtectionProvider protector) => +{ + var user = ctx.User; + + if (user.FindFirst("Type")?.Value == "admin") + { + return "secured message"; + } + else if (user.FindFirst("Type")?.Value == "user") + { + return "common message"; + } + + return null; +}); + +#endregion + + +app.Run(); \ No newline at end of file diff --git a/Cookie.Basic/Properties/launchSettings.json b/Cookie.Basic/Properties/launchSettings.json new file mode 100644 index 0000000..6a8edba --- /dev/null +++ b/Cookie.Basic/Properties/launchSettings.json @@ -0,0 +1,41 @@ +{ + "$schema": "http://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:47194", + "sslPort": 44336 + } + }, + "profiles": { + "http": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "swagger", + "applicationUrl": "http://localhost:5163", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "https": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "swagger", + "applicationUrl": "https://localhost:7254;http://localhost:5163", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/Cookie.Basic/appsettings.Development.json b/Cookie.Basic/appsettings.Development.json new file mode 100644 index 0000000..0c208ae --- /dev/null +++ b/Cookie.Basic/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/Cookie.Basic/appsettings.json b/Cookie.Basic/appsettings.json new file mode 100644 index 0000000..10f68b8 --- /dev/null +++ b/Cookie.Basic/appsettings.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*" +} diff --git a/Cookie.BuiltIn/Cookie.BuiltIn.csproj b/Cookie.BuiltIn/Cookie.BuiltIn.csproj new file mode 100644 index 0000000..48e39a5 --- /dev/null +++ b/Cookie.BuiltIn/Cookie.BuiltIn.csproj @@ -0,0 +1,14 @@ + + + + net8.0 + enable + enable + + + + + + + + diff --git a/Cookie.BuiltIn/Cookie.BuiltIn.http b/Cookie.BuiltIn/Cookie.BuiltIn.http new file mode 100644 index 0000000..9b8c9e0 --- /dev/null +++ b/Cookie.BuiltIn/Cookie.BuiltIn.http @@ -0,0 +1,6 @@ +@Cookie.BuiltIn_HostAddress = http://localhost:5209 + +GET {{Cookie.BuiltIn_HostAddress}}/weatherforecast/ +Accept: application/json + +### diff --git a/Cookie.BuiltIn/Program.cs b/Cookie.BuiltIn/Program.cs new file mode 100644 index 0000000..7609209 --- /dev/null +++ b/Cookie.BuiltIn/Program.cs @@ -0,0 +1,53 @@ +using System.Security.Claims; +using Microsoft.AspNetCore.Authentication; +using Microsoft.AspNetCore.Authentication.Cookies; +using Microsoft.AspNetCore.Authorization; + +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(CookieAuthenticationDefaults.AuthenticationScheme) + .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options => + { + options.LoginPath = "/login"; + }); +// 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(); +app.MapGet("/secured-method", /*[Authorize]*/ (HttpContext ctx) => +{ + var user = ctx.User?.FindFirst("Name"); + if (user == null) + ctx.Response.StatusCode = StatusCodes.Status401Unauthorized; + + return user?.Value ?? "Unauthorized"; +}); + +app.MapGet("/login", async (HttpContext ctx) => +{ + var claims = new List(); + claims.Add(new Claim("Type", "admin")); + claims.Add(new Claim("Name", "ivan")); + + var identity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme); + var user = new ClaimsPrincipal(identity); + + await ctx.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, user); + return "Ok"; +}); + +app.Run(); \ No newline at end of file diff --git a/Cookie.BuiltIn/Properties/launchSettings.json b/Cookie.BuiltIn/Properties/launchSettings.json new file mode 100644 index 0000000..e898fce --- /dev/null +++ b/Cookie.BuiltIn/Properties/launchSettings.json @@ -0,0 +1,41 @@ +{ + "$schema": "http://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:60915", + "sslPort": 44335 + } + }, + "profiles": { + "http": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "swagger", + "applicationUrl": "http://localhost:5209", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "https": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "swagger", + "applicationUrl": "https://localhost:7089;http://localhost:5209", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/Cookie.BuiltIn/appsettings.Development.json b/Cookie.BuiltIn/appsettings.Development.json new file mode 100644 index 0000000..0c208ae --- /dev/null +++ b/Cookie.BuiltIn/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/Cookie.BuiltIn/appsettings.json b/Cookie.BuiltIn/appsettings.json new file mode 100644 index 0000000..10f68b8 --- /dev/null +++ b/Cookie.BuiltIn/appsettings.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*" +}