Skip to content

Commit bd1b1b6

Browse files
committed
Basic code structure
1 parent 25a11c0 commit bd1b1b6

30 files changed

+5216
-0
lines changed

Descope.Test/Descope.Test.csproj

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<OutputType>Exe</OutputType>
5+
<TargetFramework>net6.0</TargetFramework>
6+
<ImplicitUsings>enable</ImplicitUsings>
7+
<Nullable>enable</Nullable>
8+
<RestorePackagesWithLockFile>true</RestorePackagesWithLockFile>
9+
</PropertyGroup>
10+
11+
<ItemGroup>
12+
<Compile Remove="Auth\AccessKeyServiceTest.cs" />
13+
</ItemGroup>
14+
15+
<ItemGroup>
16+
<PackageReference Include="Microsoft.Extensions.Configuration" Version="7.0.0" />
17+
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables"
18+
Version="7.0.0" />
19+
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="7.0.0" />
20+
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="7.0.0" />
21+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
22+
<PackageReference Include="Moq" Version="4.20.69" />
23+
<PackageReference Include="NBuilder" Version="6.1.0" />
24+
<PackageReference Include="xunit" Version="2.6.1" />
25+
<PackageReference Include="xunit.assert" Version="2.6.1" />
26+
<PackageReference Include="xunit.extensibility.core" Version="2.6.1" />
27+
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.3">
28+
<PrivateAssets>all</PrivateAssets>
29+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
30+
</PackageReference>
31+
</ItemGroup>
32+
33+
<ItemGroup>
34+
<ProjectReference Include="..\Descope\Descope.csproj" />
35+
</ItemGroup>
36+
37+
<ItemGroup>
38+
<None Update="appsettingsTest.json">
39+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
40+
</None>
41+
</ItemGroup>
42+
43+
<ItemGroup>
44+
<Content Include="xunit.runner.json" CopyToOutputDirectory="PreserveNewest" />
45+
</ItemGroup>
46+
47+
</Project>

Descope.Test/Descope.Test.sln

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
# Visual Studio Version 17
4+
VisualStudioVersion = 17.5.002.0
5+
MinimumVisualStudioVersion = 10.0.40219.1
6+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Descope.Test", "Descope.Test.csproj", "{E2E0EF99-CE4C-40BA-8A8E-532F14D47F7A}"
7+
EndProject
8+
Global
9+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
10+
Debug|Any CPU = Debug|Any CPU
11+
Release|Any CPU = Release|Any CPU
12+
EndGlobalSection
13+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
14+
{E2E0EF99-CE4C-40BA-8A8E-532F14D47F7A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15+
{E2E0EF99-CE4C-40BA-8A8E-532F14D47F7A}.Debug|Any CPU.Build.0 = Debug|Any CPU
16+
{E2E0EF99-CE4C-40BA-8A8E-532F14D47F7A}.Release|Any CPU.ActiveCfg = Release|Any CPU
17+
{E2E0EF99-CE4C-40BA-8A8E-532F14D47F7A}.Release|Any CPU.Build.0 = Release|Any CPU
18+
EndGlobalSection
19+
GlobalSection(SolutionProperties) = preSolution
20+
HideSolutionNode = FALSE
21+
EndGlobalSection
22+
GlobalSection(ExtensibilityGlobals) = postSolution
23+
SolutionGuid = {18F8C6D8-027A-45D4-BFFC-ABFF27D9416F}
24+
EndGlobalSection
25+
EndGlobal
Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
using Xunit;
2+
3+
namespace Descope.Test.Integration
4+
{
5+
public class AuthenticationTests
6+
{
7+
private readonly DescopeClient _descopeClient = IntegrationTestSetup.InitDescopeClient();
8+
9+
[Fact]
10+
public async Task Authentication_ValidateAndRefresh()
11+
{
12+
string? loginId = null;
13+
try
14+
{
15+
// Create a logged in test user
16+
var testUser = await IntegrationTestSetup.InitTestUser(_descopeClient);
17+
loginId = testUser.User.loginIds.First();
18+
19+
// Make sure the session is valid
20+
var token = await _descopeClient.Auth.ValidateSession(testUser.AuthInfo.sessionJwt);
21+
Assert.Equal(testUser.AuthInfo.sessionJwt, token.Jwt);
22+
Assert.NotEmpty(token.Id);
23+
Assert.NotEmpty(token.ProjectId);
24+
25+
// Refresh and see we got a new token
26+
var refreshedToken = await _descopeClient.Auth.RefreshSession(testUser.AuthInfo.refreshJwt!);
27+
Assert.NotNull(refreshedToken.RefreshExpiration);
28+
Assert.Equal(token.Id, refreshedToken.Id);
29+
Assert.Equal(token.ProjectId, refreshedToken.ProjectId);
30+
}
31+
finally
32+
{
33+
if (!string.IsNullOrEmpty(loginId))
34+
{
35+
try { await _descopeClient.Management.User.Delete(loginId); }
36+
catch { }
37+
}
38+
}
39+
}
40+
41+
[Fact]
42+
public async Task Authentication_ExchangeAccessKeyAndMe()
43+
{
44+
string? loginId = null;
45+
string? accessKeyId = null;
46+
try
47+
{
48+
// Create a logged in test user
49+
var testUser = await IntegrationTestSetup.InitTestUser(_descopeClient);
50+
loginId = testUser.User.loginIds.First();
51+
52+
// Create an access key and exchange it
53+
var accessKeyResponse = await _descopeClient.Management.AccessKey.Create(loginId, userId: testUser.User.userId);
54+
accessKeyId = accessKeyResponse.Key.Id;
55+
var token = await _descopeClient.Auth.ExchangeAccessKey(accessKeyResponse.Cleartext);
56+
Assert.NotEmpty(token.Id);
57+
Assert.NotEmpty(token.ProjectId);
58+
Assert.NotEmpty(token.Jwt);
59+
}
60+
finally
61+
{
62+
if (!string.IsNullOrEmpty(loginId))
63+
{
64+
try { await _descopeClient.Management.User.Delete(loginId); }
65+
catch { }
66+
}
67+
if (!string.IsNullOrEmpty(accessKeyId))
68+
{
69+
try { await _descopeClient.Management.AccessKey.Delete(accessKeyId); }
70+
catch { }
71+
}
72+
}
73+
}
74+
75+
[Fact]
76+
public async Task Authentication_SelectTenant()
77+
{
78+
string? loginId = null;
79+
List<string> tenantIds = new() { };
80+
try
81+
{
82+
// Create a logged in test user
83+
var testUser = await IntegrationTestSetup.InitTestUser(_descopeClient);
84+
loginId = testUser.User.loginIds.First();
85+
86+
// Create a couple of tenants and add to the user
87+
var tenantId = await _descopeClient.Management.Tenant.Create(new TenantOptions { name = Guid.NewGuid().ToString() });
88+
tenantIds.Add(tenantId);
89+
await _descopeClient.Management.User.AddTenant(loginId, tenantId);
90+
tenantId = await _descopeClient.Management.Tenant.Create(new TenantOptions { name = Guid.NewGuid().ToString() });
91+
tenantIds.Add(tenantId);
92+
await _descopeClient.Management.User.AddTenant(loginId, tenantId);
93+
var session = await _descopeClient.Auth.SelectTenant(tenantId, testUser.AuthInfo.refreshJwt!);
94+
Assert.NotEmpty(session.SessionToken.Id);
95+
Assert.NotEmpty(session.SessionToken.ProjectId);
96+
Assert.NotEmpty(session.SessionToken.Jwt);
97+
}
98+
finally
99+
{
100+
if (!string.IsNullOrEmpty(loginId))
101+
{
102+
try { await _descopeClient.Management.User.Delete(loginId); }
103+
catch { }
104+
}
105+
foreach (var tenantId in tenantIds)
106+
{
107+
try { await _descopeClient.Management.Tenant.Delete(tenantId); }
108+
catch { }
109+
}
110+
}
111+
}
112+
113+
// TODO: Test permissions and roles once available on via management
114+
115+
[Theory]
116+
[InlineData(true)]
117+
[InlineData(false)]
118+
public async Task Authentication_MeAndLogout(bool logoutAll)
119+
{
120+
string? loginId = null;
121+
try
122+
{
123+
// Create a logged in test user
124+
var testUser = await IntegrationTestSetup.InitTestUser(_descopeClient);
125+
loginId = testUser.User.loginIds.First();
126+
127+
// Me
128+
var user = await _descopeClient.Auth.Me(testUser.AuthInfo.refreshJwt!);
129+
Assert.Equal(testUser.User.userId, user.userId);
130+
131+
// Logout
132+
if (logoutAll) await _descopeClient.Auth.LogOut(testUser.AuthInfo.refreshJwt!);
133+
else await _descopeClient.Auth.LogOutAll(testUser.AuthInfo.refreshJwt!);
134+
135+
// Try me again
136+
await Task.Delay(200);
137+
async Task Act() => await _descopeClient.Auth.Me(testUser.AuthInfo.refreshJwt!);
138+
DescopeException result = await Assert.ThrowsAsync<DescopeException>(Act);
139+
Assert.Contains("Expired due to logout", result.Message);
140+
}
141+
finally
142+
{
143+
if (!string.IsNullOrEmpty(loginId))
144+
{
145+
try { await _descopeClient.Management.User.Delete(loginId); }
146+
catch { }
147+
}
148+
}
149+
}
150+
}
151+
}
Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
using Xunit;
2+
3+
namespace Descope.Test.Integration
4+
{
5+
public class AccessKeyTests
6+
{
7+
private readonly DescopeClient _descopeClient = IntegrationTestSetup.InitDescopeClient();
8+
9+
[Fact]
10+
public async Task AccessKey_Create_MissingName()
11+
{
12+
async Task Act() => await _descopeClient.Management.AccessKey.Create(name: "");
13+
DescopeException result = await Assert.ThrowsAsync<DescopeException>(Act);
14+
Assert.Contains("Access key name is required", result.Message);
15+
}
16+
17+
[Fact]
18+
public async Task AccessKey_CreateAndUpdate()
19+
{
20+
string? id = null;
21+
try
22+
{
23+
// Create an access key
24+
var accessKey = await _descopeClient.Management.AccessKey.Create(name: Guid.NewGuid().ToString());
25+
id = accessKey.Key.Id;
26+
27+
// Update and compare
28+
var updatedName = accessKey.Key.Name + "updated";
29+
var updatedKey = await _descopeClient.Management.AccessKey.Update(id: id, name: updatedName);
30+
Assert.Equal(updatedKey.Name, updatedKey.Name);
31+
}
32+
finally
33+
{
34+
if (!string.IsNullOrEmpty(id))
35+
{
36+
try { await _descopeClient.Management.AccessKey.Delete(id); }
37+
catch { }
38+
}
39+
}
40+
}
41+
42+
[Fact]
43+
public async Task AccessKey_Update_MissingId()
44+
{
45+
async Task Act() => await _descopeClient.Management.AccessKey.Update("", "name");
46+
DescopeException result = await Assert.ThrowsAsync<DescopeException>(Act);
47+
Assert.Contains("ID is required", result.Message);
48+
}
49+
50+
[Fact]
51+
public async Task AccessKey_Update_MissingName()
52+
{
53+
async Task Act() => await _descopeClient.Management.AccessKey.Update("someId", "");
54+
DescopeException result = await Assert.ThrowsAsync<DescopeException>(Act);
55+
Assert.Contains("name cannot be updated to empty", result.Message);
56+
}
57+
58+
[Fact]
59+
public async Task Accesskey_ActivateDeactivate()
60+
{
61+
string? id = null;
62+
try
63+
{
64+
// Create an access key
65+
var accessKey = await _descopeClient.Management.AccessKey.Create(name: Guid.NewGuid().ToString());
66+
id = accessKey.Key.Id;
67+
68+
// Deactivate
69+
await _descopeClient.Management.AccessKey.Deactivate(id);
70+
var loadedKey = await _descopeClient.Management.AccessKey.Load(id);
71+
Assert.Equal("inactive", loadedKey.Status);
72+
73+
// Activate
74+
await _descopeClient.Management.AccessKey.Activate(id);
75+
loadedKey = await _descopeClient.Management.AccessKey.Load(id);
76+
Assert.Equal("active", loadedKey.Status);
77+
}
78+
finally
79+
{
80+
if (!string.IsNullOrEmpty(id))
81+
{
82+
try { await _descopeClient.Management.AccessKey.Delete(id); }
83+
catch { }
84+
}
85+
}
86+
}
87+
88+
[Fact]
89+
public async Task AccessKey_Activate_MissingId()
90+
{
91+
async Task Act() => await _descopeClient.Management.AccessKey.Activate("");
92+
DescopeException result = await Assert.ThrowsAsync<DescopeException>(Act);
93+
Assert.Contains("ID is required", result.Message);
94+
}
95+
96+
[Fact]
97+
public async Task AccessKey_Deactivate_MissingId()
98+
{
99+
async Task Act() => await _descopeClient.Management.AccessKey.Deactivate("");
100+
DescopeException result = await Assert.ThrowsAsync<DescopeException>(Act);
101+
Assert.Contains("ID is required", result.Message);
102+
}
103+
104+
[Fact]
105+
public async Task AccessKey_Load_MissingId()
106+
{
107+
async Task Act() => await _descopeClient.Management.AccessKey.Load("");
108+
DescopeException result = await Assert.ThrowsAsync<DescopeException>(Act);
109+
Assert.Contains("Access key ID is required", result.Message);
110+
}
111+
112+
[Fact]
113+
public async Task AccessKey_SearchAll()
114+
{
115+
string? id = null;
116+
try
117+
{
118+
// Create an access key
119+
var accessKey = await _descopeClient.Management.AccessKey.Create(name: Guid.NewGuid().ToString());
120+
id = accessKey.Key.Id;
121+
122+
// Search for it
123+
var accessKeys = await _descopeClient.Management.AccessKey.SearchAll();
124+
var key = accessKeys.Find(key => key.Id == id);
125+
Assert.NotNull(key);
126+
}
127+
finally
128+
{
129+
if (!string.IsNullOrEmpty(id))
130+
{
131+
try { await _descopeClient.Management.AccessKey.Delete(id); }
132+
catch { }
133+
}
134+
}
135+
}
136+
137+
[Fact]
138+
public async Task AccessKey_Delete()
139+
{
140+
// Arrange
141+
var accessKey = await _descopeClient.Management.AccessKey.Create(name: Guid.NewGuid().ToString());
142+
143+
// Act
144+
await _descopeClient.Management.AccessKey.Delete(accessKey.Key.Id);
145+
146+
// Assert
147+
var accessKeys = await _descopeClient.Management.AccessKey.SearchAll(new List<string>() { accessKey.Key.Id });
148+
Assert.Empty(accessKeys);
149+
}
150+
151+
[Fact]
152+
public async Task Accesskey_Delete_MissingId()
153+
{
154+
async Task Act() => await _descopeClient.Management.AccessKey.Delete("");
155+
DescopeException result = await Assert.ThrowsAsync<DescopeException>(Act);
156+
Assert.Contains("Access key ID is required", result.Message);
157+
}
158+
159+
}
160+
}

0 commit comments

Comments
 (0)