| 1 | using System.Net.Http.Json; |
| 2 | using System.Text.Json; |
| 3 | |
| 4 | namespace AgentForge.Tests; |
| 5 | |
| 6 | public 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 | |