fixed origin stuff

This commit is contained in:
Rudis Muiznieks 2023-04-30 15:54:06 -05:00
parent 82bc13de67
commit 1dea48554d
Signed by: rudism
GPG Key ID: CABF2F86EF7884F9
1 changed files with 48 additions and 29 deletions

View File

@ -22,8 +22,8 @@ public static class Program {
private static readonly string s_loginHtmlCache = File.ReadAllText(Path.Combine( private static readonly string s_loginHtmlCache = File.ReadAllText(Path.Combine(
AppDomain.CurrentDomain.BaseDirectory, "login.html")); AppDomain.CurrentDomain.BaseDirectory, "login.html"));
private static readonly string s_domain = Environment private static readonly string? s_domain = Environment
.GetEnvironmentVariable("WEBAUTHN_DOMAIN") ?? "localhost"; .GetEnvironmentVariable("WEBAUTHN_DOMAIN");
private static readonly string s_db = Environment private static readonly string s_db = Environment
.GetEnvironmentVariable("WEBAUTHN_DB") ?? "credentials.db"; .GetEnvironmentVariable("WEBAUTHN_DB") ?? "credentials.db";
private static readonly long s_lifetime = long.Parse(Environment private static readonly long s_lifetime = long.Parse(Environment
@ -34,21 +34,31 @@ public static class Program {
private static readonly int s_port = int.Parse(Environment private static readonly int s_port = int.Parse(Environment
.GetEnvironmentVariable("WEBAUTHN_PORT") ?? "5000", .GetEnvironmentVariable("WEBAUTHN_PORT") ?? "5000",
CultureInfo.InvariantCulture); CultureInfo.InvariantCulture);
private static readonly Fido2 s_fido2 = new(new Fido2Configuration { private static readonly Dictionary<string, Fido2> s_fido2 = new();
ServerDomain = s_domain,
ServerName = "WebauthnProxy",
Origins = new(new[] { $"http{(
s_domain == "localhost"
? string.Empty
: "s")}://{s_domain}{(
s_domain == "localhost"
? $":{s_port}"
: string.Empty)}" }),
});
private static readonly List<PublicKeyCredentialDescriptor> s_keys = new(); private static readonly List<PublicKeyCredentialDescriptor> s_keys = new();
private static string ConnectionString { get => $"Data Source={s_db}"; } private static string ConnectionString { get => $"Data Source={s_db}"; }
private static Fido2 GetFido2(HttpContext context) {
var origin = context.Request.Host.Value.Split(":").First();
Console.WriteLine($"origin {origin}");
if (!s_fido2.ContainsKey(origin)) {
s_fido2.Add(origin, new(new Fido2Configuration {
ServerDomain = origin,
ServerName = "WebauthnProxy",
Origins = new(new[] { $"http{(
origin == "localhost"
? string.Empty
: "s")}://{origin}{(
origin == "localhost"
? $":{s_port}"
: string.Empty)}" }),
}));
}
return s_fido2[origin];
}
public static void Main(string[] args) { public static void Main(string[] args) {
var app = Initialize(args); var app = Initialize(args);
app.UseSession(); app.UseSession();
@ -82,20 +92,25 @@ public static class Program {
if (context.Request.Cookies[COOKIE_NAME] == null) if (context.Request.Cookies[COOKIE_NAME] == null)
return Task.CompletedTask; return Task.CompletedTask;
context.Response.Cookies.Append(COOKIE_NAME, string.Empty, new CookieOptions { var cookieOpts = new CookieOptions {
Path = "/", Path = "/",
Secure = true, Secure = true,
HttpOnly = true, HttpOnly = true,
MaxAge = TimeSpan.Zero, SameSite = SameSiteMode.None,
Domain = s_domain, MaxAge = TimeSpan.FromSeconds(s_lifetime),
}); };
if (string.IsNullOrEmpty(s_domain)) {
cookieOpts.Domain = s_domain;
}
context.Response.Cookies.Append(COOKIE_NAME, string.Empty, cookieOpts);
context.Response.Redirect("/"); context.Response.Redirect("/");
return Task.CompletedTask; return Task.CompletedTask;
}); });
app.MapPost("/auth/key", async (context) => { app.MapPost("/auth/key", async (context) => {
var options = s_fido2.GetAssertionOptions( var options = GetFido2(context).GetAssertionOptions(
s_keys, UserVerificationRequirement.Discouraged); s_keys, UserVerificationRequirement.Discouraged);
context.Session.SetString(SESS_ASSERTION_KEY, context.Session.SetString(SESS_ASSERTION_KEY,
JsonSerializer.Serialize(options)); JsonSerializer.Serialize(options));
@ -134,7 +149,7 @@ public static class Program {
} }
} }
var res = await s_fido2.MakeAssertionAsync( var res = await GetFido2(context).MakeAssertionAsync(
assertionResponse, opts, pubKey, 0, (_, _) => Task.FromResult(true)); assertionResponse, opts, pubKey, 0, (_, _) => Task.FromResult(true));
if (res.Status != "ok") { if (res.Status != "ok") {
context.Response.StatusCode = 401; context.Response.StatusCode = 401;
@ -142,17 +157,21 @@ public static class Program {
return; return;
} }
var cookieOpts = new CookieOptions {
Path = "/",
Secure = true,
HttpOnly = true,
SameSite = SameSiteMode.None,
MaxAge = TimeSpan.FromSeconds(s_lifetime),
};
if (string.IsNullOrEmpty(s_domain)) {
cookieOpts.Domain = s_domain;
}
context.Response.Cookies.Append( context.Response.Cookies.Append(
COOKIE_NAME, COOKIE_NAME,
GenerateToken(connection), GenerateToken(connection),
new CookieOptions { cookieOpts);
Path = "/",
Secure = true,
HttpOnly = true,
SameSite = SameSiteMode.None,
Domain = s_domain,
MaxAge = TimeSpan.FromSeconds(s_lifetime),
});
await context.Response.WriteAsJsonAsync(new { status = "ok" }); await context.Response.WriteAsJsonAsync(new { status = "ok" });
}); });
@ -162,7 +181,7 @@ public static class Program {
Name = "Default User", Name = "Default User",
DisplayName = "Default User", DisplayName = "Default User",
}; };
var options = s_fido2.RequestNewCredential( var options = GetFido2(context).RequestNewCredential(
user, user,
new List<PublicKeyCredentialDescriptor>(), new List<PublicKeyCredentialDescriptor>(),
AuthenticatorSelection.Default, AuthenticatorSelection.Default,
@ -190,7 +209,7 @@ public static class Program {
var optsJson = context.Session.GetString(SESS_ATTESTATION_KEY); var optsJson = context.Session.GetString(SESS_ATTESTATION_KEY);
context.Session.Remove(SESS_ATTESTATION_KEY); context.Session.Remove(SESS_ATTESTATION_KEY);
var opts = CredentialCreateOptions.FromJson(optsJson); var opts = CredentialCreateOptions.FromJson(optsJson);
var cred = await s_fido2.MakeNewCredentialAsync( var cred = await GetFido2(context).MakeNewCredentialAsync(
req.Response, opts, (_, _) => Task.FromResult(true)); req.Response, opts, (_, _) => Task.FromResult(true));
var descriptor = new PublicKeyCredentialDescriptor( var descriptor = new PublicKeyCredentialDescriptor(
cred.Result!.CredentialId); cred.Result!.CredentialId);