I'm working with an angular front end connected to a .NET Core back end and using OpenIddict for authorization. When I land on my login page, the url looks as follows:
https://localhost:44340/Account/Login?ReturnUrl=/connect/authorize?response_type=code&client_id=clientIDExample&state=YUVBdDJvUG04SUpVTzZqSEJvRlMxWFZnWU0xSUVsSi1IVnR1WEY2R3pCMG1m&redirect_uri=http%3A%2F%2Flocalhost%3A4200&scope=openid%20profile%20email%20offline_access&code_challenge=Ag0TCRqJBaFqpa8sJb--J67Yd88tNPmouGonUvBbBbM&code_challenge_method=S256&nonce=YUVBdDJvUG04SUpVTzZqSEJvRlMxWFZnWU0xSUVsSi1IVnR1WEY2R3pCMG1m
Here is the 'user friendly' url I want the users to see, not the authorize endpoint:
https://localhost:44340/Account/Login
Here is the part of my Authorization code that I'm hitting:
[HttpGet("~/connect/authorize")]
[HttpPost("~/connect/authorize")]
[IgnoreAntiforgeryToken]
public async Task<IActionResult> Authorize()
{
var request = HttpContext.GetOpenIddictServerRequest() ??
throw new InvalidOperationException("The OpenID Connect request cannot be retrieved.");
// Retrieve the user principal stored in the authentication cookie.
// If it can't be extracted, redirect the user to the login page.
var result = await HttpContext.AuthenticateAsync(IdentityConstants.ApplicationScheme);
if (result is null || !result.Succeeded)
{
// If the client application requested promptless authentication,
// return an error indicating that the user is not logged in.
if (request.HasPrompt(Prompts.None))
{
return Forbid(
authenticationSchemes: OpenIddictServerAspNetCoreDefaults.AuthenticationScheme,
properties: new AuthenticationProperties(new Dictionary<string, string>
{
[OpenIddictServerAspNetCoreConstants.Properties.Error] = Errors.LoginRequired,
[OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] = "The user is not logged in."
}));
}
return Challenge(
authenticationSchemes: IdentityConstants.ApplicationScheme,
properties: new AuthenticationProperties
{
RedirectUri = Request.PathBase Request.Path QueryString.Create(
Request.HasFormContentType ? Request.Form.ToList() : Request.Query.ToList())
});
}
}
Here is my Startup class:
public class Startup
{
public Startup(IConfiguration configuration, IHostEnvironment env)
{
Configuration = configuration;
_env = env;
}
public IConfiguration Configuration { get; }
public IHostEnvironment _env { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
var connectionString = Configuration[$"Connections:DefaultConnection"];
var EncryptionCertificate = new X509Certificate2(Convert.FromBase64String(Configuration["EncCert"]), (string)null, X509KeyStorageFlags.MachineKeySet);
var SignCertificate = new X509Certificate2(Convert.FromBase64String(Configuration["SigCert"]), (string)null, X509KeyStorageFlags.MachineKeySet);
services.AddRazorPages();
//DbContext OnConfiguring gets done here
services.AppDataContext(connectionString);
// OpenIddict offers native integration with Quartz.NET to perform scheduled tasks
// (like pruning orphaned authorizations/tokens from the database) at regular intervals.
services.AddQuartz(options =>
{
options.UseMicrosoftDependencyInjectionJobFactory();
options.UseSimpleTypeLoader();
options.UseInMemoryStore();
});
// Register the Quartz.NET service and configure it to block shutdown until jobs are complete.
services.AddQuartzHostedService(options => options.WaitForJobsToComplete = true);
services.AddIdentity<ApplicationUserModel, IdentityRole>()
.AddEntityFrameworkStores<DataContext>()
.AddDefaultTokenProviders();
services.Configure<IdentityOptions>(options =>
{
// Configure Identity to use the same JWT claims as OpenIddict instead
// of the legacy WS-Federation claims it uses by default (ClaimTypes),
// which saves you from doing the mapping in your authorization controller.
options.ClaimsIdentity.UserNameClaimType = Claims.Name;
options.ClaimsIdentity.UserIdClaimType = Claims.Subject;
options.ClaimsIdentity.RoleClaimType = Claims.Role;
// Note: to require account confirmation before login,
// register an email sender service (IEmailSender) and
// set options.SignIn.RequireConfirmedAccount to true.
//
// For more information, visit https://aka.ms/aspaccountconf.
options.SignIn.RequireConfirmedAccount = false;
});
services.IdentityServer(EncryptionCertificate, SignCertificate);
services.AddAuthentication(Configuration);
//Adds some claim data
services.AddScoped<IUserClaimsPrincipalFactory<ApplicationUserModel>, AdditionalUserClaimsPrincipalFactory>();
services.AddCors(options => options.AddPolicy("AllowCors",
builder =>
{
builder.SetIsOriginAllowed(_ => true)
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials();
})
);
if (_env.IsDevelopment())
{
//Script will populate Database but should be scripted for production
services.AddHostedService<Worker>();
}
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseCors("AllowCors");
//Middleware that takes care of authorization and authentication
//Should always happen before the endpoints
//These methods allow for decorating Controllers with the Authorize attribute, which controls page and feature access
app.UseAuthentication();
app.UseAuthorization();
//Endpoints instead of Razor pages
//Because using APIs and Angular
app.UseEndpoints(endpoints =>
{
//endpoints.MapControllers();
endpoints.MapDefaultControllerRoute();
});
}
}
Do I need a rewrite? A redirect? I need to retain the endpoint but I can't be showing the users the entire endpoint.
CodePudding user response:
I think most system will present you with that 'ugly' link, event if you try to login with Google or Facebook, you will be presented with the same long link.
There are ongoing work in the community that could result in nicer links and one is Pushed Authorization Requests (PAR), but I doubt all token providers supports it and I don't know what the support is for that in ASP.NET Core today.


