Skip to content
This repository has been archived by the owner on Nov 18, 2022. It is now read-only.

Commit

Permalink
Add support for resource indicators (#173)
Browse files Browse the repository at this point in the history
* update IdM

* update signatures

* update user store

* Re-org samples

* re-org samples 2

* miminmal working sample

* add support for handlers per resource, fix storage
  • Loading branch information
leastprivilege authored Jan 5, 2021
1 parent ecd37ce commit 19ec3e6
Show file tree
Hide file tree
Showing 171 changed files with 39,904 additions and 65 deletions.
23 changes: 19 additions & 4 deletions IdentityModel.AspNetCore.sln
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,19 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{054D2D66-997
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{B8F1A24B-007A-4735-B33E-9528662EDCAD}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TokenManagement3", "samples\TokenManagement3\TokenManagement3.csproj", "{7BF76B2C-3D3B-4B54-A7A4-9311E959BEDE}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Web3", "samples\Web3\Web3.csproj", "{7BF76B2C-3D3B-4B54-A7A4-9311E959BEDE}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{A7311E40-E3DC-4FE8-906C-FC943B7E7444}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tests", "test\Tests\Tests.csproj", "{A891D28E-52E0-4B93-BE47-92DE2B9CB655}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WorkerService3", "samples\WorkerService3\WorkerService3.csproj", "{F44432B9-0846-4A2A-80B8-6B121A1D8C38}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Worker3", "samples\Worker3\Worker3.csproj", "{F44432B9-0846-4A2A-80B8-6B121A1D8C38}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WorkerService5", "samples\WorkerService5\WorkerService5.csproj", "{2F0D8378-1ADA-4F0B-B8E6-7E1D97F1CBCC}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Worker5", "samples\Worker5\Worker5.csproj", "{2F0D8378-1ADA-4F0B-B8E6-7E1D97F1CBCC}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TokenManagement5", "samples\TokenManagement5\TokenManagement5.csproj", "{0F751A6E-EFB1-483E-BDF5-008644C07C07}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Web5", "samples\Web5\Web5.csproj", "{0F751A6E-EFB1-483E-BDF5-008644C07C07}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebMultiResource", "samples\WebMultiResource\WebMultiResource.csproj", "{A91C34AD-34D7-44C9-B643-1257F2162969}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand Down Expand Up @@ -103,6 +105,18 @@ Global
{0F751A6E-EFB1-483E-BDF5-008644C07C07}.Release|x64.Build.0 = Release|Any CPU
{0F751A6E-EFB1-483E-BDF5-008644C07C07}.Release|x86.ActiveCfg = Release|Any CPU
{0F751A6E-EFB1-483E-BDF5-008644C07C07}.Release|x86.Build.0 = Release|Any CPU
{A91C34AD-34D7-44C9-B643-1257F2162969}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A91C34AD-34D7-44C9-B643-1257F2162969}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A91C34AD-34D7-44C9-B643-1257F2162969}.Debug|x64.ActiveCfg = Debug|Any CPU
{A91C34AD-34D7-44C9-B643-1257F2162969}.Debug|x64.Build.0 = Debug|Any CPU
{A91C34AD-34D7-44C9-B643-1257F2162969}.Debug|x86.ActiveCfg = Debug|Any CPU
{A91C34AD-34D7-44C9-B643-1257F2162969}.Debug|x86.Build.0 = Debug|Any CPU
{A91C34AD-34D7-44C9-B643-1257F2162969}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A91C34AD-34D7-44C9-B643-1257F2162969}.Release|Any CPU.Build.0 = Release|Any CPU
{A91C34AD-34D7-44C9-B643-1257F2162969}.Release|x64.ActiveCfg = Release|Any CPU
{A91C34AD-34D7-44C9-B643-1257F2162969}.Release|x64.Build.0 = Release|Any CPU
{A91C34AD-34D7-44C9-B643-1257F2162969}.Release|x86.ActiveCfg = Release|Any CPU
{A91C34AD-34D7-44C9-B643-1257F2162969}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -114,6 +128,7 @@ Global
{F44432B9-0846-4A2A-80B8-6B121A1D8C38} = {B8F1A24B-007A-4735-B33E-9528662EDCAD}
{2F0D8378-1ADA-4F0B-B8E6-7E1D97F1CBCC} = {B8F1A24B-007A-4735-B33E-9528662EDCAD}
{0F751A6E-EFB1-483E-BDF5-008644C07C07} = {B8F1A24B-007A-4735-B33E-9528662EDCAD}
{A91C34AD-34D7-44C9-B643-1257F2162969} = {B8F1A24B-007A-4735-B33E-9528662EDCAD}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {7A4E29A0-CAE8-45E9-817B-AF126F85EE15}
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
using Polly;
using System;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;

namespace MvcCode
{
Expand Down Expand Up @@ -79,7 +78,7 @@ public void ConfigureServices(IServiceCollection services)
}));

// registers HTTP client that uses the managed user access token
services.AddUserAccessTokenClient("user_client", client =>
services.AddUserAccessTokenClient("user_client", configureClient: client =>
{
client.BaseAddress = new Uri("https://demo.identityserver.io/api/");
});
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<RootNamespace>TokenManagement3</RootNamespace>
</PropertyGroup>


Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
using Polly;
using System;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;

namespace MvcCode
{
Expand Down Expand Up @@ -79,7 +78,7 @@ public void ConfigureServices(IServiceCollection services)
}));

// registers HTTP client that uses the managed user access token
services.AddUserAccessTokenClient("user_client", client =>
services.AddUserAccessTokenClient("user_client", configureClient: client =>
{
client.BaseAddress = new Uri("https://demo.identityserver.io/api/");
});
Expand Down
File renamed without changes.
20 changes: 20 additions & 0 deletions samples/Web5/Web5.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<RootNamespace>TokenManagement5</RootNamespace>
</PropertyGroup>


<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="5.0.0" />
<PackageReference Include="Microsoft.Extensions.Http.Polly" Version="5.0.0" />

<PackageReference Include="Serilog.AspNetCore" Version="3.4.0" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\src\IdentityModel.AspNetCore.csproj" />
</ItemGroup>

</Project>
74 changes: 74 additions & 0 deletions samples/WebMultiResource/Controllers/HomeController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;

namespace MvcCode.Controllers
{
public class HomeController : Controller
{
private readonly IHttpClientFactory _httpClientFactory;

public HomeController(IHttpClientFactory httpClientFactory)
{
_httpClientFactory = httpClientFactory;
}

[AllowAnonymous]
public IActionResult Index() => View();

public IActionResult Secure() => View();

public IActionResult Logout() => SignOut("cookie", "oidc");

public async Task<IActionResult> CallApiAsUser()
{
var client = _httpClientFactory.CreateClient("user_client");

var response = await client.GetStringAsync("test");
ViewBag.Json = JArray.Parse(response).ToString();

return View("CallApi");
}

public async Task<IActionResult> CallApiAsUserResource3()
{
var client = _httpClientFactory.CreateClient("user_client_resource3");

var response = await client.GetStringAsync("test");
ViewBag.Json = JArray.Parse(response).ToString();

return View("CallApi");
}

public async Task<IActionResult> CallApiAsUserTyped([FromServices] TypedUserClient client)
{
var response = await client.CallApi();
ViewBag.Json = JArray.Parse(response).ToString();

return View("CallApi");
}

[AllowAnonymous]
public async Task<IActionResult> CallApiAsClient()
{
var client = _httpClientFactory.CreateClient("client");

var response = await client.GetStringAsync("test");
ViewBag.Json = JArray.Parse(response).ToString();

return View("CallApi");
}

[AllowAnonymous]
public async Task<IActionResult> CallApiAsClientTyped([FromServices] TypedClientClient client)
{
var response = await client.CallApi();
ViewBag.Json = JArray.Parse(response).ToString();

return View("CallApi");
}
}
}
33 changes: 33 additions & 0 deletions samples/WebMultiResource/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;
using Serilog;
using Serilog.Events;
using Serilog.Sinks.SystemConsole.Themes;

namespace MvcCode
{
public class Program
{
public static void Main(string[] args)
{
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
.MinimumLevel.Override("System", LogEventLevel.Error)
.MinimumLevel.Override("Microsoft", LogEventLevel.Error)
.MinimumLevel.Override("System.Net.Http", LogEventLevel.Information)
.MinimumLevel.Override("Microsoft.AspNetCore.Authentication", LogEventLevel.Information)
.WriteTo.Console(theme: AnsiConsoleTheme.Code)
.CreateLogger();

CreateHostBuilder(args).Build().Run();
}

public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseSerilog()
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
}
12 changes: 12 additions & 0 deletions samples/WebMultiResource/Properties/launchSettings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"profiles": {
"MvcCode": {
"commandName": "Project",
"launchBrowser": true,
"applicationUrl": "https://localhost:5001;http://localhost:5000",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
142 changes: 142 additions & 0 deletions samples/WebMultiResource/Startup.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.IdentityModel.Tokens;
using Polly;
using System;
using System.IdentityModel.Tokens.Jwt;
using System.Threading.Tasks;

namespace MvcCode
{
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
JwtSecurityTokenHandler.DefaultMapInboundClaims = false;

services.AddControllersWithViews();

services.AddAuthentication(options =>
{
options.DefaultScheme = "cookie";
options.DefaultChallengeScheme = "oidc";
})
.AddCookie("cookie", options =>
{
options.Cookie.Name = "mvccode";

options.Events.OnSigningOut = async e =>
{
await e.HttpContext.RevokeUserRefreshTokenAsync();
};
})
.AddOpenIdConnect("oidc", options =>
{
options.Authority = "https://demo.duendesoftware.com";

options.ClientId = "interactive.confidential.short";
options.ClientSecret = "secret";

options.ResponseType = "code";
options.ResponseMode = "query";

options.Scope.Clear();
options.Scope.Add("openid");
options.Scope.Add("profile");
options.Scope.Add("email");
options.Scope.Add("offline_access");

options.Scope.Add("resource1.scope1");
options.Scope.Add("resource2.scope1");
options.Scope.Add("resource3.scope1");
options.Scope.Add("scope3");
options.Scope.Add("scope4");

// keeps id_token smaller
options.GetClaimsFromUserInfoEndpoint = true;
options.SaveTokens = true;

options.TokenValidationParameters = new TokenValidationParameters
{
NameClaimType = "name",
RoleClaimType = "role"
};

options.Events.OnRedirectToIdentityProvider = e =>
{
// prepare token requests, so a resource specific token can be requested
e.ProtocolMessage.Resource = "urn:resource3";

return Task.CompletedTask;
};
});

// adds user and client access token management
services.AddAccessTokenManagement(options =>
{
// ask for a token for a specific resource
//options.Client.Resource = "urn:resource3";

// ask for a specific scope
//options.Client.Scope = "shared.scope";
})
.ConfigureBackchannelHttpClient()
.AddTransientHttpErrorPolicy(policy => policy.WaitAndRetryAsync(new[]
{
TimeSpan.FromSeconds(1),
TimeSpan.FromSeconds(2),
TimeSpan.FromSeconds(3)
}));

// registers HTTP client that uses the managed user access token
services.AddUserAccessTokenClient("user_client", configureClient: client =>
{
client.BaseAddress = new Uri("https://demo.duendesoftware.com/api/");
});

// registers HTTP client that uses the managed user access token for a specific resource
services.AddUserAccessTokenClient("user_client_resource3", "urn:resource3", configureClient: client =>
{
client.BaseAddress = new Uri("https://demo.duendesoftware.com/api/");
});

// registers HTTP client that uses the managed client access token
services.AddClientAccessTokenClient("client", configureClient: client =>
{
client.BaseAddress = new Uri("https://demo.duendesoftware.com/api/");
});

// registers a typed HTTP client with token management support
services.AddHttpClient<TypedUserClient>(client =>
{
client.BaseAddress = new Uri("https://demo.duendesoftware.com/api/");
})
.AddUserAccessTokenHandler();

services.AddHttpClient<TypedClientClient>(client =>
{
client.BaseAddress = new Uri("https://demo.duendesoftware.com/api/");
})
.AddClientAccessTokenHandler();
}

public void Configure(IApplicationBuilder app)
{
app.UseDeveloperExceptionPage();
app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseAuthentication();
app.UseAuthorization();

app.UseEndpoints(endpoints =>
{
endpoints.MapDefaultControllerRoute()
.RequireAuthorization();
});
}
}
}
Loading

0 comments on commit 19ec3e6

Please sign in to comment.