Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions BFF/v4/JsBffSample/.vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
{
"version": "0.2.0",
"compounds": [
{
"name": "Run All",
"configurations": ["BFF", "API"],
"presentation": {
"hidden": false,
"group": "",
"order": 1
}
}
],
"configurations": [
{
"name": "API",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build-api",
"program": "${workspaceFolder}/BackendApiHost/bin/Debug/net8.0/BackendApiHost.dll",
"args": [],
"cwd": "${workspaceFolder}/BackendApiHost",
"env": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"console": "externalTerminal",
},
{
"name": "BFF",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build-bff",
"program": "${workspaceFolder}/FrontendHost/bin/Debug/net8.0/FrontendHost.dll",
"args": [],
"cwd": "${workspaceFolder}/FrontendHost",
"env": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"serverReadyAction": {
"action": "openExternally",
"pattern": "\\bNow listening on:\\s+(https?://\\S+)"
},
"console": "externalTerminal",
}
]
}
43 changes: 43 additions & 0 deletions BFF/v4/JsBffSample/.vscode/tasks.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "build",
"type": "process",
"command": "dotnet",
"args": [
"build",
"${workspaceFolder}/JsBffSample.sln",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"problemMatcher": "$msCompile"
},
{
"label": "build-api",
"type": "process",
"command": "dotnet",
"args": [
"build",
"${workspaceFolder}\\BackendApiHost\\BackendApiHost.csproj",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"problemMatcher": "$msCompile"
},
{
"label": "build-bff",
"type": "process",
"command": "dotnet",
"args": [
"build",
"${workspaceFolder}\\FrontendHost\\FrontendHost.csproj",

"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"problemMatcher": "$msCompile"
}
]

}
12 changes: 12 additions & 0 deletions BFF/v4/JsBffSample/BackendApiHost/BackendApiHost.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>true</ImplicitUsings>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="10.0.2" />
</ItemGroup>

</Project>
39 changes: 39 additions & 0 deletions BFF/v4/JsBffSample/BackendApiHost/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Copyright (c) Duende Software. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers();

builder.Services.AddAuthentication("token")
.AddJwtBearer("token", options =>
{
options.Authority = "https://demo.duendesoftware.com";
options.Audience = "api";

options.MapInboundClaims = false;
});

builder.Services.AddAuthorization(options =>
{
options.AddPolicy("ApiCaller", policy =>
{
policy.RequireClaim("scope", "api");
});

options.AddPolicy("RequireInteractiveUser", policy =>
{
policy.RequireClaim("sub");
});
});

var app = builder.Build();

app.UseRouting();

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

app.MapControllers().RequireAuthorization("ApiCaller");

app.Run();
19 changes: 19 additions & 0 deletions BFF/v4/JsBffSample/BackendApiHost/Properties/launchSettings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:25721",
"sslPort": 44337
}
},
"profiles": {
"BackendApiHost": {
"commandName": "Project",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "https://localhost:5020"
}
}
}
95 changes: 95 additions & 0 deletions BFF/v4/JsBffSample/BackendApiHost/ToDoController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
// Copyright (c) Duende Software. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

namespace BackendApiHost;

[Authorize("RequireInteractiveUser")]
public class ToDoController : ControllerBase
{
private readonly ILogger<ToDoController> _logger;

private static readonly List<ToDo> __data = new List<ToDo>()
{
new ToDo { Id = ToDo.NewId(), Date = DateTimeOffset.UtcNow, Name = "Demo ToDo API", User = "bob" },
new ToDo { Id = ToDo.NewId(), Date = DateTimeOffset.UtcNow.AddHours(1), Name = "Stop Demo", User = "bob" },
new ToDo { Id = ToDo.NewId(), Date = DateTimeOffset.UtcNow.AddHours(4), Name = "Have Dinner", User = "alice" },
};

public ToDoController(ILogger<ToDoController> logger)
{
_logger = logger;
}

[HttpGet("todos")]
public IActionResult GetAll()
{
_logger.LogInformation("GetAll");

return Ok(__data.AsEnumerable());
}

[HttpGet("todos/{id}")]
public IActionResult Get(int id)
{
var item = __data.FirstOrDefault(x => x.Id == id);
if (item == null) return NotFound();

_logger.LogInformation("Get {id}", id);
return Ok(item);
}

[HttpPost("todos")]
public IActionResult Post([FromBody] ToDo model)
{
model.Id = ToDo.NewId();
model.User = $"{User.FindFirst("sub").Value} ({User.FindFirst("name").Value})";

__data.Add(model);
_logger.LogInformation("Added todo");

return Created(Url.Action(nameof(Get), new { id = model.Id }), model);
}

[HttpPut("todos/{id}")]
public IActionResult Put(int id, [FromBody] ToDo model)
{
var item = __data.FirstOrDefault(x => x.Id == id);
if (item == null) return NotFound();

item.Date = model.Date;
item.Name = model.Name;

_logger.LogInformation("Updated todo");

return NoContent();
}

[HttpDelete("todos/{id}")]
public IActionResult Delete(int id)
{
var item = __data.FirstOrDefault(x => x.Id == id);
if (item == null) return NotFound();

__data.Remove(item);
_logger.LogInformation("Delete {id}", id);

return NoContent();
}
}

public class ToDo
{
static int _nextId = 1;
public static int NewId()
{
return _nextId++;
}

public int Id { get; set; }
public DateTimeOffset Date { get; set; }
public string Name { get; set; }
public string User { get; set; }
}
15 changes: 15 additions & 0 deletions BFF/v4/JsBffSample/FrontendHost/FrontendHost.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>true</ImplicitUsings>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Duende.BFF" Version="4.0.2" />
<PackageReference Include="Duende.BFF.Yarp" Version="4.0.2" />

<PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="10.0.2" />
</ItemGroup>

</Project>
81 changes: 81 additions & 0 deletions BFF/v4/JsBffSample/FrontendHost/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
// Copyright (c) Duende Software. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.

using Duende.AccessTokenManagement.OpenIdConnect;
using Duende.Bff;
using Duende.Bff.DynamicFrontends;
using Duende.Bff.Yarp;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers();

builder.Services.AddBff()
.AddRemoteApis()
.ConfigureOpenIdConnect(options =>
{
options.Authority = "https://demo.duendesoftware.com";
options.ClientId = "interactive.confidential";
options.ClientSecret = "secret";
options.ResponseType = "code";
options.ResponseMode = "query";

options.GetClaimsFromUserInfoEndpoint = true;
options.MapInboundClaims = false;
options.SaveTokens = true;
options.DisableTelemetry = true;

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

options.TokenValidationParameters = new()
{
NameClaimType = "name",
RoleClaimType = "role"
};
})
.ConfigureCookies(options =>
{
options.Cookie.Name = "__Host-bff";
options.Cookie.SameSite = SameSiteMode.Strict;
});

builder.Services.AddAuthentication(options =>
{
options.DefaultScheme = BffAuthenticationSchemes.BffCookie;
options.DefaultChallengeScheme = BffAuthenticationSchemes.BffOpenIdConnect;
options.DefaultSignOutScheme = BffAuthenticationSchemes.BffOpenIdConnect;
});

// registers HTTP client that uses the managed user access token
builder.Services.AddUserAccessTokenHttpClient("api_client", configureClient: client =>
{
client.BaseAddress = new Uri("https://localhost:5002/");
});

var app = builder.Build();

app.UseDefaultFiles();
app.UseStaticFiles();

app.UseRouting();

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

app.MapBffManagementEndpoints();

// if you want the TODOs API local
app.MapControllers()
.RequireAuthorization()
.AsBffApiEndpoint();

// if you want the TODOs API remote
// app.MapRemoteBffApiEndpoint("/todos", "https://localhost:5020/todos")
// .RequireAccessToken(Duende.Bff.TokenType.User);

app.Run();
20 changes: 20 additions & 0 deletions BFF/v4/JsBffSample/FrontendHost/Properties/launchSettings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:32659",
"sslPort": 44348
}
},
"profiles": {
"JsBffSample": {
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "https://localhost:5010"
}
}
}
Loading
Loading