mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
fix(http): exclude withCredentials requests from transfer cache
Update the transfer cache check to safely exclude all requests sent with the `withCredentials` flag. By default, the HTTP transfer cache avoids caching user-specific responses to prevent sensitive data exposure or incorrect caching. While requests with explicit headers like `Cookie` or `Authorization` are excluded by default, requests can also be sent with credentials via the `withCredentials` flag without having those headers explicitly declared on the request object. To keep user-specific responses from being cached, exclude `withCredentials` requests unconditionally, even when the `includeRequestsWithAuthHeaders` option is set to true.
This commit is contained in:
committed by
Alex Rickabaugh
parent
4233188d8e
commit
de7b2a62e7
@@ -362,7 +362,7 @@ To configure this, update your `angular.json` file as follows:
|
||||
You can customize how Angular caches HTTP responses during server‑side rendering (SSR) and reuses them during hydration by configuring `HttpTransferCacheOptions`.
|
||||
This configuration is provided globally using `withHttpTransferCacheOptions` inside `provideClientHydration()`.
|
||||
|
||||
By default, `HttpClient` caches all `HEAD` and `GET` requests which don't contain `Authorization`, `Proxy-Authorization`, or `Cookie` headers. You can override those settings by using `withHttpTransferCacheOptions` to the hydration configuration.
|
||||
By default, `HttpClient` caches all `HEAD` and `GET` requests which don't contain `Authorization`, `Proxy-Authorization`, or `Cookie` headers and are not sent with `withCredentials`. You can override those settings by using `withHttpTransferCacheOptions` to the hydration configuration.
|
||||
|
||||
```ts
|
||||
import { bootstrapApplication } from '@angular/platform-browser';
|
||||
@@ -417,7 +417,7 @@ Use this only when `POST` requests are **idempotent** and safe to reuse between
|
||||
### `includeRequestsWithAuthHeaders`
|
||||
|
||||
Determines whether requests containing `Authorization`, `Proxy‑Authorization`, or `Cookie` headers are eligible for caching.
|
||||
By default, these are excluded to prevent caching user‑specific responses.
|
||||
By default, these are excluded to prevent caching user‑specific responses. Requests sent with `withCredentials` are also excluded by default.
|
||||
|
||||
```ts
|
||||
withHttpTransferCacheOptions({
|
||||
|
||||
@@ -42,7 +42,7 @@ import {HttpParams} from './params';
|
||||
* (for example using GraphQL).
|
||||
* @param includeRequestsWithAuthHeaders Enables caching of requests containing `Authorization`,
|
||||
* `Proxy-Authorization`, or `Cookie` headers. By default, these requests are excluded from
|
||||
* caching.
|
||||
* caching. Requests sent using `withCredentials` are also excluded by default.
|
||||
*
|
||||
* @see [Configuring the caching options](guide/ssr#configuring-the-caching-options)
|
||||
*
|
||||
@@ -135,6 +135,8 @@ export function transferCacheInterceptorFn(
|
||||
if (
|
||||
!isCacheActive ||
|
||||
requestOptions === false ||
|
||||
// Do not cache requests sent with credentials.
|
||||
req.withCredentials ||
|
||||
// POST requests are allowed either globally or at request level
|
||||
(requestMethod === 'POST' && !globalOptions.includePostRequests && !requestOptions) ||
|
||||
(requestMethod !== 'POST' && !ALLOWED_METHODS.includes(requestMethod)) ||
|
||||
|
||||
@@ -40,6 +40,7 @@ interface RequestParams {
|
||||
observe?: 'body' | 'response';
|
||||
transferCache?: {includeHeaders: string[]} | boolean;
|
||||
headers?: {[key: string]: string};
|
||||
withCredentials?: boolean;
|
||||
body?: RequestBody;
|
||||
}
|
||||
|
||||
@@ -397,6 +398,16 @@ describe('TransferCache', () => {
|
||||
makeRequestAndExpectOne('/test-auth', 'foo');
|
||||
});
|
||||
|
||||
it('should not cache requests with credentials', async () => {
|
||||
makeRequestAndExpectOne('/test-auth', 'foo', {
|
||||
withCredentials: true,
|
||||
});
|
||||
|
||||
makeRequestAndExpectOne('/test-auth', 'foo', {
|
||||
withCredentials: true,
|
||||
});
|
||||
});
|
||||
|
||||
it('should cache POST with the differing body in string form', () => {
|
||||
makeRequestAndExpectOne('/test-1', null, {method: 'POST', transferCache: true, body: 'foo'});
|
||||
makeRequestAndExpectNone('/test-1', 'POST', {transferCache: true, body: 'foo'});
|
||||
@@ -549,6 +560,16 @@ describe('TransferCache', () => {
|
||||
makeRequestAndExpectNone('/test-auth');
|
||||
});
|
||||
|
||||
it(`should not cache requests with credentials when 'includeRequestsWithAuthHeaders' is 'true'`, async () => {
|
||||
makeRequestAndExpectOne('/test-auth', 'foo', {
|
||||
withCredentials: true,
|
||||
});
|
||||
|
||||
makeRequestAndExpectOne('/test-auth', 'foo', {
|
||||
withCredentials: true,
|
||||
});
|
||||
});
|
||||
|
||||
it('should cache a POST request', () => {
|
||||
makeRequestAndExpectOne('/include?foo=1', 'post-body', {method: 'POST'});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user