Skip to content
This repository was archived by the owner on Dec 21, 2024. It is now read-only.

Commit 1ccba18

Browse files
add BFF template
1 parent 5e69486 commit 1ccba18

11 files changed

+427
-8
lines changed

Duende.IdentityServer.Templates.sln

+8-8
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11

22
Microsoft Visual Studio Solution File, Format Version 12.00
3-
# Visual Studio 15
4-
VisualStudioVersion = 15.0.27130.2010
3+
# Visual Studio Version 16
4+
VisualStudioVersion = 16.0.31112.23
55
MinimumVisualStudioVersion = 10.0.40219.1
66
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{5B4906FF-64CC-4A42-A145-221F083EE165}"
77
EndProject
@@ -13,7 +13,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IdentityServerAspNetIdentit
1313
EndProject
1414
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IdentityServerEntityFramework", "src\IdentityServerEntityFramework\IdentityServerEntityFramework.csproj", "{46000F46-B039-49F3-AACD-42E4FBC11E94}"
1515
EndProject
16-
16+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BffJs", "src\BffJs\BffJs.csproj", "{D471E5B4-1D16-4861-81B9-5DD4DC0786BA}"
17+
EndProject
1718
Global
1819
GlobalSection(SolutionConfigurationPlatforms) = preSolution
1920
Debug|Any CPU = Debug|Any CPU
@@ -36,15 +37,14 @@ Global
3637
{46000F46-B039-49F3-AACD-42E4FBC11E94}.Debug|Any CPU.Build.0 = Debug|Any CPU
3738
{46000F46-B039-49F3-AACD-42E4FBC11E94}.Release|Any CPU.ActiveCfg = Release|Any CPU
3839
{46000F46-B039-49F3-AACD-42E4FBC11E94}.Release|Any CPU.Build.0 = Release|Any CPU
39-
{5C903922-2014-40F6-920A-2E02E0D7F5E4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
40-
{5C903922-2014-40F6-920A-2E02E0D7F5E4}.Debug|Any CPU.Build.0 = Debug|Any CPU
41-
{5C903922-2014-40F6-920A-2E02E0D7F5E4}.Release|Any CPU.ActiveCfg = Release|Any CPU
42-
{5C903922-2014-40F6-920A-2E02E0D7F5E4}.Release|Any CPU.Build.0 = Release|Any CPU
40+
{D471E5B4-1D16-4861-81B9-5DD4DC0786BA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
41+
{D471E5B4-1D16-4861-81B9-5DD4DC0786BA}.Debug|Any CPU.Build.0 = Debug|Any CPU
42+
{D471E5B4-1D16-4861-81B9-5DD4DC0786BA}.Release|Any CPU.ActiveCfg = Release|Any CPU
43+
{D471E5B4-1D16-4861-81B9-5DD4DC0786BA}.Release|Any CPU.Build.0 = Release|Any CPU
4344
EndGlobalSection
4445
GlobalSection(SolutionProperties) = preSolution
4546
HideSolutionNode = FALSE
4647
EndGlobalSection
47-
4848
GlobalSection(ExtensibilityGlobals) = postSolution
4949
SolutionGuid = {32B6CD87-BBD9-4A01-82E9-BA1579E4A083}
5050
EndGlobalSection

nuget.config

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<configuration>
3+
<packageSources>
4+
<add key="Duende IdentityServer CI" value="https://www.myget.org/F/duende_identityserver/api/v3/index.json" />
5+
</packageSources>
6+
</configuration>
+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"author": "Duende Software",
3+
"classifications": [
4+
"Web",
5+
"IdentityServer"
6+
],
7+
"name": "Duende BFF with JavaScript",
8+
"identity": "IdentityServer.BFF.JavaScript",
9+
"groupIdentity": "IdentityServer.BFF.JavaScript",
10+
"shortName": "bffjs",
11+
"tags": {
12+
"language": "C#",
13+
"type": "project"
14+
},
15+
16+
"sourceName": "BffJs",
17+
"preferNameDirectory": "true",
18+
"primaryOutputs": [ { "path": "BffJs.csproj" } ]
19+
}

src/BffJs/BffJs.csproj

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<Project Sdk="Microsoft.NET.Sdk.Web">
2+
3+
<PropertyGroup>
4+
<TargetFramework>netcoreapp3.1</TargetFramework>
5+
</PropertyGroup>
6+
7+
<ItemGroup>
8+
<PackageReference Include="Duende.BFF" Version="1.0.0-preview.1" />
9+
<PackageReference Include="Serilog.AspNetCore" Version="4.0.0" />
10+
11+
<PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="3.1.13" />
12+
</ItemGroup>
13+
14+
</Project>

src/BffJs/Program.cs

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
using Microsoft.AspNetCore.Hosting;
2+
using Microsoft.Extensions.Hosting;
3+
using Serilog;
4+
using Serilog.Events;
5+
using Serilog.Sinks.SystemConsole.Themes;
6+
using System;
7+
8+
namespace BffJs
9+
{
10+
public class Program
11+
{
12+
public static int Main(string[] args)
13+
{
14+
Log.Logger = new LoggerConfiguration()
15+
.MinimumLevel.Information()
16+
.MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
17+
.MinimumLevel.Override("Microsoft.Hosting.Lifetime", LogEventLevel.Information)
18+
.MinimumLevel.Override("Microsoft.AspNetCore.Authentication", LogEventLevel.Information)
19+
.MinimumLevel.Override("IdentityModel", LogEventLevel.Debug)
20+
.Enrich.FromLogContext()
21+
.WriteTo.Console(outputTemplate: "[{Timestamp:HH:mm:ss} {Level}] {SourceContext}{NewLine}{Message:lj}{NewLine}{Exception}{NewLine}", theme: AnsiConsoleTheme.Code)
22+
.CreateLogger();
23+
24+
try
25+
{
26+
Log.Information("Starting host...");
27+
CreateHostBuilder(args).Build().Run();
28+
return 0;
29+
}
30+
catch (Exception ex)
31+
{
32+
Log.Fatal(ex, "Host terminated unexpectedly.");
33+
return 1;
34+
}
35+
finally
36+
{
37+
Log.CloseAndFlush();
38+
}
39+
}
40+
41+
public static IHostBuilder CreateHostBuilder(string[] args)
42+
{
43+
return Host.CreateDefaultBuilder(args)
44+
.UseSerilog()
45+
.ConfigureWebHostDefaults(webBuilder =>
46+
{
47+
webBuilder.UseStartup<Startup>();
48+
});
49+
}
50+
}
51+
}
+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"profiles": {
3+
"BffJs": {
4+
"commandName": "Project",
5+
"launchBrowser": true,
6+
"applicationUrl": "https://localhost:5001",
7+
"environmentVariables": {
8+
"ASPNETCORE_ENVIRONMENT": "Development"
9+
}
10+
}
11+
}
12+
}

src/BffJs/Startup.cs

+91
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
using Microsoft.AspNetCore.Builder;
2+
using Microsoft.AspNetCore.Hosting;
3+
using Microsoft.AspNetCore.Http;
4+
using Microsoft.Extensions.Configuration;
5+
using Microsoft.Extensions.DependencyInjection;
6+
using Microsoft.Extensions.Hosting;
7+
using System.IdentityModel.Tokens.Jwt;
8+
9+
namespace BffJs
10+
{
11+
public class Startup
12+
{
13+
private readonly IWebHostEnvironment _environment;
14+
15+
public Startup(IConfiguration configuration, IWebHostEnvironment environment)
16+
{
17+
_environment = environment;
18+
19+
JwtSecurityTokenHandler.DefaultMapInboundClaims = false;
20+
}
21+
22+
public void ConfigureServices(IServiceCollection services)
23+
{
24+
services.AddControllers();
25+
26+
// add BFF services and server-side session management
27+
services.AddBff()
28+
.AddServerSideSessions();
29+
30+
services.AddAuthentication(options =>
31+
{
32+
options.DefaultScheme = "cookie";
33+
options.DefaultChallengeScheme = "oidc";
34+
options.DefaultSignOutScheme = "oidc";
35+
})
36+
.AddCookie("cookie", options =>
37+
{
38+
options.Cookie.Name = "__Host-bff";
39+
options.Cookie.SameSite = SameSiteMode.Strict;
40+
})
41+
.AddOpenIdConnect("oidc", options =>
42+
{
43+
options.Authority = "https://demo.duendesoftware.com";
44+
options.ClientId = "interactive.confidential";
45+
options.ClientSecret = "secret";
46+
options.ResponseType = "code";
47+
options.ResponseMode = "query";
48+
49+
options.GetClaimsFromUserInfoEndpoint = true;
50+
options.SaveTokens = true;
51+
52+
options.Scope.Clear();
53+
options.Scope.Add("openid");
54+
options.Scope.Add("profile");
55+
options.Scope.Add("api");
56+
options.Scope.Add("offline_access");
57+
});
58+
}
59+
60+
public void Configure(IApplicationBuilder app)
61+
{
62+
if (_environment.IsDevelopment())
63+
{
64+
app.UseDeveloperExceptionPage();
65+
}
66+
67+
app.UseDefaultFiles();
68+
app.UseStaticFiles();
69+
70+
app.UseAuthentication();
71+
app.UseRouting();
72+
73+
// add CSRF protection and status code handling for API endpoints
74+
app.UseBff();
75+
app.UseAuthorization();
76+
77+
app.UseEndpoints(endpoints =>
78+
{
79+
endpoints.MapControllers()
80+
.RequireAuthorization()
81+
.AsLocalBffApiEndpoint();
82+
83+
endpoints.MapBffManagementEndpoints("/bff");
84+
85+
// enable proxying to remote API
86+
//endpoints.MapRemoteBffApiEndpoint("/api", "https://api.mycompany.com")
87+
// .RequireAccessToken();
88+
});
89+
}
90+
}
91+
}

src/BffJs/ToDoController.cs

+80
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
using Microsoft.AspNetCore.Mvc;
2+
using System;
3+
using System.Collections.Generic;
4+
using System.Linq;
5+
6+
namespace BffJs
7+
{
8+
public class ToDoController : ControllerBase
9+
{
10+
private static readonly List<ToDo> __data = new List<ToDo>()
11+
{
12+
new ToDo { Id = ToDo.NewId(), Date = DateTimeOffset.UtcNow, Name = "Demo ToDo API", User = "bob" },
13+
new ToDo { Id = ToDo.NewId(), Date = DateTimeOffset.UtcNow.AddHours(1), Name = "Stop Demo", User = "bob" },
14+
new ToDo { Id = ToDo.NewId(), Date = DateTimeOffset.UtcNow.AddHours(4), Name = "Have Dinner", User = "alice" },
15+
};
16+
17+
[HttpGet("todos")]
18+
public IActionResult GetAll()
19+
{
20+
return Ok(__data.AsEnumerable());
21+
}
22+
23+
[HttpGet("todos/{id}")]
24+
public IActionResult Get(int id)
25+
{
26+
var item = __data.FirstOrDefault(x => x.Id == id);
27+
if (item == null) return NotFound();
28+
29+
return Ok(item);
30+
}
31+
32+
[HttpPost("todos")]
33+
public IActionResult Post([FromBody] ToDo model)
34+
{
35+
model.Id = ToDo.NewId();
36+
model.User = $"{User.FindFirst("sub").Value} ({User.FindFirst("name").Value})";
37+
38+
__data.Add(model);
39+
40+
return Created(Url.Action(nameof(Get), new { id = model.Id }), model);
41+
}
42+
43+
[HttpPut("todos/{id}")]
44+
public IActionResult Put(int id, [FromBody] ToDo model)
45+
{
46+
var item = __data.FirstOrDefault(x => x.Id == id);
47+
if (item == null) return NotFound();
48+
49+
item.Date = model.Date;
50+
item.Name = model.Name;
51+
52+
return NoContent();
53+
}
54+
55+
[HttpDelete("todos/{id}")]
56+
public IActionResult Delete(int id)
57+
{
58+
var item = __data.FirstOrDefault(x => x.Id == id);
59+
if (item == null) return NotFound();
60+
61+
__data.Remove(item);
62+
63+
return NoContent();
64+
}
65+
}
66+
67+
public class ToDo
68+
{
69+
static int _nextId = 1;
70+
public static int NewId()
71+
{
72+
return _nextId++;
73+
}
74+
75+
public int Id { get; set; }
76+
public DateTimeOffset Date { get; set; }
77+
public string Name { get; set; }
78+
public string User { get; set; }
79+
}
80+
}

src/BffJs/wwwroot/index.html

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<meta charset="utf-8" />
5+
<title></title>
6+
<link href="libs/bootstrap.min.css" rel="stylesheet" />
7+
</head>
8+
<body>
9+
<div class="container">
10+
<header class="page-header">
11+
<h1>Duende.BFF - TODOs sample</h1>
12+
<div>
13+
<a href="/bff/login">Login</a>
14+
<a href="/bff/logout">Logout</a>
15+
</div>
16+
</header>
17+
18+
<div class="row">
19+
<h2>Add New</h2>
20+
<div>
21+
<label>Todo Date</label>
22+
<input id="date" type="datetime" value="2021-03-01" />
23+
<label>Todo Name</label>
24+
<input id="name" value="Do something" />
25+
<button id="createNewButton">Create</button>
26+
</div>
27+
</div>
28+
29+
<div class="row">
30+
<table class="table table-condensed">
31+
<thead>
32+
<tr>
33+
<th></th>
34+
<th>Id</th>
35+
<th>Date</th>
36+
<th>Note</th>
37+
<th>User</th>
38+
</tr>
39+
</thead>
40+
<tbody id="todos"></tbody>
41+
</table>
42+
</div>
43+
</div>
44+
45+
<script src="todo.js"></script>
46+
</body>
47+
</html>

src/BffJs/wwwroot/libs/bootstrap.min.css

+5
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)