-
Notifications
You must be signed in to change notification settings - Fork 270
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added BFF token exchange/ITokenRetriever sample
- Loading branch information
1 parent
94d524b
commit 77d4755
Showing
133 changed files
with
58,335 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
{ | ||
"version": "0.2.0", | ||
"compounds": [ | ||
{ | ||
"name": "All", | ||
"configurations": ["IdentityServer", "API", "BFF"], | ||
"presentation": { | ||
"hidden": false, | ||
"group": "compunds", | ||
} | ||
}, | ||
], | ||
"configurations": [ | ||
{ | ||
"name": "IdentityServer", | ||
"type": "coreclr", | ||
"request": "launch", | ||
"preLaunchTask": "build-identityserver", | ||
"program": "${workspaceFolder}/TokenExchange.IdentityServer/bin/Debug/net6.0/TokenExchange.IdentityServer.dll", | ||
"args": [], | ||
"cwd": "${workspaceFolder}/TokenExchange.IdentityServer", | ||
"env": { | ||
"ASPNETCORE_ENVIRONMENT": "Development" | ||
}, | ||
"console": "externalTerminal", | ||
}, | ||
{ | ||
"name": "API", | ||
"type": "coreclr", | ||
"request": "launch", | ||
"preLaunchTask": "build-api", | ||
"program": "${workspaceFolder}/TokenExchange.Api/bin/Debug/net6.0/TokenExchange.Api.dll", | ||
"args": [], | ||
"cwd": "${workspaceFolder}/TokenExchange.Api", | ||
"env": { | ||
"ASPNETCORE_ENVIRONMENT": "Development" | ||
}, | ||
"console": "externalTerminal", | ||
}, | ||
{ | ||
"name": "BFF", | ||
"type": "coreclr", | ||
"request": "launch", | ||
"preLaunchTask": "build-bff", | ||
"program": "${workspaceFolder}/TokenExchange.Bff/bin/Debug/net6.0/TokenExchange.Bff.dll", | ||
"args": [], | ||
"cwd": "${workspaceFolder}/TokenExchange.Bff", | ||
"env": { | ||
"ASPNETCORE_ENVIRONMENT": "Development" | ||
}, | ||
"console": "externalTerminal", | ||
}, | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
{ | ||
"version": "2.0.0", | ||
"tasks": [ | ||
{ | ||
"label": "build", | ||
"type": "process", | ||
"command": "dotnet", | ||
"args": [ | ||
"build", | ||
"${workspaceFolder}/TokenExchange.sln", | ||
"/property:GenerateFullPaths=true", | ||
"/consoleloggerparameters:NoSummary" | ||
], | ||
"problemMatcher": "$msCompile" | ||
}, | ||
{ | ||
"label": "build-identityserver", | ||
"type": "process", | ||
"command": "dotnet", | ||
"args": [ | ||
"build", | ||
"${workspaceFolder}/TokenExchange.IdentityServer/TokenExchange.IdentityServer.csproj", | ||
"/property:GenerateFullPaths=true", | ||
"/consoleloggerparameters:NoSummary" | ||
], | ||
"problemMatcher": "$msCompile" | ||
}, | ||
{ | ||
"label": "build-api", | ||
"type": "process", | ||
"command": "dotnet", | ||
"args": [ | ||
"build", | ||
"${workspaceFolder}/TokenExchange.Api/TokenExchange.Api.csproj", | ||
"/property:GenerateFullPaths=true", | ||
"/consoleloggerparameters:NoSummary" | ||
], | ||
"problemMatcher": "$msCompile" | ||
}, | ||
{ | ||
"label": "build-bff", | ||
"type": "process", | ||
"command": "dotnet", | ||
"args": [ | ||
"build", | ||
"${workspaceFolder}/TokenExchange.Bff/TokenExchange.Bff.csproj", | ||
"/property:GenerateFullPaths=true", | ||
"/consoleloggerparameters:NoSummary" | ||
], | ||
"problemMatcher": "$msCompile" | ||
}, | ||
] | ||
|
||
} |
45 changes: 45 additions & 0 deletions
45
IdentityServer/v6/BFF/TokenExchange/TokenExchange.Api/EchoController.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
// Copyright (c) Duende Software. All rights reserved. | ||
// See LICENSE in the project root for license information. | ||
|
||
using Microsoft.AspNetCore.Mvc; | ||
using System; | ||
using Microsoft.AspNetCore.Authorization; | ||
|
||
namespace TokenExchange.Api | ||
{ | ||
[AllowAnonymous] | ||
public class EchoController : ControllerBase | ||
{ | ||
[HttpGet("{**catch-all}")] | ||
public IActionResult Get() | ||
{ | ||
string message; | ||
var sub = User.FindFirst("sub"); | ||
|
||
if (!User.Identity.IsAuthenticated) | ||
{ | ||
message = "Hello, anonymous caller"; | ||
} | ||
else if (sub != null) | ||
{ | ||
var userName = User.FindFirst("name"); | ||
message = $"Hello user, {userName.Value}"; | ||
} | ||
else | ||
{ | ||
var client = User.FindFirst("client_id"); | ||
message = $"Hello client, {client.Value}"; | ||
} | ||
|
||
var response = new | ||
{ | ||
path = Request.Path.Value, | ||
message = message, | ||
time = DateTime.UtcNow.ToString(), | ||
headers = Request.Headers | ||
}; | ||
|
||
return Ok(response); | ||
} | ||
} | ||
} |
58 changes: 58 additions & 0 deletions
58
IdentityServer/v6/BFF/TokenExchange/TokenExchange.Api/Program.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
// Copyright (c) Duende Software. All rights reserved. | ||
// See LICENSE in the project root for license information. | ||
|
||
using System; | ||
using System.Diagnostics; | ||
using Microsoft.AspNetCore.Hosting; | ||
using Microsoft.Extensions.Hosting; | ||
using Serilog; | ||
using Serilog.Events; | ||
using Serilog.Sinks.SystemConsole.Themes; | ||
|
||
namespace TokenExchange.Api | ||
{ | ||
public class Program | ||
{ | ||
public static int Main(string[] args) | ||
{ | ||
Console.Title = "Simple API"; | ||
Activity.DefaultIdFormat = ActivityIdFormat.W3C; | ||
|
||
Log.Logger = new LoggerConfiguration() | ||
.MinimumLevel.Debug() | ||
.MinimumLevel.Override("Microsoft", LogEventLevel.Warning) | ||
.MinimumLevel.Override("Microsoft.Hosting.Lifetime", LogEventLevel.Information) | ||
.MinimumLevel.Override("System", LogEventLevel.Warning) | ||
.MinimumLevel.Override("Microsoft.AspNetCore.Authentication", LogEventLevel.Information) | ||
.Enrich.FromLogContext() | ||
.WriteTo.Console(outputTemplate: "[{Timestamp:HH:mm:ss} {Level}] {SourceContext}{NewLine}{Message:lj}{NewLine}{Exception}{NewLine}", theme: AnsiConsoleTheme.Code) | ||
.CreateLogger(); | ||
|
||
try | ||
{ | ||
Log.Information("Starting host..."); | ||
CreateHostBuilder(args).Build().Run(); | ||
return 0; | ||
} | ||
catch (Exception ex) | ||
{ | ||
Log.Fatal(ex, "Host terminated unexpectedly."); | ||
return 1; | ||
} | ||
finally | ||
{ | ||
Log.CloseAndFlush(); | ||
} | ||
} | ||
|
||
public static IHostBuilder CreateHostBuilder(string[] args) | ||
{ | ||
return Host.CreateDefaultBuilder(args) | ||
.UseSerilog() | ||
.ConfigureWebHostDefaults(webBuilder => | ||
{ | ||
webBuilder.UseStartup<Startup>(); | ||
}); | ||
} | ||
} | ||
} |
13 changes: 13 additions & 0 deletions
13
IdentityServer/v6/BFF/TokenExchange/TokenExchange.Api/Properties/launchSettings.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
{ | ||
"profiles": { | ||
"Api": { | ||
"commandName": "Project", | ||
"dotnetRunMessages": true, | ||
"launchBrowser": false, | ||
"applicationUrl": "https://localhost:7001", | ||
"environmentVariables": { | ||
"ASPNETCORE_ENVIRONMENT": "Development" | ||
} | ||
} | ||
} | ||
} |
75 changes: 75 additions & 0 deletions
75
IdentityServer/v6/BFF/TokenExchange/TokenExchange.Api/Startup.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
// Copyright (c) Duende Software. All rights reserved. | ||
// See LICENSE in the project root for license information. | ||
|
||
using Microsoft.AspNetCore.Builder; | ||
using Microsoft.AspNetCore.Hosting; | ||
using Microsoft.AspNetCore.HttpOverrides; | ||
using Microsoft.Extensions.DependencyInjection; | ||
using Microsoft.Extensions.Hosting; | ||
using Microsoft.IdentityModel.Tokens; | ||
using Serilog; | ||
|
||
namespace TokenExchange.Api | ||
{ | ||
public class Startup | ||
{ | ||
public void ConfigureServices(IServiceCollection services) | ||
{ | ||
services.AddControllers(); | ||
|
||
services.AddAuthentication("token") | ||
.AddJwtBearer("token", options => | ||
{ | ||
options.Authority = "https://localhost:5001"; | ||
options.MapInboundClaims = false; | ||
options.TokenValidationParameters = new TokenValidationParameters() | ||
{ | ||
ValidateAudience = false, | ||
ValidTypes = new[] { "at+jwt" }, | ||
NameClaimType = "name", | ||
RoleClaimType = "role" | ||
}; | ||
}); | ||
|
||
services.AddAuthorization(options => | ||
{ | ||
options.AddPolicy("ApiCaller", policy => | ||
{ | ||
policy.RequireClaim("scope", "api"); | ||
}); | ||
options.AddPolicy("RequireInteractiveUser", policy => | ||
{ | ||
policy.RequireClaim("sub"); | ||
}); | ||
}); | ||
} | ||
|
||
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) | ||
{ | ||
app.UseForwardedHeaders(new ForwardedHeadersOptions | ||
{ | ||
ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto | ForwardedHeaders.XForwardedHost, | ||
}); | ||
|
||
app.UseSerilogRequestLogging(); | ||
|
||
if (env.IsDevelopment()) | ||
{ | ||
app.UseDeveloperExceptionPage(); | ||
} | ||
|
||
app.UseRouting(); | ||
app.UseAuthentication(); | ||
app.UseAuthorization(); | ||
|
||
app.UseEndpoints(endpoints => | ||
{ | ||
endpoints.MapControllers() | ||
.RequireAuthorization("ApiCaller"); | ||
}); | ||
} | ||
} | ||
} |
12 changes: 12 additions & 0 deletions
12
IdentityServer/v6/BFF/TokenExchange/TokenExchange.Api/TokenExchange.Api.csproj
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
<Project Sdk="Microsoft.NET.Sdk.Web"> | ||
|
||
<PropertyGroup> | ||
<TargetFramework>net6.0</TargetFramework> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="IdentityModel" Version="6.1.0" /> | ||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="6.0.9" /> | ||
<PackageReference Include="Serilog.AspNetCore" Version="6.0.1" /> | ||
</ItemGroup> | ||
</Project> |
52 changes: 52 additions & 0 deletions
52
IdentityServer/v6/BFF/TokenExchange/TokenExchange.Bff/ImpersonationAccessTokenRetriever.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
// Copyright (c) Duende Software. All rights reserved. | ||
// See LICENSE in the project root for license information. | ||
|
||
using System.Net.Http; | ||
using System.Threading.Tasks; | ||
using Duende.Bff; | ||
using IdentityModel; | ||
using IdentityModel.Client; | ||
using Microsoft.Extensions.Logging; | ||
|
||
namespace TokenExchange.Bff; | ||
|
||
public class ImpersonationAccessTokenRetriever : DefaultAccessTokenRetriever | ||
{ | ||
public ImpersonationAccessTokenRetriever(ILogger<ImpersonationAccessTokenRetriever> logger) : base(logger) | ||
{ | ||
} | ||
|
||
public override async Task<AccessTokenResult> GetAccessToken(AccessTokenRetrievalContext context) | ||
{ | ||
var result = await base.GetAccessToken(context); | ||
|
||
if(result is BearerTokenResult bearerToken) | ||
{ | ||
var client = new HttpClient(); | ||
var exchangeResponse = await client.RequestTokenExchangeTokenAsync(new TokenExchangeTokenRequest | ||
{ | ||
Address = "https://localhost:5001/connect/token", | ||
GrantType = OidcConstants.GrantTypes.TokenExchange, | ||
|
||
ClientId = "spa", | ||
ClientSecret = "secret", | ||
|
||
SubjectToken = bearerToken.AccessToken, | ||
SubjectTokenType = OidcConstants.TokenTypeIdentifiers.AccessToken | ||
}); | ||
if(exchangeResponse.IsError) | ||
{ | ||
return new AccessTokenRetrievalError($"Token exchanged failed: {exchangeResponse.ErrorDescription}"); | ||
} | ||
if(exchangeResponse.AccessToken is null) | ||
{ | ||
return new AccessTokenRetrievalError("Token exchanged failed. Access token is null"); | ||
} else | ||
{ | ||
return new BearerTokenResult(exchangeResponse.AccessToken); | ||
} | ||
} | ||
|
||
return result; | ||
} | ||
} |
Oops, something went wrong.