Login Logik aktualisiert
This commit is contained in:
@@ -1,80 +1,39 @@
|
||||
using System.Security.Claims;
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
using Microsoft.AspNetCore.Authentication.Cookies;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Watcher.ViewModels;
|
||||
|
||||
namespace Watcher.Controllers;
|
||||
|
||||
public class AuthController : Controller
|
||||
{
|
||||
private readonly IConfiguration _config;
|
||||
|
||||
public AuthController(IConfiguration config)
|
||||
public IActionResult Login()
|
||||
{
|
||||
_config = config;
|
||||
return View();
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public IActionResult Login(string? returnUrl = null)
|
||||
public IActionResult SignIn()
|
||||
{
|
||||
var vm = new LoginViewModel { ReturnUrl = returnUrl };
|
||||
return View(vm);
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[ValidateAntiForgeryToken]
|
||||
public async Task<IActionResult> Login(LoginViewModel model)
|
||||
{
|
||||
if (!ModelState.IsValid)
|
||||
return View(model);
|
||||
|
||||
// Beispielhafte, harte lokale Benutzerprüfung
|
||||
if (model.Username == "admin" && model.Password == "password")
|
||||
{
|
||||
var claims = new List<Claim>
|
||||
{
|
||||
new Claim(ClaimTypes.Name, model.Username),
|
||||
new Claim(ClaimTypes.Role, "Admin")
|
||||
};
|
||||
|
||||
var identity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
|
||||
var principal = new ClaimsPrincipal(identity);
|
||||
|
||||
await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, principal);
|
||||
|
||||
return Redirect(model.ReturnUrl ?? "/");
|
||||
}
|
||||
|
||||
ModelState.AddModelError("", "Ungültiger Benutzername oder Passwort");
|
||||
return View(model);
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[ValidateAntiForgeryToken]
|
||||
public IActionResult SignIn(string? returnUrl = null)
|
||||
{
|
||||
var redirectUrl = Url.Action(nameof(ExternalLoginCallback), "Auth", new { returnUrl });
|
||||
return Challenge(new AuthenticationProperties
|
||||
{
|
||||
RedirectUri = redirectUrl
|
||||
RedirectUri = "/"
|
||||
}, "oidc");
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public IActionResult ExternalLoginCallback(string? returnUrl = null)
|
||||
{
|
||||
return Redirect(returnUrl ?? "/");
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[ValidateAntiForgeryToken]
|
||||
public async Task<IActionResult> Logout()
|
||||
[ValidateAntiForgeryToken]
|
||||
public async Task<IActionResult> Logout()
|
||||
{
|
||||
// Lokales Cookie löschen
|
||||
await HttpContext.SignOutAsync("Cookies");
|
||||
|
||||
// Externes OIDC-Logout initiieren
|
||||
await HttpContext.SignOutAsync("oidc", new AuthenticationProperties
|
||||
{
|
||||
await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
|
||||
return RedirectToAction("Index", "Home");
|
||||
}
|
||||
RedirectUri = "/" // Nach Logout zurück zur Startseite oder Login-Seite
|
||||
});
|
||||
|
||||
return RedirectToAction("Index", "Home");
|
||||
}
|
||||
|
||||
[Authorize]
|
||||
public IActionResult Info()
|
||||
|
@@ -55,67 +55,78 @@ builder.Services.AddDbContext<AppDbContext>((serviceProvider, options) =>
|
||||
builder.Services.AddAuthentication(options =>
|
||||
{
|
||||
options.DefaultScheme = "Cookies";
|
||||
options.DefaultChallengeScheme = "oidc";
|
||||
options.DefaultChallengeScheme = "Cookies"; // Nur wenn kein OIDC erzwungen wird
|
||||
})
|
||||
.AddCookie("Cookies")
|
||||
.AddOpenIdConnect("oidc", options =>
|
||||
.AddCookie("Cookies", options =>
|
||||
{
|
||||
var config = builder.Configuration.GetSection("Authentication:PocketID");
|
||||
options.Authority = config["Authority"];
|
||||
options.ClientId = config["ClientId"];
|
||||
options.ClientSecret = config["ClientSecret"];
|
||||
options.ResponseType = "code";
|
||||
options.CallbackPath = config["CallbackPath"];
|
||||
options.SaveTokens = true;
|
||||
|
||||
options.GetClaimsFromUserInfoEndpoint = true;
|
||||
|
||||
options.Scope.Clear();
|
||||
options.Scope.Add("openid");
|
||||
options.Scope.Add("profile");
|
||||
options.Scope.Add("email");
|
||||
|
||||
options.Events = new OpenIdConnectEvents
|
||||
{
|
||||
OnTokenValidated = async ctx =>
|
||||
{
|
||||
var db = ctx.HttpContext.RequestServices.GetRequiredService<AppDbContext>();
|
||||
|
||||
var principal = ctx.Principal;
|
||||
var pocketId = principal.FindFirst("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier")?.Value;
|
||||
var preferredUsername = principal.FindFirst("preferred_username")?.Value;
|
||||
var email = principal.FindFirst("email")?.Value;
|
||||
|
||||
if (string.IsNullOrEmpty(pocketId))
|
||||
return;
|
||||
|
||||
var user = await db.Users.FirstOrDefaultAsync(u => u.PocketId == pocketId);
|
||||
|
||||
if (user == null)
|
||||
{
|
||||
user = new User
|
||||
{
|
||||
PocketId = pocketId,
|
||||
PreferredUsername = preferredUsername ?? "",
|
||||
Email = email,
|
||||
LastLogin = DateTime.UtcNow
|
||||
};
|
||||
db.Users.Add(user);
|
||||
}
|
||||
else
|
||||
{
|
||||
user.LastLogin = DateTime.UtcNow;
|
||||
user.PreferredUsername = preferredUsername ?? user.PreferredUsername;
|
||||
user.Email = email ?? user.Email;
|
||||
db.Users.Update(user);
|
||||
}
|
||||
|
||||
await db.SaveChangesAsync();
|
||||
}
|
||||
};
|
||||
|
||||
options.LoginPath = "/Account/Login"; // Falls eigene Login-Seite
|
||||
});
|
||||
|
||||
// PocketID nur konfigurieren, wenn aktiviert
|
||||
var pocketIdSection = builder.Configuration.GetSection("Authentication:PocketID");
|
||||
var pocketIdEnabled = pocketIdSection.GetValue<bool>("Enabled");
|
||||
|
||||
if (pocketIdEnabled)
|
||||
{
|
||||
builder.Services.AddAuthentication()
|
||||
.AddOpenIdConnect("oidc", options =>
|
||||
{
|
||||
options.Authority = pocketIdSection["Authority"];
|
||||
options.ClientId = pocketIdSection["ClientId"];
|
||||
options.ClientSecret = pocketIdSection["ClientSecret"];
|
||||
options.ResponseType = "code";
|
||||
options.CallbackPath = pocketIdSection["CallbackPath"];
|
||||
options.SaveTokens = true;
|
||||
|
||||
options.GetClaimsFromUserInfoEndpoint = true;
|
||||
|
||||
options.Scope.Clear();
|
||||
options.Scope.Add("openid");
|
||||
options.Scope.Add("profile");
|
||||
options.Scope.Add("email");
|
||||
|
||||
options.Events = new OpenIdConnectEvents
|
||||
{
|
||||
OnTokenValidated = async ctx =>
|
||||
{
|
||||
var db = ctx.HttpContext.RequestServices.GetRequiredService<AppDbContext>();
|
||||
|
||||
var principal = ctx.Principal;
|
||||
var pocketId = principal.FindFirst("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier")?.Value;
|
||||
var preferredUsername = principal.FindFirst("preferred_username")?.Value;
|
||||
var email = principal.FindFirst("email")?.Value;
|
||||
|
||||
if (string.IsNullOrEmpty(pocketId))
|
||||
return;
|
||||
|
||||
var user = await db.Users.FirstOrDefaultAsync(u => u.PocketId == pocketId);
|
||||
|
||||
if (user == null)
|
||||
{
|
||||
user = new User
|
||||
{
|
||||
PocketId = pocketId,
|
||||
PreferredUsername = preferredUsername ?? "",
|
||||
Email = email,
|
||||
LastLogin = DateTime.UtcNow
|
||||
};
|
||||
db.Users.Add(user);
|
||||
}
|
||||
else
|
||||
{
|
||||
user.LastLogin = DateTime.UtcNow;
|
||||
user.PreferredUsername = preferredUsername ?? user.PreferredUsername;
|
||||
user.Email = email ?? user.Email;
|
||||
db.Users.Update(user);
|
||||
}
|
||||
|
||||
await db.SaveChangesAsync();
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
@@ -145,7 +156,7 @@ app.UseStaticFiles();
|
||||
|
||||
app.MapControllerRoute(
|
||||
name: "default",
|
||||
pattern: "{controller=Home}/{action=Index}/{id?}"
|
||||
pattern: "{controller=Auth}/{action=Login}/"
|
||||
);
|
||||
|
||||
|
||||
|
@@ -1,36 +1,28 @@
|
||||
@model Watcher.ViewModels.LoginViewModel
|
||||
|
||||
@{
|
||||
ViewData["Title"] = "Login";
|
||||
}
|
||||
|
||||
<h2>Anmelden</h2>
|
||||
<div class="login-container">
|
||||
<h2>Login</h2>
|
||||
|
||||
<form asp-action="Login" method="post">
|
||||
<div class="form-group">
|
||||
<label asp-for="Username"></label>
|
||||
<input asp-for="Username" class="form-control" />
|
||||
<span asp-validation-for="Username" class="text-danger"></span>
|
||||
</div>
|
||||
<form asp-action="Login" method="post">
|
||||
<div>
|
||||
<label asp-for="Username"></label>
|
||||
<input asp-for="Username" />
|
||||
<span asp-validation-for="Username"></span>
|
||||
</div>
|
||||
<div>
|
||||
<label asp-for="Password"></label>
|
||||
<input asp-for="Password" type="password" />
|
||||
<span asp-validation-for="Password"></span>
|
||||
</div>
|
||||
<button type="submit">Login</button>
|
||||
</form>
|
||||
|
||||
<div class="form-group">
|
||||
<label asp-for="Password"></label>
|
||||
<input asp-for="Password" class="form-control" type="password" />
|
||||
<span asp-validation-for="Password" class="text-danger"></span>
|
||||
</div>
|
||||
<hr />
|
||||
|
||||
<input type="hidden" asp-for="ReturnUrl" />
|
||||
|
||||
<button type="submit" class="btn btn-primary">Anmelden</button>
|
||||
</form>
|
||||
|
||||
<hr />
|
||||
|
||||
<form asp-action="LoginWithOidc" method="post">
|
||||
<input type="hidden" name="returnUrl" value="@Model.ReturnUrl" />
|
||||
<button type="submit" class="btn btn-outline-secondary">Mit PocketID anmelden</button>
|
||||
</form>
|
||||
|
||||
@section Scripts {
|
||||
<partial name="_ValidationScriptsPartial" />
|
||||
}
|
||||
<form asp-controller="Auth" asp-action="SignIn" method="get">
|
||||
<button type="submit">Mit PocketID anmelden</button>
|
||||
</form>
|
||||
</div>
|
||||
|
@@ -62,10 +62,10 @@
|
||||
<h4>Watcher</h4>
|
||||
<ul class="nav flex-column">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/">Dashboard</a>
|
||||
<a class="nav-link" href="/Home/Index">Dashboard</a>
|
||||
</li>
|
||||
<li class="nav-item"></li>
|
||||
<a class="nav-link" href="/Uptime">Uptime</a>
|
||||
<a class="nav-link" href="/Uptime/Overview">Uptime</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/Server/Overview">Servers</a>
|
||||
|
@@ -18,6 +18,7 @@
|
||||
|
||||
"Authentication": {
|
||||
"UseLocal": true,
|
||||
"PocketIDEnabled": true,
|
||||
"PocketID": {
|
||||
"Authority": "https://pocketid.triggermeelmo.com",
|
||||
"ClientId": "629a5f42-ab02-4905-8311-cc7b64165cc0",
|
||||
|
Reference in New Issue
Block a user