aboutsummaryrefslogtreecommitdiffstats
path: root/src/server
diff options
context:
space:
mode:
authorivarlovlie <git@ivarlovlie.no>2020-08-06 23:28:30 +0200
committerivarlovlie <git@ivarlovlie.no>2020-08-06 23:28:30 +0200
commitd7b5f8b7775a7c623d4bcfa7015476f835aabfa2 (patch)
tree72c1daf1a0b66765c16217c416173310dd73c214 /src/server
parent0cdb0b7ee3cd80ddb089344e80be2c4b46d75364 (diff)
downloaddough-d7b5f8b7775a7c623d4bcfa7015476f835aabfa2.tar.xz
dough-d7b5f8b7775a7c623d4bcfa7015476f835aabfa2.zip
server: start of ids4 impl
Diffstat (limited to 'src/server')
-rw-r--r--src/server/Controllers/AccountController.cs63
-rw-r--r--src/server/Dough.csproj6
-rw-r--r--src/server/IdentityServer/Config.cs48
-rw-r--r--src/server/Models/Constants.cs21
-rw-r--r--src/server/Models/Database/User.cs1
-rw-r--r--src/server/Services/EmailService.cs7
-rw-r--r--src/server/Startup.cs45
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(); });
}
}
}