forked from github/copilot-sdk
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathPerSessionAuthE2ETests.cs
More file actions
142 lines (118 loc) · 4.97 KB
/
Copy pathPerSessionAuthE2ETests.cs
File metadata and controls
142 lines (118 loc) · 4.97 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
*--------------------------------------------------------------------------------------------*/
using GitHub.Copilot.Test.Harness;
using Xunit;
using Xunit.Abstractions;
namespace GitHub.Copilot.Test.E2E;
public class PerSessionAuthE2ETests(E2ETestFixture fixture, ITestOutputHelper output) : E2ETestBase(fixture, "per-session-auth", output)
{
/// <summary>
/// Creates a client with COPILOT_DEBUG_GITHUB_API_URL redirected to the proxy
/// so per-session auth token resolution (fetchCopilotUser) is intercepted.
/// </summary>
private CopilotClient CreateAuthTestClient()
{
var env = new Dictionary<string, string>(Ctx.GetEnvironment())
{
["COPILOT_DEBUG_GITHUB_API_URL"] = Ctx.ProxyUrl,
};
// Disable the harness's auto-injected client token so the per-session
// auth tests validate only session-scoped tokens.
return Ctx.CreateClient(options: new CopilotClientOptions { Environment = env }, autoInjectGitHubToken: false);
}
private CopilotClient CreateNoAuthTestClient()
{
var env = WithoutAuthEnv(Ctx.GetEnvironment());
env["COPILOT_DEBUG_GITHUB_API_URL"] = Ctx.ProxyUrl;
return Ctx.CreateClient(options: new CopilotClientOptions
{
Environment = env,
UseLoggedInUser = false,
}, autoInjectGitHubToken: false);
}
private static Dictionary<string, string> WithoutAuthEnv(Dictionary<string, string> env)
{
var result = new Dictionary<string, string>(env)
{
["COPILOT_SDK_AUTH_TOKEN"] = "",
["GH_TOKEN"] = "",
["GITHUB_TOKEN"] = "",
};
return result;
}
private async Task SetupCopilotUsersAsync()
{
await Ctx.SetCopilotUserByTokenAsync("token-alice", new CopilotUserConfig(
Login: "alice",
CopilotPlan: "individual_pro",
Endpoints: new CopilotUserEndpoints(Api: Ctx.ProxyUrl, Telemetry: "https://localhost:1/telemetry"),
AnalyticsTrackingId: "alice-tracking-id"
));
await Ctx.SetCopilotUserByTokenAsync("token-bob", new CopilotUserConfig(
Login: "bob",
CopilotPlan: "business",
Endpoints: new CopilotUserEndpoints(Api: Ctx.ProxyUrl, Telemetry: "https://localhost:1/telemetry"),
AnalyticsTrackingId: "bob-tracking-id"
));
}
private CopilotClient? _authClient;
private CopilotClient AuthClient => _authClient ??= CreateAuthTestClient();
[Fact]
public async Task ShouldAuthenticateWithGitHubToken()
{
await SetupCopilotUsersAsync();
await using var session = await AuthClient.CreateSessionAsync(new SessionConfig
{
GitHubToken = "token-alice",
OnPermissionRequest = PermissionHandler.ApproveAll,
});
var status = await session.Rpc.Auth.GetStatusAsync();
Assert.True(status.IsAuthenticated);
Assert.Equal("alice", status.Login);
}
[Fact]
public async Task ShouldIsolateAuthBetweenSessions()
{
await SetupCopilotUsersAsync();
await using var sessionA = await AuthClient.CreateSessionAsync(new SessionConfig
{
GitHubToken = "token-alice",
OnPermissionRequest = PermissionHandler.ApproveAll,
});
await using var sessionB = await AuthClient.CreateSessionAsync(new SessionConfig
{
GitHubToken = "token-bob",
OnPermissionRequest = PermissionHandler.ApproveAll,
});
var statusA = await sessionA.Rpc.Auth.GetStatusAsync();
Assert.True(statusA.IsAuthenticated);
Assert.Equal("alice", statusA.Login);
var statusB = await sessionB.Rpc.Auth.GetStatusAsync();
Assert.True(statusB.IsAuthenticated);
Assert.Equal("bob", statusB.Login);
}
[Fact]
public async Task ShouldBeUnauthenticatedWithoutToken()
{
var noAuthClient = CreateNoAuthTestClient();
await using var session = await noAuthClient.CreateSessionAsync(new SessionConfig
{
OnPermissionRequest = PermissionHandler.ApproveAll,
});
var status = await session.Rpc.Auth.GetStatusAsync();
// Without a per-session GitHub token, there is no per-session identity.
Assert.True(string.IsNullOrEmpty(status.Login), $"Expected no per-session login without token, got {status.Login}");
}
[Fact]
public async Task ShouldFailWithInvalidToken()
{
await SetupCopilotUsersAsync();
var ex = await Assert.ThrowsAnyAsync<Exception>(() => AuthClient.CreateSessionAsync(new SessionConfig
{
GitHubToken = "invalid-token",
OnPermissionRequest = PermissionHandler.ApproveAll,
}));
Assert.Contains("401 Unauthorized", ex.ToString(), StringComparison.OrdinalIgnoreCase);
}
}