Skip to content

Commit

Permalink
Add test using resource parameters
Browse files Browse the repository at this point in the history
  • Loading branch information
josephdecock committed Nov 27, 2023
1 parent b692099 commit 29e59eb
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 2 deletions.
3 changes: 2 additions & 1 deletion test/Tests/Framework/ApiHost.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,12 @@ public class ApiHost : GenericHost
private readonly IdentityServerHost _identityServerHost;
public event Action<Microsoft.AspNetCore.Http.HttpContext> ApiInvoked = ctx => { };

public ApiHost(IdentityServerHost identityServerHost, string scope, string baseAddress = "https://api")
public ApiHost(IdentityServerHost identityServerHost, string scope, string baseAddress = "https://api", string resource = "urn:api")
: base(baseAddress)
{
_identityServerHost = identityServerHost;
_identityServerHost.ApiScopes.Add(new ApiScope(scope));
_identityServerHost.ApiResources.Add(new ApiResource(resource));

OnConfigureServices += ConfigureServices;
OnConfigure += Configure;
Expand Down
16 changes: 15 additions & 1 deletion test/Tests/Framework/AppHost.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Http;
using RichardSzalay.MockHttp;
using Duende.AccessTokenManagement.OpenIdConnect;
using Microsoft.AspNetCore.Mvc;

namespace Duende.AccessTokenManagement.Tests;

Expand Down Expand Up @@ -92,7 +94,10 @@ private void ConfigureServices(IServiceCollection services)
});

services.AddDistributedMemoryCache();
services.AddOpenIdConnectAccessTokenManagement();
services.AddOpenIdConnectAccessTokenManagement(opt =>
{
opt.UseChallengeSchemeScopedTokens = true;
});

}

Expand Down Expand Up @@ -122,6 +127,15 @@ await context.ChallengeAsync(new AuthenticationProperties
var token = await context.GetUserAccessTokenAsync();
await context.Response.WriteAsJsonAsync(token);
});
endpoints.MapGet("/user_token_with_resource/{resource}", async (string resource, HttpContext context) =>
{
var token = await context.GetUserAccessTokenAsync(new UserTokenRequestParameters
{
Resource = resource
});
await context.Response.WriteAsJsonAsync(token);
});
endpoints.MapGet("/client_token", async context =>
{
Expand Down
6 changes: 6 additions & 0 deletions test/Tests/Framework/IdentityServerHost.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ public IdentityServerHost(string baseAddress = "https://identityserver")
};

public List<ApiScope> ApiScopes { get; set; } = new();
public List<ApiResource> ApiResources { get; set; } = new()
{
new ApiResource("urn:api1"),
new ApiResource("urn:api2")
};

private void ConfigureServices(IServiceCollection services)
{
Expand All @@ -47,6 +52,7 @@ private void ConfigureServices(IServiceCollection services)
})
.AddInMemoryClients(Clients)
.AddInMemoryIdentityResources(IdentityResources)
.AddInMemoryApiResources(ApiResources)
.AddInMemoryApiScopes(ApiScopes);
}

Expand Down
80 changes: 80 additions & 0 deletions test/Tests/UserTokenManagementTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -269,4 +269,84 @@ public async Task Short_token_lifetime_should_trigger_refresh()
token.RefreshToken.ShouldBe("refreshed2_refresh_token");
token.Expiration.ShouldNotBe(DateTimeOffset.MaxValue);
}

[Fact]
public async Task Resources_get_distinct_tokens()
{
var mockHttp = new MockHttpMessageHandler();
AppHost.IdentityServerHttpHandler = mockHttp;

// no resource specified
var initialTokenResponse = new
{
id_token = IdentityServerHost.CreateIdToken("1", "web"),
access_token = "access_token_without_resource",
token_type = "token_type",
expires_in = 3600,
refresh_token = "initial_refresh_token",
};
mockHttp.When("/connect/token")
.WithFormData("grant_type", "authorization_code")
.Respond("application/json", JsonSerializer.Serialize(initialTokenResponse));

// resource 1 specified
var resource1TokenResponse = new
{
access_token = "urn:api1_access_token",
token_type = "token_type1",
expires_in = 3600,
refresh_token = "initial_refresh_token",
};
mockHttp.When("/connect/token")
.WithFormData("grant_type", "refresh_token")
.WithFormData("resource", "urn:api1")
.Respond("application/json", JsonSerializer.Serialize(resource1TokenResponse));

// resource 2 specified
var resource2TokenResponse = new
{
access_token = "urn:api2_access_token",
token_type = "token_type1",
expires_in = 3600,
refresh_token = "initial_refresh_token",
};
mockHttp.When("/connect/token")
.WithFormData("grant_type", "refresh_token")
.WithFormData("resource", "urn:api2")
.Respond("application/json", JsonSerializer.Serialize(resource2TokenResponse));

// setup host
await AppHost.InitializeAsync();
await AppHost.LoginAsync("alice");

// first request - no resource
var response = await AppHost.BrowserClient.GetAsync(AppHost.Url("/user_token"));
var token = await response.Content.ReadFromJsonAsync<UserToken>();

token.ShouldNotBeNull();
token.IsError.ShouldBeFalse();
token.AccessToken.ShouldBe("access_token_without_resource");
token.RefreshToken.ShouldBe("initial_refresh_token");
token.Expiration.ShouldNotBe(DateTimeOffset.MaxValue);

// second request - with resource api1
response = await AppHost.BrowserClient.GetAsync(AppHost.Url("/user_token_with_resource/urn:api1"));
token = await response.Content.ReadFromJsonAsync<UserToken>();

token.ShouldNotBeNull();
token.IsError.ShouldBeFalse();
token.AccessToken.ShouldBe("urn:api1_access_token");
token.RefreshToken.ShouldBe("initial_refresh_token"); // This doesn't change with resources!
token.Expiration.ShouldNotBe(DateTimeOffset.MaxValue);

// third request - with resource api2
response = await AppHost.BrowserClient.GetAsync(AppHost.Url("/user_token_with_resource/urn:api2"));
token = await response.Content.ReadFromJsonAsync<UserToken>();

token.ShouldNotBeNull();
token.IsError.ShouldBeFalse();
token.AccessToken.ShouldBe("urn:api2_access_token");
token.RefreshToken.ShouldBe("initial_refresh_token");
token.Expiration.ShouldNotBe(DateTimeOffset.MaxValue);
}
}

0 comments on commit 29e59eb

Please sign in to comment.