So I have an 'Echo' service that is just created so I can get a deeper understanding of Web Applications and Web APIs. It had a bunch of routes and in every situation it will just return a JSON result with information about the request and response.
So I have a method "header" which will add a header to the response. And a method "cookie" that will send back a cookie. And a few other methods with experimental routes.
And now I want to focus on authentication by using the authentication stuff and JWTs so I can go deeper into understanding what these things do. Because just adding AddAuthentication/AddJwtBearer by copy/pasting things from other projects is not what I want. I also don't want some database backend, but I might want to go for OAuth authentication through Google, Facebook and Twitter as a next step. But for now, I have a variable accounts
that holds some valid login accounts and now I need to use this to make a login and make use of this authentication framework.
No database, no Azure, no complex stuff. Just plain, minimal API code. That's because this project is meant to understand the technique and experiment with it and I don't want to focus on anything else. Only the authentication. (Like I also used it to focus on how routing works, exactly.)
So what I want are a few steps:
- Learn how to add authentication in a minimal project.
- Make one route that requires authentication.
- Add authorization to this project.
- Make one route that requires authorization.
- Add Identity to this project.
- Make one route that uses Identity.
So, to begin this all, how do I do step 1?
var builder = WebApplication.CreateBuilder(args);
Dictionary<string, string> accounts = new Dictionary<string, string>() { { "wim", "123456" }, { "test", "abc123" } };
builder.Services.AddAuthentication()
.AddCookie(options =>
{
options.LoginPath = "/Account/Unauthorized/";
options.AccessDeniedPath = "/Account/Forbidden/";
})
.AddJwtBearer(options =>
{
options.Audience = "Everyone";
options.Authority = "Wim";
});
var app = builder.Build();
app
.UseHsts()
.UseAuthentication()
.MapWhen(ContainsPhp, HandlePhp());
app.MapGet("/", (HttpContext context) => Echo(context));
app.MapGet("/cookie/{name}/{*values}", (HttpContext context, string name, string values) =>
{
foreach (var value in values.Split("/"))
{
context.Response.Cookies.Append($"{name}.{value}", value);
}
return Echo(context);
});
app.MapGet("/header/{name}/{*values}", (HttpContext context, string name, string values) =>
{
context.Response.Headers[name] = values.Split("/").ToArray();
return Echo(context);
});
app.MapGet("{name}.html", (HttpContext context) => Echo(context));
app.MapGet("/{one}/{two}/{three}.{four}", (HttpContext context, string one, string two, string three, string four, [FromQuery] string five, [FromQuery] string six) =>
{
context.Response.Headers["one"] = one;
context.Response.Headers["two"] = two;
context.Response.Headers["three"] = three;
context.Response.Headers["four"] = four;
context.Response.Headers["five"] = five;
context.Response.Headers["six"] = six;
return Echo(context);
});
app.MapGet("/{*rest}", (HttpContext context) => Echo(context));
app.MapGet("/echo/", (HttpContext context) => Echo(context));
app.MapGet("/echo/{*rest}", (HttpContext context) => Echo(context));
app.MapGet("{path}.html", (HttpContext context) => Echo(context));
app.Run();
// ----------------------------------------------------------------
bool ContainsPhp(HttpContext context) => context.Request.Path.Value?.ToLower().Contains(".php") ?? false;
Action<IApplicationBuilder> HandlePhp() => applicationBuilder =>
applicationBuilder.Run((context) => Task.Run(() => context.Response.Redirect("https://www.php.net/")));
IResult Echo(HttpContext httpContext)
{
return Results.Json(new
{
Request = new
{
host = httpContext.Request.Host,
method = httpContext.Request.Method,
path = httpContext.Request.Path,
pathBase = httpContext.Request.PathBase,
route = httpContext.Request.RouteValues,
scheme = httpContext.Request.Scheme,
Query = new
{
query = httpContext.Request.Query,
queryString = httpContext.Request.QueryString,
},
},
response = new
{
statusCode = httpContext.Response.StatusCode,
cookies = httpContext.Response.Cookies,
contentType = httpContext.Response.ContentType,
},
headers = new
{
response = httpContext.Response.Headers,
request = httpContext.Request.Headers,
},
Connection = new
{
protocol = httpContext.Request.Protocol,
localIpAddress = httpContext.Connection.LocalIpAddress?.ToString(),
localPort = httpContext.Connection.LocalPort,
remoteIpAddress = httpContext.Connection.RemoteIpAddress?.ToString(),
remotePort = httpContext.Connection.RemotePort,
},
user = httpContext.User,
items = httpContext.Items,
}, new(JsonSerializerDefaults.Web) { WriteIndented = true });
}
I expect that the response JSON will show something in the User/Identity path. Right?
I got the authentication and authorization to work, sort of, and the result is in this question. But I expect there might be a better option for this, keeping it all to a minimum.