Skip to content

Commit fc9e92f

Browse files
authored
Merge pull request #745 from DuendeSoftware/mb/various
Various updates
2 parents 79fb12f + 71ce7e9 commit fc9e92f

File tree

4 files changed

+125
-88
lines changed

4 files changed

+125
-88
lines changed

src/content/docs/bff/fundamentals/apis/local.md renamed to src/content/docs/bff/fundamentals/apis/local.mdx

Lines changed: 77 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -11,25 +11,33 @@ redirect_from:
1111
- /identityserver/v7/bff/apis/local/
1212
---
1313

14-
A _Local API_ is an API that is located within the BFF host. Local APIs are implemented with the familiar ASP.NET abstractions of API controllers or Minimal API endpoints.
14+
import { Steps } from "@astrojs/starlight/components";
15+
16+
A _Local API_ is an API located within the BFF host. Local APIs are implemented with the familiar ASP.NET abstractions of API controllers or Minimal API endpoints.
1517

1618
There are two styles of local APIs:
19+
1720
- Self-contained Local APIs
1821
- Local APIs that Make Requests using Managed Access Tokens
1922

2023
#### Self-Contained Local APIs
24+
2125
These APIs reside within the BFF and don't make HTTP requests to other APIs. They access data controlled by the BFF itself, which can simplify the architecture of the system by reducing the number of APIs that must be deployed and managed. They are suitable for scenarios where the BFF is the sole consumer of the data. If you require data accessibility from other applications or services, this approach is probably not suitable.
2226

2327
#### Local APIs That Make Requests Using Managed Access Tokens
24-
Alternatively, you can make the data available as a service and make HTTP requests to that service from your BFF's local endpoints. The benefits of this style of Local Endpoint include
28+
29+
Alternatively, you can make the data available as a service and make HTTP requests to that service from your BFF's local endpoints. The benefits of this style of Local Endpoint include:
30+
2531
- Your frontend's network access can be simplified into an aggregated call for the specific data that it needs, which reduces the amount of data that must be sent to the client.
26-
- Your BFF endpoint can expose a subset of your remote APIs so that they are called in a more controlled manner than if the BFF proxied all requests to the endpoint.
32+
- Your BFF endpoint can expose a subset of your remote APIs so that they are called in a more controlled manner than if the BFF proxied all requests to the endpoint.
2733
- Your BFF endpoint can include business logic to call the appropriate endpoints, which simplifies your front end code.
2834

29-
Your local endpoints can leverage services like the HTTP client factory and Duende.BFF [token management](/bff/fundamentals/tokens) to make the outgoing calls. The following is a simplified example showing how local endpoints can obtain managed access tokens and use them to make requests to remote APIs.
35+
Your local endpoints can leverage services like the HTTP client factory and Duende.BFF [token management](/bff/fundamentals/tokens) to make the outgoing calls.
3036

37+
The following is a simplified example showing how local endpoints can get managed access tokens and use them to make requests to remote APIs.
3138

32-
```cs
39+
```csharp
40+
// MyApiController.cs
3341
[Route("myApi")]
3442
public class MyApiController : ControllerBase
3543
{
@@ -39,12 +47,12 @@ public class MyApiController : ControllerBase
3947
{
4048
_httpClientFactory = httpClientFactory;
4149
}
42-
50+
4351
public async Task<IActionResult> Get(string id)
4452
{
4553
// create HTTP client
4654
var client = _httpClientFactory.CreateClient();
47-
55+
4856
// get current user access token and set it on HttpClient
4957
var token = await HttpContext.GetUserAccessTokenAsync();
5058
client.SetBearerToken(token);
@@ -61,84 +69,97 @@ public class MyApiController : ControllerBase
6169
The example above is simplified to demonstrate the way that you might obtain a token. Real local endpoints will typically enforce constraints on the way the API is called, aggregate multiple calls, or perform other business logic. Local endpoints that merely forward requests from the frontend to the remote API may not be needed at all. Instead, you could proxy the requests through the BFF using either the [simple http forwarder](/bff/fundamentals/apis/remote/) or [YARP](/bff/fundamentals/apis/yarp/).
6270

6371
## Securing Local API Endpoints
64-
Regardless of the style of data access used by a local API, it must be protected against threats such as [CSRF (Cross-Site Request Forgery)](https://developer.mozilla.org/en-US/docs/Glossary/CSRF) attacks. To defend against such attacks and ensure that only the frontend can access these endpoints, we recommend implementing two layers of protection.
72+
73+
Regardless of the style of data access used by a local API, it must be protected against threats such as [CSRF (Cross-Site Request Forgery)](https://developer.mozilla.org/en-US/docs/Glossary/CSRF) attacks. To defend against such attacks and ensure that only the frontend can access these endpoints, we recommend implementing two layers of protection.
6574

6675
#### SameSite Cookies
6776

6877
[The SameSite cookie attribute](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#samesitesamesite-value) is a feature of modern browsers that restricts cookies so that they are only sent to pages originating from the [site](https://developer.mozilla.org/en-US/docs/Glossary/Site) where the cookie was originally issued.
6978

7079
This is a good first layer of defense, but makes the assumption that you can trust all subdomains of your site. All subdomains within a registrable domain are considered the same site for purposes of SameSite cookies. Thus, if another application hosted on a subdomain within your site is infected with malware, it can make CSRF attacks against your application.
7180

72-
7381
#### Anti-forgery Header
7482

75-
For this reason, we recommend requiring an additional custom header on API endpoints, for example:
83+
We recommend requiring an additional custom header on API endpoints, for example:
7684

7785
```
7886
GET /endpoint
7987
8088
x-csrf: 1
8189
```
8290

83-
The value of the header is not important, but its presence, combined with the cookie requirement, triggers a CORS preflight request for cross-origin calls. This effectively isolates the caller to the same origin as the backend, providing a robust security guarantee.
91+
The value of the header is not important, but its presence, combined with the cookie requirement, triggers a CORS preflight request for cross-origin calls. This effectively isolates the caller to the same origin as the backend, providing a robust security guarantee.
8492

8593
Additionally, API endpoints should handle scenarios where the session has expired or authorization fails without triggering an authentication redirect to the upstream identity provider. Instead, they should return Ajax-friendly status codes.
8694

8795
## Setup
96+
97+
### Adding Anti-forgery Protection
98+
8899
Duende.BFF can automate the pre-processing step of requiring the custom anti-forgery header. To do so, first add the BFF middleware to the pipeline, and then decorate your endpoints to indicate that they should receive BFF pre-processing.
89100

90-
#### Add Middleware
91-
Add the BFF middleware to the pipeline by calling *UseBFF*. Note that the middleware must be placed before the authorization middleware, but after routing.
101+
<Steps>
92102

93-
```csharp
94-
app.UseAuthentication();
95-
app.UseRouting();
103+
1. **Add Middleware to the pipeline**
96104

97-
app.UseBff();
105+
Add the BFF middleware to the pipeline by calling `UseBff`. Note that the middleware must be placed before the authorization middleware, but after routing.
98106

99-
app.UseAuthorization();
107+
```csharp {5}
108+
// Program.cs
109+
app.UseAuthentication();
110+
app.UseRouting();
100111

101-
//map endpoints
102-
```
112+
app.UseBff();
103113

104-
#### Decorate Endpoints
105-
Endpoints that require the pre- and post-processing described above must be decorated with a call to *AsBffApiEndpoint()*.
114+
app.UseAuthorization();
106115

107-
For Minimal API endpoints, you can apply BFF pre- and post-processing when they are mapped.
108-
```csharp
109-
app.MapPost("/foo", context => {
110-
// ...
116+
// map endpoints
117+
```
118+
119+
2. **Decorate Endpoints**
120+
121+
Endpoints that require the pre- and post-processing described above must be decorated with a call to `AsBffApiEndpoint()`.
122+
123+
For Minimal API endpoints, you can apply BFF pre- and post-processing when they are mapped.
124+
125+
```csharp {4-5}
126+
app.MapPost("/foo", context => {
127+
// ...
111128
})
112-
.RequireAuthorization() // no anonymous access
113-
.AsBffApiEndpoint(); // BFF pre/post processing
114-
```
129+
.RequireAuthorization() // no anonymous access
130+
.AsBffApiEndpoint(); // BFF pre/post processing
131+
```
115132

116-
For MVC controllers, you can similarly apply BFF pre- and post-processing to controller actions when they are mapped.
117-
```csharp
118-
app.MapControllers()
119-
.RequireAuthorization() // no anonymous access
120-
.AsBffApiEndpoint(); // BFF pre/post processing
121-
```
133+
For MVC controllers, you can similarly apply BFF pre- and post-processing to controller actions when they are mapped.
122134

123-
Alternatively, you can apply the *[BffApi]* attribute directly to the controller or action.
124-
```csharp
125-
[Route("myApi")]
126-
[BffApi]
127-
public class MyApiController : ControllerBase
128-
{
129-
// ...
130-
}
131-
```
135+
```csharp {2-3}
136+
app.MapControllers()
137+
.RequireAuthorization() // no anonymous access
138+
.AsBffApiEndpoint(); // BFF pre/post processing
139+
```
140+
141+
Alternatively, you can apply the `[BffApi]` attribute directly to the controller or action.
142+
143+
```csharp {2}
144+
[Route("myApi")]
145+
[BffApi]
146+
public class MyApiController : ControllerBase
147+
{
148+
// ...
149+
}
150+
```
151+
</Steps>
132152

133-
#### Disabling Anti-forgery Protection
153+
### Disabling Anti-forgery Protection
134154

135-
Disabling anti-forgery protection is possible but not recommended. Antiforgery protection defends against CSRF attacks, so opting out may cause security vulnerabilities.
155+
Disabling anti-forgery protection is possible but not recommended. Antiforgery protection defends against CSRF attacks, so opting out may cause security vulnerabilities.
136156

137157
However, if you are defending against CSRF attacks with some other mechanism, you can opt out of Duende.BFF's CSRF protection. Depending on the version of Duende.BFF, use one of the following approaches.
138158

139-
For *version 1.x*, set the *requireAntiForgeryCheck* parameter to *false* when adding the endpoint. For example:
159+
For _version 1.x_, set the `requireAntiForgeryCheck` parameter to `false` when adding the endpoint. For example:
140160

141-
```csharp
161+
```csharp {6-7,14-16}
162+
// Program.cs
142163
// MVC controllers
143164
app.MapControllers()
144165
.RequireAuthorization()
@@ -148,17 +169,17 @@ app.MapControllers()
148169

149170
// simple endpoint
150171
app.MapPost("/foo", context => {
151-
// ...
172+
// ...
152173
})
153174
.RequireAuthorization()
154175
// WARNING: Disabling antiforgery protection may make
155176
// your APIs vulnerable to CSRF attacks
156177
.AsBffApiEndpoint(requireAntiforgeryCheck: false);
157178
```
158179

159-
On MVC controllers and actions you can set the *RequireAntiForgeryCheck* as a flag in the *BffApiAttribute*, like this:
180+
On MVC controllers and actions you can set the `RequireAntiForgeryCheck` as a flag in the `BffApiAttribute`, like this:
160181

161-
```csharp
182+
```csharp {2-4}
162183
[Route("sample")]
163184
// WARNING: Disabling antiforgery protection may make
164185
// your APIs vulnerable to CSRF attacks
@@ -167,10 +188,10 @@ public class SampleApiController : ControllerBase
167188
{ /* ... */ }
168189
```
169190

191+
In _version 2.x and 3.x_, use the `SkipAntiforgery` fluent API when adding the endpoint. For example:
170192

171-
In *version 2.x*, use the *SkipAntiforgery* fluent API when adding the endpoint. For example:
172-
173-
```csharp
193+
```csharp {6-8,14-16}
194+
// Program.cs
174195
// MVC controllers
175196
app.MapControllers()
176197
.RequireAuthorization()
@@ -188,20 +209,13 @@ app.MapPost("/foo", context => { /* ... */ })
188209
.SkipAntiforgery();
189210
```
190211

191-
MVC controllers and actions can use the *BffApiSkipAntiforgeryAttribute* (which is independent of the *BffApiAttribute*), like this:
212+
MVC controllers and actions can use the `BffApiSkipAntiforgeryAttribute` (which is independent of the `BffApiAttribute`), like this:
192213

193-
```csharp
214+
```csharp {2-4}
194215
[Route("sample")]
195216
// WARNING: Disabling antiforgery protection may make
196217
// your APIs vulnerable to CSRF attacks
197218
[BffApiSkipAntiforgeryAttribute]
198219
public class SampleApiController : ControllerBase
199220
{ /* ... */ }
200221
```
201-
202-
203-
204-
205-
206-
207-

0 commit comments

Comments
 (0)