diff options
Diffstat (limited to 'src/server')
| -rw-r--r-- | src/server/Controllers/AccountController.cs | 63 | ||||
| -rw-r--r-- | src/server/Dough.csproj | 6 | ||||
| -rw-r--r-- | src/server/IdentityServer/Config.cs | 48 | ||||
| -rw-r--r-- | src/server/Models/Constants.cs | 21 | ||||
| -rw-r--r-- | src/server/Models/Database/User.cs | 1 | ||||
| -rw-r--r-- | src/server/Services/EmailService.cs | 7 | ||||
| -rw-r--r-- | src/server/Startup.cs | 45 |
7 files changed, 129 insertions, 62 deletions
diff --git a/src/server/Controllers/AccountController.cs b/src/server/Controllers/AccountController.cs index af1e9ac..fe7b7a2 100644 --- a/src/server/Controllers/AccountController.cs +++ b/src/server/Controllers/AccountController.cs @@ -1,69 +1,54 @@ using System; -using System.Collections.Generic; -using System.Security.Claims; using System.Threading.Tasks; -using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Dough.Models; using Dough.Models.Database; -using Dough.Models.Payloads; -using Dough.Models.Results; using Dough.Utilities; +using IdentityServer4.Services; namespace Dough.Controllers { + [AllowAnonymous] public class AccountController : BaseController { private readonly MainDbContext _context; + private readonly IIdentityServerInteractionService _identityServerInteractionService; - public AccountController(MainDbContext context) + public AccountController(MainDbContext context, + IIdentityServerInteractionService identityServerInteractionService) { _context = context; + _identityServerInteractionService = identityServerInteractionService; } + + // This is the default route for identityserver4 logins (https://identityserver4.readthedocs.io/en/latest/topics/signin.html#login-workflow) [HttpPost("login")] - public async Task<ActionResult> Login(LoginPayload payload) + public async Task<ActionResult> Login(string returnUrl) { - var user = _context.Users.SingleByNameOrDefault(payload.Username); - if (user == default) - return BadRequest(new ErrorResult("Ugyldig brukernavn eller passord", - "Verifiser at passord og brukernavn er riktig og prøv igjen")); - - if (!user.VerifyPassword(payload.Password)) - return BadRequest(new ErrorResult("Ugyldig brukernavn eller passord", - "Verifiser at passord og brukernavn er riktig")); - - var claims = new List<Claim> - { - new Claim(ClaimTypes.Name, user.Username), - new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()), - new Claim(ClaimTypes.AuthenticationInstant, DateTime.UtcNow.ToString("O")) - }; + if (returnUrl.IsMissing() || !_identityServerInteractionService.IsValidReturnUrl(returnUrl)) + return BadRequest("route parameter returnUrl is invalid"); - var claimsIdentity = new ClaimsIdentity(claims, Constants.AuthenticationScheme); - var claimsPrincipal = new ClaimsPrincipal(claimsIdentity); - var authenticationProperties = new AuthenticationProperties + Console.WriteLine("returnUrl: " + returnUrl); + var reqBody = await HttpContext.Request.ReadFormAsync(); + foreach (var formEl in reqBody) { - IsPersistent = false, - IssuedUtc = DateTime.UtcNow, - AllowRefresh = true, - ExpiresUtc = DateTime.UtcNow.AddDays(7), - }; - - await HttpContext.SignInAsync(Constants.AuthenticationScheme, - claimsPrincipal, - authenticationProperties); + Console.WriteLine(formEl.Key); + foreach (var value in formEl.Value) + Console.WriteLine(" - " + value); + } return Ok(); } - [HttpGet("logout")] - public async Task<ActionResult> Logout(string continueTo = default) + + [HttpGet("forgot")] + public async Task<ActionResult> ForgotPassword(string username) { - await HttpContext.SignOutAsync(Constants.AuthenticationScheme); - if (continueTo.IsPresent() && continueTo.IsValidUrl()) return Redirect(continueTo); + var user = _context.Users.SingleByNameOrDefault(username); + if (user == default) return Ok(); return Ok(); } @@ -74,4 +59,4 @@ namespace Dough.Controllers return Ok(LoggedInUser); } } -} +}
\ No newline at end of file diff --git a/src/server/Dough.csproj b/src/server/Dough.csproj index 65911ed..e54ff49 100644 --- a/src/server/Dough.csproj +++ b/src/server/Dough.csproj @@ -6,9 +6,15 @@ </PropertyGroup> <ItemGroup> <PackageReference Include="BCrypt.Net-Core" Version="1.6.0" /> + <PackageReference Include="IdentityServer4" Version="4.0.4" /> + <PackageReference Include="IdentityServer4.EntityFramework" Version="4.0.4" /> + <PackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore" Version="3.1.6" /> <PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="3.1.2" /> <PackageReference Include="Serilog.AspNetCore" Version="3.2.0" /> <PackageReference Include="Microsoft.EntityFrameworkCore" Version="3.1.6" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="3.1.6" /> </ItemGroup> + <ItemGroup> + <Folder Include="AppData" /> + </ItemGroup> </Project>
\ No newline at end of file diff --git a/src/server/IdentityServer/Config.cs b/src/server/IdentityServer/Config.cs new file mode 100644 index 0000000..41363f1 --- /dev/null +++ b/src/server/IdentityServer/Config.cs @@ -0,0 +1,48 @@ +using System.Collections.Generic; +using Dough.Models; +using IdentityServer4; +using IdentityServer4.Models; + +namespace Dough.IdentityServer +{ + public static class Config + { + private const string MainApiScopeName = "main_api"; + private const string BrowserClientId = "browser"; + + + public static IEnumerable<Client> Clients => new List<Client> + { + new Client + { + ClientId = BrowserClientId, + AllowedGrantTypes = GrantTypes.Code, + RequireClientSecret = false, + + RedirectUris = Constants.BrowserAppLoginRedirectUrls, + PostLogoutRedirectUris = Constants.BrowserAppLogoutRedirectUrls, + AllowedCorsOrigins = Constants.BrowserAppUrls, + + AllowedScopes = + { + IdentityServerConstants.StandardScopes.OpenId, + IdentityServerConstants.StandardScopes.Profile, + MainApiScopeName + } + } + }; + + public static IEnumerable<ApiScope> ApiScopes => + new List<ApiScope> + { + new ApiScope(MainApiScopeName) + }; + + public static IEnumerable<IdentityResource> IdentityResources => + new List<IdentityResource> + { + new IdentityResources.OpenId(), + new IdentityResources.Profile(), + }; + } +} diff --git a/src/server/Models/Constants.cs b/src/server/Models/Constants.cs index 759030a..3afaaad 100644 --- a/src/server/Models/Constants.cs +++ b/src/server/Models/Constants.cs @@ -1,7 +1,24 @@ +using System.Collections.Generic; + namespace Dough.Models { - public class Constants + public static class Constants { - public const string AuthenticationScheme = "Cookies"; + public static readonly string[] BrowserAppUrls = + { + "http://localhost:8080", + "http://localhost:3000", + }; + public static readonly string[] BrowserAppLoginRedirectUrls = + { + "http://localhost:8080/signin-oidc", + "http://localhost:3000/signin-oidc", + }; + public static readonly string[] BrowserAppLogoutRedirectUrls = + { + "http://localhost:8080/signout-callback-oidc", + "http://localhost:3000/signout-callback-oidc", + }; + } }
\ No newline at end of file diff --git a/src/server/Models/Database/User.cs b/src/server/Models/Database/User.cs index 479c15c..7d8bf1c 100644 --- a/src/server/Models/Database/User.cs +++ b/src/server/Models/Database/User.cs @@ -1,4 +1,5 @@ using System; +using Microsoft.AspNetCore.Identity; namespace Dough.Models.Database { diff --git a/src/server/Services/EmailService.cs b/src/server/Services/EmailService.cs new file mode 100644 index 0000000..0d70f0f --- /dev/null +++ b/src/server/Services/EmailService.cs @@ -0,0 +1,7 @@ +namespace Dough.Services +{ + public class EmailService + { + + } +}
\ No newline at end of file diff --git a/src/server/Startup.cs b/src/server/Startup.cs index 4f0d467..f55a761 100644 --- a/src/server/Startup.cs +++ b/src/server/Startup.cs @@ -1,4 +1,4 @@ -using Microsoft.AspNetCore.Authentication.Cookies;
+using Dough.IdentityServer;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.EntityFrameworkCore;
@@ -6,10 +6,9 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Dough.Models;
-using Dough.Utilities;
using Dough.Models.Database;
-using Microsoft.AspNetCore.CookiePolicy;
using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Mvc;
namespace Dough
{
@@ -21,7 +20,8 @@ namespace Dough }
public IConfiguration Configuration { get; }
- private const string MainCorsPolicy = "MainCorsPolicy";
+
+ private const string DefaultCorsPolicy = "DefaultCorsPolicy";
private string GetConnectionStringFromEnvironment()
{
@@ -38,33 +38,35 @@ namespace Dough services.AddCors(options =>
{
- options.AddPolicy(MainCorsPolicy, builder =>
+ options.AddPolicy(DefaultCorsPolicy, builder =>
{
builder
+ .WithOrigins(Constants.BrowserAppUrls)
.AllowAnyHeader()
.AllowAnyMethod()
- .AllowCredentials()
- .WithOrigins("http://localhost:8080");
+ .AllowCredentials();
});
});
+ services.AddHealthChecks()
+ .AddDbContextCheck<MainDbContext>();
+
services.AddDbContext<MainDbContext>(options => {
options.UseMySql(GetConnectionStringFromEnvironment());
});
+
+ services.Configure<ApiBehaviorOptions>(options =>
+ {
+ options.SuppressModelStateInvalidFilter = true;
+ options.SuppressInferBindingSourcesForParameters = true;
+ });
+ var builder = services.AddIdentityServer()
+ .AddInMemoryIdentityResources(Config.IdentityResources)
+ .AddInMemoryApiScopes(Config.ApiScopes)
+ .AddInMemoryClients(Config.Clients);
+
services.AddControllers();
-
- services.AddAuthentication(Constants.AuthenticationScheme)
- .AddCookie(Constants.AuthenticationScheme, options =>
- {
- options.Cookie.Name = "dough_session";
- options.Cookie.HttpOnly = true;
- options.Cookie.SameSite = SameSiteMode.Strict;
- options.Cookie.SecurePolicy = CookieSecurePolicy.SameAsRequest;
- options.LoginPath = "/api/account/login";
- options.SlidingExpiration = true;
- options.LogoutPath = "/api/account/logout";
- });
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
@@ -72,12 +74,13 @@ namespace Dough if (env.IsDevelopment())
app.UseDeveloperExceptionPage();
- app.UseCors(MainCorsPolicy);
app.UseRouting();
+ app.UseCors(DefaultCorsPolicy);
+ app.UseHealthChecks("/health");
app.UseStatusCodePages();
app.UseAuthentication();
app.UseAuthorization();
- app.UseEndpoints(endpoints => { endpoints.MapControllers(); });
+ app.UseEndpoints(endpoints => { endpoints.MapControllers().RequireAuthorization(); });
}
}
}
|
