Forge
csharp3407750f
1using System.Net.Http.Json;
2using System.Text.Json;
3
4namespace AgentForge.Tests;
5
6public sealed class ForgeDeviceAuthTests
7{
8 private static readonly JsonSerializerOptions JsonOptions = new() { PropertyNameCaseInsensitive = true };
9
10 [Fact]
11 public async Task Device_login_flow_issues_token_after_bootstrap_approve()
12 {
13 Environment.SetEnvironmentVariable("FORGE_BOOTSTRAP_TOKEN", "bootstrap-device");
14 using var factory = new ForgeWebApplicationFactory();
15 using var client = factory.CreateClient();
16
17 using var beginResponse = await client.PostAsJsonAsync("/api/v1/auth/device", new { clientName = "test-cli" });
18 beginResponse.EnsureSuccessStatusCode();
19 var begin = await beginResponse.Content.ReadFromJsonAsync<JsonElement>(JsonOptions);
20 var deviceCode = begin.GetProperty("device_code").GetString()!;
21 var userCode = begin.GetProperty("user_code").GetString()!;
22
23 using var pendingPoll = await client.PostAsJsonAsync("/api/v1/auth/device/token", new { deviceCode });
24 Assert.Equal(System.Net.HttpStatusCode.BadRequest, pendingPoll.StatusCode);
25
26 using var approveRequest = new HttpRequestMessage(HttpMethod.Post, "/api/v1/auth/device/approve")
27 {
28 Content = JsonContent.Create(new { userCode }),
29 };
30 approveRequest.Headers.Authorization =
31 new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", "bootstrap-device");
32 (await client.SendAsync(approveRequest)).EnsureSuccessStatusCode();
33
34 using var successPoll = await client.PostAsJsonAsync("/api/v1/auth/device/token", new { deviceCode });
35 successPoll.EnsureSuccessStatusCode();
36 var tokenBody = await successPoll.Content.ReadFromJsonAsync<JsonElement>(JsonOptions);
37 var token = tokenBody.GetProperty("access_token").GetString();
38 Assert.StartsWith("fg_", token);
39
40 Environment.SetEnvironmentVariable("FORGE_BOOTSTRAP_TOKEN", null);
41 }
42}
43
View only · write via MCP/CIDE