Skip to content

Commit 78625f3

Browse files
author
Dave Syer
committed
Disable CSRF for Servlet apps by default
1 parent 758ddba commit 78625f3

File tree

5 files changed

+84
-56
lines changed

5 files changed

+84
-56
lines changed

samples/grpc-tomcat-secure/src/main/java/org/springframework/grpc/sample/GrpcServerApplication.java

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,6 @@
22

33
import org.springframework.boot.SpringApplication;
44
import org.springframework.boot.autoconfigure.SpringBootApplication;
5-
import org.springframework.context.annotation.Bean;
6-
import org.springframework.grpc.autoconfigure.server.security.GrpcServletRequest;
7-
import org.springframework.security.config.Customizer;
8-
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
9-
import org.springframework.security.web.SecurityFilterChain;
105

116
@SpringBootApplication
127
public class GrpcServerApplication {
@@ -15,12 +10,4 @@ public static void main(String[] args) {
1510
SpringApplication.run(GrpcServerApplication.class, args);
1611
}
1712

18-
@Bean
19-
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
20-
return http.httpBasic(Customizer.withDefaults())
21-
.authorizeHttpRequests((requests) -> requests.anyRequest().authenticated())
22-
.csrf(csrf -> csrf.ignoringRequestMatchers(GrpcServletRequest.all()))
23-
.build();
24-
}
25-
2613
}

spring-grpc-docs/src/main/antora/modules/ROOT/pages/server.adoc

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ Spring gRPC handles this for the default configuration.
199199

200200
Spring gRPC will automatically configure the gRPC server interceptors, and https://docs.spring.io/spring-boot/reference/web/spring-security.html[Spring Boot will provide defaults] for an `AuthenticationManager` and a `UserDetailsService`.
201201
Spring Boot will also provide default configuration for an OAuth2 resource server, if you set the classpath up correctly (following the https://docs.spring.io/spring-boot/reference/web/spring-security.html#web.security.oauth2.server[Spring Boot documentation]) which will be used to validate the token.
202-
You will want to provide your own `SecurityFilterChain` because the one provided by Spring Boot will enable CSRF protection for all endpoints, which is not compatible with gRPC.
202+
You may still want to provide your own `SecurityFilterChain`, but you can use the defaults just to get started.
203203
Here's an example with HTTP Basic authentication:
204204

205205
[source,java]
@@ -208,22 +208,10 @@ Here's an example with HTTP Basic authentication:
208208
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
209209
return http.httpBasic(Customizer.withDefaults())
210210
.authorizeHttpRequests((requests) -> requests.anyRequest().authenticated())
211-
.csrf(csrf -> csrf.disable())
212211
.build();
213212
}
214213
----
215214

216-
Disabling CSRF is fine if you have no other HTTP endpoints, but if you do you will need to be careful to disable CSRF protection for gRPC requests.
217-
To help you do that you can use a `GrpcServletRequest` to check if the request is a gRPC request and disable CSRF protection for it.
218-
Example:
219-
220-
[source,java]
221-
----
222-
@Bean
223-
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
224-
return http
225-
... // configure endpoint paths and authentication patterns
226-
.csrf(csrf -> csrf.ignoringRequestMatchers(GrpcServletRequest.all()))
227-
.build();
228-
}
229-
----
215+
By default CSRF protection is automatically disabled for gRPC requests because it is incompatible with the protocol.
216+
You can switch off that behaviour and configure your own CSRF protection if you want to by explicitly setting `spring.grpc.security.csrf.enabled=true`.
217+
A servlet application that exposes gRPC endpoints on a different port (with `spring.grpc.server.servlet.enabled=false`) will also not have CSRF protection disabled by default.

spring-grpc-docs/src/main/antora/modules/ROOT/partials/_configprops.adoc

Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2,48 +2,48 @@
22
|Name | Default | Description
33

44
|spring.grpc.client.channels | | Map of channels configured by name.
5-
|spring.grpc.client.default-channel.address | `+++static://localhost:9090+++` | The target address uri to connect to.
6-
|spring.grpc.client.default-channel.default-load-balancing-policy | `+++round_robin+++` | The default load balancing policy the channel should use.
7-
|spring.grpc.client.default-channel.enable-keep-alive | `+++false+++` | Whether keep alive is enabled on the channel.
8-
|spring.grpc.client.default-channel.health.enabled | `+++false+++` | Whether to enable client-side health check for the channel.
5+
|spring.grpc.client.default-channel.address | | The target address uri to connect to.
6+
|spring.grpc.client.default-channel.default-load-balancing-policy | | The default load balancing policy the channel should use.
7+
|spring.grpc.client.default-channel.enable-keep-alive | | Whether keep alive is enabled on the channel.
8+
|spring.grpc.client.default-channel.health.enabled | | Whether to enable client-side health check for the channel.
99
|spring.grpc.client.default-channel.health.service-name | | Name of the service to check health on.
10-
|spring.grpc.client.default-channel.idle-timeout | `+++20s+++` | The duration without ongoing RPCs before going to idle mode.
11-
|spring.grpc.client.default-channel.keep-alive-time | `+++5m+++` | The delay before sending a keepAlive. Note that shorter intervals increase the network burden for the server and this value can not be lower than 'permitKeepAliveTime' on the server.
12-
|spring.grpc.client.default-channel.keep-alive-timeout | `+++20s+++` | The default timeout for a keepAlives ping request.
13-
|spring.grpc.client.default-channel.keep-alive-without-calls | `+++false+++` | Whether a keepAlive will be performed when there are no outstanding RPC on a connection.
14-
|spring.grpc.client.default-channel.max-inbound-message-size | `+++4194304B+++` | Maximum message size allowed to be received by the channel (default 4MiB). Set to '-1' to use the highest possible limit (not recommended).
15-
|spring.grpc.client.default-channel.max-inbound-metadata-size | `+++8192B+++` | Maximum metadata size allowed to be received by the channel (default 8KiB). Set to '-1' to use the highest possible limit (not recommended).
16-
|spring.grpc.client.default-channel.negotiation-type | `+++plaintext+++` | The negotiation type for the channel.
17-
|spring.grpc.client.default-channel.secure | `+++true+++` | Flag to say that strict SSL checks are not enabled (so the remote certificate could be anonymous).
10+
|spring.grpc.client.default-channel.idle-timeout | | The duration without ongoing RPCs before going to idle mode.
11+
|spring.grpc.client.default-channel.keep-alive-time | | The delay before sending a keepAlive. Note that shorter intervals increase the network burden for the server and this value can not be lower than 'permitKeepAliveTime' on the server.
12+
|spring.grpc.client.default-channel.keep-alive-timeout | | The default timeout for a keepAlives ping request.
13+
|spring.grpc.client.default-channel.keep-alive-without-calls | | Whether a keepAlive will be performed when there are no outstanding RPC on a connection.
14+
|spring.grpc.client.default-channel.max-inbound-message-size | | Maximum message size allowed to be received by the channel (default 4MiB). Set to '-1' to use the highest possible limit (not recommended).
15+
|spring.grpc.client.default-channel.max-inbound-metadata-size | | Maximum metadata size allowed to be received by the channel (default 8KiB). Set to '-1' to use the highest possible limit (not recommended).
16+
|spring.grpc.client.default-channel.negotiation-type | | The negotiation type for the channel.
17+
|spring.grpc.client.default-channel.secure | | Flag to say that strict SSL checks are not enabled (so the remote certificate could be anonymous).
1818
|spring.grpc.client.default-channel.ssl.bundle | | SSL bundle name.
1919
|spring.grpc.client.default-channel.ssl.enabled | | Whether to enable SSL support. Enabled automatically if "bundle" is provided unless specified otherwise.
2020
|spring.grpc.client.default-channel.user-agent | | The custom User-Agent for the channel.
2121
|spring.grpc.client.observations.enabled | `+++true+++` | Whether to enable Observations on the client.
2222
|spring.grpc.server.address | | The address to bind to. could be a host:port combination or a pseudo URL like static://host:port. Can not be set if host or port are set independently.
2323
|spring.grpc.server.exception-handling.enabled | `+++true+++` | Whether to enable user-defined global exception handling on the gRPC server.
24-
|spring.grpc.server.health.actuator.enabled | `+++true+++` | Whether to adapt Actuator health indicators into gRPC health checks.
24+
|spring.grpc.server.health.actuator.enabled | | Whether to adapt Actuator health indicators into gRPC health checks.
2525
|spring.grpc.server.health.actuator.health-indicator-paths | | List of Actuator health indicator paths to adapt into gRPC health checks.
26-
|spring.grpc.server.health.actuator.update-initial-delay | `+++5s+++` | The initial delay before updating the health status the very first time.
27-
|spring.grpc.server.health.actuator.update-overall-health | `+++true+++` | Whether to update the overall gRPC server health (the '' service) with the aggregate status of the configured health indicators.
28-
|spring.grpc.server.health.actuator.update-rate | `+++5s+++` | How often to update the health status.
29-
|spring.grpc.server.health.enabled | `+++true+++` | Whether to auto-configure Health feature on the gRPC server.
30-
|spring.grpc.server.host | `+++*+++` | Server address to bind to. The default is any IP address ('*').
26+
|spring.grpc.server.health.actuator.update-initial-delay | | The initial delay before updating the health status the very first time.
27+
|spring.grpc.server.health.actuator.update-overall-health | | Whether to update the overall gRPC server health (the '' service) with the aggregate status of the configured health indicators.
28+
|spring.grpc.server.health.actuator.update-rate | | How often to update the health status.
29+
|spring.grpc.server.health.enabled | | Whether to auto-configure Health feature on the gRPC server.
30+
|spring.grpc.server.host | | Server address to bind to. The default is any IP address ('*').
3131
|spring.grpc.server.keep-alive.max-age | | Maximum time a connection may exist before being gracefully terminated (default infinite).
3232
|spring.grpc.server.keep-alive.max-age-grace | | Maximum time for graceful connection termination (default infinite).
3333
|spring.grpc.server.keep-alive.max-idle | | Maximum time a connection can remain idle before being gracefully terminated (default infinite).
34-
|spring.grpc.server.keep-alive.permit-time | `+++5m+++` | Maximum keep-alive time clients are permitted to configure (default 5m).
35-
|spring.grpc.server.keep-alive.permit-without-calls | `+++false+++` | Whether clients are permitted to send keep alive pings when there are no outstanding RPCs on the connection (default false).
36-
|spring.grpc.server.keep-alive.time | `+++2h+++` | Duration without read activity before sending a keep alive ping (default 2h).
37-
|spring.grpc.server.keep-alive.timeout | `+++20s+++` | Maximum time to wait for read activity after sending a keep alive ping. If sender does not receive an acknowledgment within this time, it will close the connection (default 20s).
38-
|spring.grpc.server.max-inbound-message-size | `+++4194304B+++` | Maximum message size allowed to be received by the server (default 4MiB).
39-
|spring.grpc.server.max-inbound-metadata-size | `+++8192B+++` | Maximum metadata size allowed to be received by the server (default 8KiB).
34+
|spring.grpc.server.keep-alive.permit-time | | Maximum keep-alive time clients are permitted to configure (default 5m).
35+
|spring.grpc.server.keep-alive.permit-without-calls | | Whether clients are permitted to send keep alive pings when there are no outstanding RPCs on the connection (default false).
36+
|spring.grpc.server.keep-alive.time | | Duration without read activity before sending a keep alive ping (default 2h).
37+
|spring.grpc.server.keep-alive.timeout | | Maximum time to wait for read activity after sending a keep alive ping. If sender does not receive an acknowledgment within this time, it will close the connection (default 20s).
38+
|spring.grpc.server.max-inbound-message-size | | Maximum message size allowed to be received by the server (default 4MiB).
39+
|spring.grpc.server.max-inbound-metadata-size | | Maximum metadata size allowed to be received by the server (default 8KiB).
4040
|spring.grpc.server.observations.enabled | `+++true+++` | Whether to enable Observations on the server.
4141
|spring.grpc.server.port | `+++9090+++` | Server port to listen on. When the value is 0, a random available port is selected. The default is 9090.
4242
|spring.grpc.server.reflection.enabled | `+++true+++` | Whether to enable Reflection on the gRPC server.
43-
|spring.grpc.server.shutdown-grace-period | `+++30s+++` | Maximum time to wait for the server to gracefully shutdown. When the value is negative, the server waits forever. When the value is 0, the server will force shutdown immediately. The default is 30 seconds.
43+
|spring.grpc.server.shutdown-grace-period | | Maximum time to wait for the server to gracefully shutdown. When the value is negative, the server waits forever. When the value is 0, the server will force shutdown immediately. The default is 30 seconds.
4444
|spring.grpc.server.ssl.bundle | | SSL bundle name.
45-
|spring.grpc.server.ssl.client-auth | `+++none+++` | Client authentication mode.
45+
|spring.grpc.server.ssl.client-auth | | Client authentication mode.
4646
|spring.grpc.server.ssl.enabled | | Whether to enable SSL support. Enabled automatically if "bundle" is provided unless specified otherwise.
47-
|spring.grpc.server.ssl.secure | `+++true+++` | Flag to indicate that client authentication is secure (i.e. certificates are checked). Do not set this to false in production.
47+
|spring.grpc.server.ssl.secure | | Flag to indicate that client authentication is secure (i.e. certificates are checked). Do not set this to false in production.
4848

4949
|===
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/*
2+
* Copyright 2024-2024 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.grpc.autoconfigure.server.security;
17+
18+
import org.springframework.context.ApplicationContext;
19+
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
20+
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
21+
22+
/**
23+
* A custom {@link AbstractHttpConfigurer} that disables CSRF protection for gRPC
24+
* requests.
25+
* <p>
26+
* This configurer checks the application context to determine if CSRF protection should
27+
* be disabled for gRPC requests based on the property
28+
* {@code spring.grpc.security.csrf.enabled}. By default, CSRF protection is disabled
29+
* unless explicitly enabled in the application properties.
30+
* </p>
31+
*
32+
* @see AbstractHttpConfigurer
33+
* @see HttpSecurity
34+
* @author Dave Syer
35+
*/
36+
public class GrpcDisableCsrfHttpConfigurer extends AbstractHttpConfigurer<GrpcDisableCsrfHttpConfigurer, HttpSecurity> {
37+
38+
@Override
39+
public void init(HttpSecurity http) throws Exception {
40+
ApplicationContext context = http.getSharedObject(ApplicationContext.class);
41+
if (context != null && isGrpcEmbedded(context)) {
42+
http.csrf(csrf -> csrf.ignoringRequestMatchers(GrpcServletRequest.all()));
43+
}
44+
}
45+
46+
private boolean isGrpcEmbedded(ApplicationContext context) {
47+
return context.getEnvironment().getProperty("spring.grpc.server.servlet.enabled", Boolean.class, true)
48+
&& !context.getEnvironment().getProperty("spring.grpc.security.csrf.enabled", Boolean.class, false);
49+
}
50+
51+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer=\
2+
org.springframework.grpc.autoconfigure.server.security.GrpcDisableCsrfHttpConfigurer

0 commit comments

Comments
 (0)