diff --git a/src/atproto/oauth.zig b/src/atproto/oauth.zig index d6eacf2..88fac16 100644 --- a/src/atproto/oauth.zig +++ b/src/atproto/oauth.zig @@ -147,6 +147,7 @@ pub fn authorizeGet(request: *http.Server.Request) !void { return oauthError(request, .bad_request, "invalid_scope", "Failed to summarize requested permission set"); }; const issuer = config.publicUrl(); + const passkey_html = try passkeyLoginHtml(allocator, oauth_request.login_hint); const html = try std.fmt.allocPrint(allocator, \\ \\ @@ -220,7 +221,7 @@ pub fn authorizeGet(request: *http.Server.Request) !void { \\ \\ \\ - \\ + \\{s} \\
\\use password instead \\
@@ -257,11 +258,21 @@ pub fn authorizeGet(request: *http.Server.Request) !void { request_uri_prefix, oauth_request.request_id, try htmlEscape(allocator, oauth_request.login_hint orelse ""), + passkey_html, try htmlEscape(allocator, issuer), }); try respondHtml(request, .ok, html); } +fn passkeyLoginHtml(allocator: std.mem.Allocator, login_hint: ?[]const u8) ![]const u8 { + if (login_hint) |identifier| { + const account = (try store.findAccount(allocator, identifier)) orelse return ""; + const passkeys = try store.listPasskeys(allocator, account.did); + if (passkeys.len == 0) return ""; + } + return allocator.dupe(u8, ""); +} + pub fn authorizePost(request: *http.Server.Request) !void { var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); defer arena.deinit();