|
|
@ -0,0 +1,113 @@ |
|
|
|
using Microsoft.AspNetCore.Authentication; |
|
|
|
using Microsoft.AspNetCore.Components.Authorization; |
|
|
|
using Microsoft.AspNetCore.Http.Extensions; |
|
|
|
using Microsoft.AspNetCore.Identity; |
|
|
|
using Microsoft.AspNetCore.Mvc; |
|
|
|
using Microsoft.Extensions.Primitives; |
|
|
|
using System.Security.Claims; |
|
|
|
using System.Text.Json; |
|
|
|
using TestBlazorApp.Components.Account.Pages; |
|
|
|
using TestBlazorApp.Components.Account.Pages.Manage; |
|
|
|
using TestBlazorApp.Data; |
|
|
|
|
|
|
|
namespace Microsoft.AspNetCore.Routing |
|
|
|
{ |
|
|
|
internal static class IdentityComponentsEndpointRouteBuilderExtensions |
|
|
|
{ |
|
|
|
// These endpoints are required by the Identity Razor components defined in the /Components/Account/Pages directory of this project.
|
|
|
|
public static IEndpointConventionBuilder MapAdditionalIdentityEndpoints(this IEndpointRouteBuilder endpoints) |
|
|
|
{ |
|
|
|
ArgumentNullException.ThrowIfNull(endpoints); |
|
|
|
|
|
|
|
var accountGroup = endpoints.MapGroup("/Account"); |
|
|
|
|
|
|
|
accountGroup.MapPost("/PerformExternalLogin", ( |
|
|
|
HttpContext context, |
|
|
|
[FromServices] SignInManager<ApplicationUser> signInManager, |
|
|
|
[FromForm] string provider, |
|
|
|
[FromForm] string returnUrl) => |
|
|
|
{ |
|
|
|
IEnumerable<KeyValuePair<string, StringValues>> query = [ |
|
|
|
new("ReturnUrl", returnUrl), |
|
|
|
new("Action", ExternalLogin.LoginCallbackAction)]; |
|
|
|
|
|
|
|
var redirectUrl = UriHelper.BuildRelative( |
|
|
|
context.Request.PathBase, |
|
|
|
"/Account/ExternalLogin", |
|
|
|
QueryString.Create(query)); |
|
|
|
|
|
|
|
var properties = signInManager.ConfigureExternalAuthenticationProperties(provider, redirectUrl); |
|
|
|
return TypedResults.Challenge(properties, [provider]); |
|
|
|
}); |
|
|
|
|
|
|
|
accountGroup.MapPost("/Logout", async ( |
|
|
|
ClaimsPrincipal user, |
|
|
|
SignInManager<ApplicationUser> signInManager, |
|
|
|
[FromForm] string returnUrl) => |
|
|
|
{ |
|
|
|
await signInManager.SignOutAsync(); |
|
|
|
return TypedResults.LocalRedirect($"~/{returnUrl}"); |
|
|
|
}); |
|
|
|
|
|
|
|
var manageGroup = accountGroup.MapGroup("/Manage").RequireAuthorization(); |
|
|
|
|
|
|
|
manageGroup.MapPost("/LinkExternalLogin", async ( |
|
|
|
HttpContext context, |
|
|
|
[FromServices] SignInManager<ApplicationUser> signInManager, |
|
|
|
[FromForm] string provider) => |
|
|
|
{ |
|
|
|
// Clear the existing external cookie to ensure a clean login process
|
|
|
|
await context.SignOutAsync(IdentityConstants.ExternalScheme); |
|
|
|
|
|
|
|
var redirectUrl = UriHelper.BuildRelative( |
|
|
|
context.Request.PathBase, |
|
|
|
"/Account/Manage/ExternalLogins", |
|
|
|
QueryString.Create("Action", ExternalLogins.LinkLoginCallbackAction)); |
|
|
|
|
|
|
|
var properties = signInManager.ConfigureExternalAuthenticationProperties(provider, redirectUrl, signInManager.UserManager.GetUserId(context.User)); |
|
|
|
return TypedResults.Challenge(properties, [provider]); |
|
|
|
}); |
|
|
|
|
|
|
|
var loggerFactory = endpoints.ServiceProvider.GetRequiredService<ILoggerFactory>(); |
|
|
|
var downloadLogger = loggerFactory.CreateLogger("DownloadPersonalData"); |
|
|
|
|
|
|
|
manageGroup.MapPost("/DownloadPersonalData", async ( |
|
|
|
HttpContext context, |
|
|
|
[FromServices] UserManager<ApplicationUser> userManager, |
|
|
|
[FromServices] AuthenticationStateProvider authenticationStateProvider) => |
|
|
|
{ |
|
|
|
var user = await userManager.GetUserAsync(context.User); |
|
|
|
if (user is null) |
|
|
|
{ |
|
|
|
return Results.NotFound($"Unable to load user with ID '{userManager.GetUserId(context.User)}'."); |
|
|
|
} |
|
|
|
|
|
|
|
var userId = await userManager.GetUserIdAsync(user); |
|
|
|
downloadLogger.LogInformation("User with ID '{UserId}' asked for their personal data.", userId); |
|
|
|
|
|
|
|
// Only include personal data for download
|
|
|
|
var personalData = new Dictionary<string, string>(); |
|
|
|
var personalDataProps = typeof(ApplicationUser).GetProperties().Where( |
|
|
|
prop => Attribute.IsDefined(prop, typeof(PersonalDataAttribute))); |
|
|
|
foreach (var p in personalDataProps) |
|
|
|
{ |
|
|
|
personalData.Add(p.Name, p.GetValue(user)?.ToString() ?? "null"); |
|
|
|
} |
|
|
|
|
|
|
|
var logins = await userManager.GetLoginsAsync(user); |
|
|
|
foreach (var l in logins) |
|
|
|
{ |
|
|
|
personalData.Add($"{l.LoginProvider} external login provider key", l.ProviderKey); |
|
|
|
} |
|
|
|
|
|
|
|
personalData.Add("Authenticator Key", (await userManager.GetAuthenticatorKeyAsync(user))!); |
|
|
|
var fileBytes = JsonSerializer.SerializeToUtf8Bytes(personalData); |
|
|
|
|
|
|
|
context.Response.Headers.TryAdd("Content-Disposition", "attachment; filename=PersonalData.json"); |
|
|
|
return TypedResults.File(fileBytes, contentType: "application/json", fileDownloadName: "PersonalData.json"); |
|
|
|
}); |
|
|
|
|
|
|
|
return accountGroup; |
|
|
|
} |
|
|
|
} |
|
|
|
} |