Skip to content

Commit dc992ad

Browse files
Merge pull request #131 from InseeFr/devAuth
Add authentication
2 parents 3e8407b + 35f082f commit dc992ad

File tree

9 files changed

+158
-24
lines changed

9 files changed

+158
-24
lines changed

pom.xml

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,15 @@
2424
<sonar.core.codeCoveragePlugin>jacoco</sonar.core.codeCoveragePlugin>
2525
<sonar.language>java</sonar.language>
2626
<sonar.sourceEncoding>UTF-8</sonar.sourceEncoding>
27+
<sonar.exclusions>
28+
src/main/java/fr/insee/genesis/configuration/**/*.java
29+
</sonar.exclusions>
2730
<skipSurefireReport>true</skipSurefireReport>
2831
<!-- Pi Test-->
2932
<pitest.version>1.17.2</pitest.version>
3033
<pitest.junit.version>1.2.1</pitest.junit.version>
3134
<jackson.version>2.18.2</jackson.version>
32-
<bpm.version>1.0.3</bpm.version>
35+
<bpm.version>1.0.4</bpm.version>
3336
</properties>
3437
<dependencies>
3538
<dependency>
@@ -44,6 +47,11 @@
4447
<groupId>org.springframework.boot</groupId>
4548
<artifactId>spring-boot-starter-data-mongodb</artifactId>
4649
</dependency>
50+
<dependency>
51+
<groupId>org.springframework.boot</groupId>
52+
<artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
53+
</dependency>
54+
4755
<dependency>
4856
<groupId>org.springframework.boot</groupId>
4957
<artifactId>spring-boot-starter-test</artifactId>
@@ -163,6 +171,11 @@
163171
<groupId>org.jacoco</groupId>
164172
<artifactId>jacoco-maven-plugin</artifactId>
165173
<version>${jacoco.version}</version>
174+
<configuration>
175+
<excludes>
176+
<exclude>src/main/java/fr/insee/genesis/configuration/**/*</exclude>
177+
</excludes>
178+
</configuration>
166179
<executions>
167180
<execution>
168181
<id>default-prepare-agent</id>

src/main/java/fr/insee/genesis/configuration/Config.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,21 @@ public class Config {
2020
@Value("${fr.insee.genesis.sourcefolder.specifications}")
2121
private String specFolderSource;
2222

23+
@Value("${fr.insee.genesis.oidc.auth-server-url}")
24+
private String authServerUrl;
25+
26+
@Value("${fr.insee.genesis.oidc.realm}")
27+
private String realm;
28+
29+
@Value("${fr.insee.genesis.security.token.oidc-claim-role}")
30+
private String oidcClaimRole;
31+
32+
@Value("${fr.insee.genesis.security.token.oidc-claim-username}")
33+
private String oidcClaimUsername;
34+
35+
@Value("#{'${fr.insee.genesis.security.whitelist-matchers}'.split(',')}")
36+
private String[] whiteList;
37+
2338
private final String logFolder;
2439

2540
//Extract log folder from log filename property
Lines changed: 61 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,76 @@
11
package fr.insee.genesis.configuration;
22

3+
import io.swagger.v3.oas.models.Components;
34
import io.swagger.v3.oas.models.OpenAPI;
45
import io.swagger.v3.oas.models.info.Info;
5-
import io.swagger.v3.oas.models.servers.Server;
6+
7+
import io.swagger.v3.oas.models.security.OAuthFlow;
8+
import io.swagger.v3.oas.models.security.OAuthFlows;
9+
import io.swagger.v3.oas.models.security.Scopes;
10+
import io.swagger.v3.oas.models.security.SecurityRequirement;
11+
import io.swagger.v3.oas.models.security.SecurityScheme;
612
import org.springframework.beans.factory.annotation.Value;
13+
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
714
import org.springframework.context.annotation.Bean;
815
import org.springframework.context.annotation.Configuration;
916

1017
@Configuration
1118
public class SpringDocConfiguration {
1219

13-
@Value("${fr.insee.genesis.version}")
14-
private String projectVersion;
20+
@Value("${fr.insee.genesis.version}")
21+
private String projectVersion;
22+
public static final String BEARERSCHEME = "bearerAuth";
23+
public static final String OAUTH2SCHEME = "oauth2";
24+
25+
@Bean
26+
@ConditionalOnProperty(name = "fr.insee.genesis.authentication", havingValue = "NONE")
27+
public OpenAPI noAuthOpenAPI() {
28+
return generateOpenAPI();
29+
}
30+
31+
@Bean
32+
@ConditionalOnProperty(name = "fr.insee.genesis.authentication", havingValue = "OIDC")
33+
public OpenAPI oidcOpenAPI(Config config) {
34+
String authUrl = config.getAuthServerUrl() + "/realms/" + config.getRealm() + "/protocol/openid-connect";
35+
return generateOpenAPI()
36+
.addSecurityItem(new SecurityRequirement().addList(OAUTH2SCHEME))
37+
.addSecurityItem(new SecurityRequirement().addList(BEARERSCHEME))
38+
.components(
39+
new Components()
40+
.addSecuritySchemes(OAUTH2SCHEME,
41+
new SecurityScheme()
42+
.name(OAUTH2SCHEME)
43+
.type(SecurityScheme.Type.OAUTH2)
44+
.flows(getFlows(authUrl))
45+
)
46+
.addSecuritySchemes(BEARERSCHEME,
47+
new SecurityScheme()
48+
.name(BEARERSCHEME)
49+
.type(SecurityScheme.Type.HTTP)
50+
.scheme("bearer")
51+
.bearerFormat("JWT")
52+
)
53+
);
54+
}
1555

16-
@Bean
17-
public OpenAPI customOpenAPI() {
18-
return new OpenAPI()
19-
.addServersItem(new Server().url("/"))
20-
.info(new Info()
21-
.title("Genesis API")
22-
.description("Rest Endpoints and services to communicate with Genesis database")
23-
.version(projectVersion)
24-
);
25-
}
56+
private OpenAPI generateOpenAPI() {
57+
return new OpenAPI()
58+
.info(new Info()
59+
.title("Genesis API")
60+
.description("Rest Endpoints and services to communicate with Genesis database")
61+
.version(projectVersion)
62+
);
63+
}
2664

65+
private OAuthFlows getFlows(String authUrl) {
66+
OAuthFlows flows = new OAuthFlows();
67+
OAuthFlow flow = new OAuthFlow();
68+
Scopes scopes = new Scopes();
69+
flow.setAuthorizationUrl(authUrl + "/auth");
70+
flow.setTokenUrl(authUrl + "/token");
71+
flow.setRefreshUrl(authUrl + "/token");
72+
flow.setScopes(scopes);
73+
return flows.authorizationCode(flow);
74+
}
2775

2876
}

src/main/java/fr/insee/genesis/configuration/auth/security/DefaultSecurityConfig.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package fr.insee.genesis.configuration.auth.security;
22

3-
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
3+
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
44
import org.springframework.context.annotation.Bean;
55
import org.springframework.context.annotation.Configuration;
66
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
@@ -10,7 +10,7 @@
1010

1111
@Configuration
1212
@EnableWebSecurity
13-
@ConditionalOnMissingBean(OIDCSecurityConfig.class)
13+
@ConditionalOnProperty(name = "fr.insee.genesis.authentication", havingValue = "NONE")
1414
public class DefaultSecurityConfig {
1515

1616
@Bean
Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,48 @@
11
package fr.insee.genesis.configuration.auth.security;
22

3+
import fr.insee.genesis.configuration.Config;
4+
import lombok.extern.slf4j.Slf4j;
5+
import org.springframework.beans.factory.annotation.Autowired;
36
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
47
import org.springframework.context.annotation.Bean;
58
import org.springframework.context.annotation.Configuration;
9+
import org.springframework.security.config.Customizer;
610
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
711
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
812
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
13+
import org.springframework.security.config.http.SessionCreationPolicy;
914
import org.springframework.security.web.SecurityFilterChain;
15+
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
1016

1117
@Configuration
1218
@EnableWebSecurity
19+
@Slf4j
1320
@ConditionalOnProperty(name = "fr.insee.genesis.authentication", havingValue = "OIDC")
1421
public class OIDCSecurityConfig {
1522

16-
@Bean
17-
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
18-
http.csrf(AbstractHttpConfigurer::disable).authorizeHttpRequests(auth -> auth.anyRequest().permitAll());
19-
return http.build();
23+
Config config;
24+
@Autowired
25+
public OIDCSecurityConfig(Config config) {
26+
this.config = config;
2027
}
2128

29+
@Bean
30+
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
31+
http
32+
.csrf(AbstractHttpConfigurer::disable)
33+
.sessionManagement(sess -> sess.sessionCreationPolicy(SessionCreationPolicy.STATELESS));
34+
for (var pattern : config.getWhiteList()) {
35+
http.authorizeHttpRequests(authorize ->
36+
authorize
37+
.requestMatchers(AntPathRequestMatcher.antMatcher(pattern)).permitAll()
38+
);
39+
}
40+
http
41+
.authorizeHttpRequests(configurer -> configurer
42+
.anyRequest().authenticated()
43+
)
44+
.oauth2ResourceServer(oauth2 -> oauth2.jwt(Customizer.withDefaults()));
45+
return http.build();
46+
}
47+
2248
}

src/main/resources/application-dev.properties

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,11 @@ fr.insee.genesis.persistence.database.mongodb.port=27017
55
fr.insee.genesis.persistence.database.mongodb.database=CollectedDataRepository
66
fr.insee.genesis.persistence.database.mongodb.username=user
77

8-
#fr.insee.genesis.persistence.database.mongodb.password in Vault
8+
#fr.insee.genesis.persistence.database.mongodb.password in Vault
9+
10+
#--------------------------------------------------------------------------
11+
# Keycloak configuration
12+
#--------------------------------------------------------------------------
13+
fr.insee.genesis.oidc.auth-server-url=***
14+
fr.insee.genesis.oidc.realm=***
15+
springdoc.swagger-ui.oauth.client-id=***

src/main/resources/application-preprod.properties

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,11 @@ fr.insee.genesis.persistence.database.mongodb.port=27017
55
fr.insee.genesis.persistence.database.mongodb.database=CollectedDataRepository
66
fr.insee.genesis.persistence.database.mongodb.username=user
77

8-
#fr.insee.genesis.persistence.database.mongodb.password in Vault
8+
#fr.insee.genesis.persistence.database.mongodb.password in Vault
9+
10+
#--------------------------------------------------------------------------
11+
# Keycloak configuration
12+
#--------------------------------------------------------------------------
13+
fr.insee.genesis.oidc.auth-server-url=***
14+
fr.insee.genesis.oidc.realm=***
15+
springdoc.swagger-ui.oauth.client-id=***

src/main/resources/application-prod.properties

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,11 @@ fr.insee.genesis.persistence.database.mongodb.port=27017
55
fr.insee.genesis.persistence.database.mongodb.database=CollectedDataRepository
66
fr.insee.genesis.persistence.database.mongodb.username=user
77

8-
#fr.insee.genesis.persistence.database.mongodb.password in Vault
8+
#fr.insee.genesis.persistence.database.mongodb.password in Vault
9+
10+
#--------------------------------------------------------------------------
11+
# Keycloak configuration
12+
#--------------------------------------------------------------------------
13+
fr.insee.genesis.oidc.auth-server-url=***
14+
fr.insee.genesis.oidc.realm=***
15+
springdoc.swagger-ui.oauth.client-id=***

src/main/resources/application.properties

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,25 @@ spring.profiles.active=local
66
#--------------------------------------------------------------------------
77
# Global configuration
88
#--------------------------------------------------------------------------
9-
fr.insee.genesis.authentication = NONE
9+
fr.insee.genesis.authentication = OIDC
1010

1111
#--------------------------------------------------------------------------
1212
# Configuration for springdoc / swagger
1313
#--------------------------------------------------------------------------
1414
fr.insee.genesis.version=@project.version@
1515
#To make swagger-ui display the actuator endpoints
1616
springdoc.show-actuator=true
17+
springdoc.swagger-ui.oauth2RedirectUrl=${fr.insee.genesis.application.host.url}/swagger-ui/oauth2-redirect.html
18+
# To deal with http/https issues in swagger
19+
server.forward-headers-strategy=framework
20+
21+
#--------------------------------------------------------------------------
22+
# Security
23+
#--------------------------------------------------------------------------
24+
fr.insee.genesis.security.token.oidc-claim-role=realm_access.roles
25+
fr.insee.genesis.security.token.oidc-claim-username=name
26+
spring.security.oauth2.resourceserver.jwt.issuer-uri=${fr.insee.genesis.oidc.auth-server-url}/realms/${fr.insee.genesis.oidc.realm}
27+
fr.insee.genesis.security.whitelist-matchers=/v3/api-docs/**,/swagger-ui/**,/swagger-ui.html,/actuator/**,/error,/,/health-check/**
1728

1829
#--------------------------------------------------------------------------
1930
# Actuator

0 commit comments

Comments
 (0)