Skip to content

Commit c960d90

Browse files
authored
Merge pull request Baeldung#235 from MajewskiKrzysztof/BAEL-4754
BAEL-4754 Spring Security OAuth Authorization Server
2 parents cb0fe2e + dbe41d2 commit c960d90

File tree

18 files changed

+489
-0
lines changed

18 files changed

+489
-0
lines changed
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<project xmlns="http://maven.apache.org/POM/4.0.0"
2+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4+
<modelVersion>4.0.0</modelVersion>
5+
6+
<groupId>com.baeldung</groupId>
7+
<artifactId>authorization-server</artifactId>
8+
<version>0.1.0-SNAPSHOT</version>
9+
<packaging>jar</packaging>
10+
11+
<parent>
12+
<groupId>org.springframework.boot</groupId>
13+
<artifactId>spring-boot-starter-parent</artifactId>
14+
<version>2.4.3</version>
15+
<relativePath/> <!-- lookup parent from repository -->
16+
</parent>
17+
18+
<dependencies>
19+
<dependency>
20+
<groupId>org.springframework.boot</groupId>
21+
<artifactId>spring-boot-starter-web</artifactId>
22+
<version>2.4.3</version>
23+
</dependency>
24+
<dependency>
25+
<groupId>org.springframework.boot</groupId>
26+
<artifactId>spring-boot-starter-security</artifactId>
27+
<version>2.4.3</version>
28+
</dependency>
29+
<dependency>
30+
<groupId>org.springframework.security.experimental</groupId>
31+
<artifactId>spring-security-oauth2-authorization-server</artifactId>
32+
<version>0.1.0</version>
33+
</dependency>
34+
</dependencies>
35+
36+
<properties>
37+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
38+
<java.version>11</java.version>
39+
</properties>
40+
41+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package com.baeldung;
2+
3+
import org.springframework.boot.SpringApplication;
4+
import org.springframework.boot.autoconfigure.SpringBootApplication;
5+
6+
@SpringBootApplication
7+
public class OAuth2AuthorizationServerApplication {
8+
9+
public static void main(String[] args) {
10+
SpringApplication.run(OAuth2AuthorizationServerApplication.class, args);
11+
}
12+
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
package com.baeldung.config;
2+
3+
import com.nimbusds.jose.jwk.JWKSet;
4+
import com.nimbusds.jose.jwk.RSAKey;
5+
import com.nimbusds.jose.jwk.source.JWKSource;
6+
import com.nimbusds.jose.proc.SecurityContext;
7+
import org.springframework.context.annotation.Bean;
8+
import org.springframework.context.annotation.Configuration;
9+
import org.springframework.context.annotation.Import;
10+
import org.springframework.security.config.annotation.web.configuration.OAuth2AuthorizationServerConfiguration;
11+
import org.springframework.security.oauth2.core.AuthorizationGrantType;
12+
import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
13+
import org.springframework.security.oauth2.server.authorization.client.InMemoryRegisteredClientRepository;
14+
import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
15+
import org.springframework.security.oauth2.server.authorization.client.RegisteredClientRepository;
16+
import org.springframework.security.oauth2.server.authorization.config.ProviderSettings;
17+
18+
import java.security.KeyPair;
19+
import java.security.KeyPairGenerator;
20+
import java.security.interfaces.RSAPrivateKey;
21+
import java.security.interfaces.RSAPublicKey;
22+
import java.util.UUID;
23+
24+
@Configuration(proxyBeanMethods = false)
25+
@Import(OAuth2AuthorizationServerConfiguration.class)
26+
public class AuthorizationServerConfig {
27+
28+
@Bean
29+
public RegisteredClientRepository registeredClientRepository() {
30+
RegisteredClient registeredClient = RegisteredClient.withId(UUID.randomUUID().toString())
31+
.clientId("article-client").clientSecret("secret")
32+
.clientAuthenticationMethod(ClientAuthenticationMethod.BASIC)
33+
.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
34+
.authorizationGrantType(AuthorizationGrantType.REFRESH_TOKEN)
35+
.redirectUri("http://localhost:8080/login/oauth2/code/articles-client-oidc")
36+
.scope("articles.read").build();
37+
return new InMemoryRegisteredClientRepository(registeredClient);
38+
}
39+
40+
@Bean
41+
public JWKSource<SecurityContext> jwkSource() {
42+
RSAKey rsaKey = generateRsa();
43+
JWKSet jwkSet = new JWKSet(rsaKey);
44+
return (jwkSelector, securityContext) -> jwkSelector.select(jwkSet);
45+
}
46+
47+
private static RSAKey generateRsa() {
48+
KeyPair keyPair = generateRsaKey();
49+
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
50+
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
51+
return new RSAKey.Builder(publicKey)
52+
.privateKey(privateKey)
53+
.keyID(UUID.randomUUID().toString())
54+
.build();
55+
}
56+
57+
private static KeyPair generateRsaKey() {
58+
KeyPair keyPair;
59+
try {
60+
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
61+
keyPairGenerator.initialize(2048);
62+
keyPair = keyPairGenerator.generateKeyPair();
63+
} catch (Exception ex) {
64+
throw new IllegalStateException(ex);
65+
}
66+
return keyPair;
67+
}
68+
69+
@Bean
70+
public ProviderSettings providerSettings() {
71+
return new ProviderSettings().issuer("http://127.0.0.1:9000");
72+
}
73+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package com.baeldung.config;
2+
3+
import org.springframework.context.annotation.Bean;
4+
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
5+
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
6+
import org.springframework.security.core.userdetails.User;
7+
import org.springframework.security.core.userdetails.UserDetails;
8+
import org.springframework.security.core.userdetails.UserDetailsService;
9+
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
10+
import org.springframework.security.web.SecurityFilterChain;
11+
12+
import static org.springframework.security.config.Customizer.withDefaults;
13+
14+
@EnableWebSecurity
15+
public class DefaultSecurityConfig {
16+
17+
@Bean
18+
SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
19+
http.authorizeRequests(authorizeRequests ->
20+
authorizeRequests.anyRequest().authenticated()
21+
)
22+
.formLogin(withDefaults());
23+
return http.build();
24+
}
25+
26+
@Bean
27+
UserDetailsService users() {
28+
UserDetails user = User.withDefaultPasswordEncoder()
29+
.username("admin")
30+
.password("password")
31+
.roles("USER")
32+
.build();
33+
return new InMemoryUserDetailsManager(user);
34+
}
35+
36+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
server:
2+
port: 9000
3+
4+
logging:
5+
level:
6+
root: INFO
7+
org.springframework.web: INFO
8+
org.springframework.security: INFO
9+
org.springframework.security.oauth2: INFO
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
<project xmlns="http://maven.apache.org/POM/4.0.0"
2+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4+
<modelVersion>4.0.0</modelVersion>
5+
6+
<groupId>com.baeldung</groupId>
7+
<artifactId>client-server</artifactId>
8+
<version>0.1.0-SNAPSHOT</version>
9+
<packaging>jar</packaging>
10+
11+
<parent>
12+
<groupId>org.springframework.boot</groupId>
13+
<artifactId>spring-boot-starter-parent</artifactId>
14+
<version>2.4.3</version>
15+
<relativePath/> <!-- lookup parent from repository -->
16+
</parent>
17+
18+
<dependencies>
19+
<dependency>
20+
<groupId>org.springframework.boot</groupId>
21+
<artifactId>spring-boot-starter-web</artifactId>
22+
<version>2.4.3</version>
23+
</dependency>
24+
<dependency>
25+
<groupId>org.springframework.boot</groupId>
26+
<artifactId>spring-boot-starter-security</artifactId>
27+
<version>2.4.3</version>
28+
</dependency>
29+
<dependency>
30+
<groupId>org.springframework.boot</groupId>
31+
<artifactId>spring-boot-starter-oauth2-client</artifactId>
32+
<version>2.4.3</version>
33+
</dependency>
34+
<dependency>
35+
<groupId>org.springframework</groupId>
36+
<artifactId>spring-webflux</artifactId>
37+
<version>5.3.4</version>
38+
</dependency>
39+
<dependency>
40+
<groupId>io.projectreactor.netty</groupId>
41+
<artifactId>reactor-netty</artifactId>
42+
<version>1.0.4</version>
43+
</dependency>
44+
</dependencies>
45+
46+
<properties>
47+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
48+
<java.version>11</java.version>
49+
</properties>
50+
51+
</project>
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package com.baeldung;
2+
3+
import org.springframework.boot.SpringApplication;
4+
import org.springframework.boot.autoconfigure.SpringBootApplication;
5+
6+
@SpringBootApplication
7+
public class OAuth2ClientApplication {
8+
9+
public static void main(String[] args) {
10+
SpringApplication.run(OAuth2ClientApplication.class, args);
11+
}
12+
13+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package com.baeldung.config;
2+
3+
import org.springframework.context.annotation.Bean;
4+
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
5+
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
6+
import org.springframework.security.web.SecurityFilterChain;
7+
8+
import static org.springframework.security.config.Customizer.withDefaults;
9+
10+
@EnableWebSecurity
11+
public class SecurityConfig {
12+
13+
@Bean
14+
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
15+
http
16+
.authorizeRequests(authorizeRequests ->
17+
authorizeRequests.anyRequest().authenticated()
18+
)
19+
.oauth2Login(oauth2Login ->
20+
oauth2Login.loginPage("/oauth2/authorization/articles-client-oidc"))
21+
.oauth2Client(withDefaults());
22+
return http.build();
23+
}
24+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package com.baeldung.config;
2+
3+
import org.springframework.context.annotation.Bean;
4+
import org.springframework.context.annotation.Configuration;
5+
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientManager;
6+
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientProvider;
7+
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientProviderBuilder;
8+
import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
9+
import org.springframework.security.oauth2.client.web.DefaultOAuth2AuthorizedClientManager;
10+
import org.springframework.security.oauth2.client.web.OAuth2AuthorizedClientRepository;
11+
import org.springframework.security.oauth2.client.web.reactive.function.client.ServletOAuth2AuthorizedClientExchangeFilterFunction;
12+
import org.springframework.web.reactive.function.client.WebClient;
13+
14+
@Configuration
15+
public class WebClientConfig {
16+
17+
@Bean
18+
WebClient webClient(OAuth2AuthorizedClientManager authorizedClientManager) {
19+
ServletOAuth2AuthorizedClientExchangeFilterFunction oauth2Client =
20+
new ServletOAuth2AuthorizedClientExchangeFilterFunction(authorizedClientManager);
21+
return WebClient.builder()
22+
.apply(oauth2Client.oauth2Configuration())
23+
.build();
24+
}
25+
26+
@Bean
27+
OAuth2AuthorizedClientManager authorizedClientManager(
28+
ClientRegistrationRepository clientRegistrationRepository,
29+
OAuth2AuthorizedClientRepository authorizedClientRepository) {
30+
31+
OAuth2AuthorizedClientProvider authorizedClientProvider =
32+
OAuth2AuthorizedClientProviderBuilder.builder()
33+
.authorizationCode()
34+
.refreshToken()
35+
.build();
36+
DefaultOAuth2AuthorizedClientManager authorizedClientManager = new DefaultOAuth2AuthorizedClientManager(
37+
clientRegistrationRepository, authorizedClientRepository);
38+
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);
39+
40+
return authorizedClientManager;
41+
}
42+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package com.baeldung.web;
2+
3+
import org.springframework.security.oauth2.client.OAuth2AuthorizedClient;
4+
import org.springframework.security.oauth2.client.annotation.RegisteredOAuth2AuthorizedClient;
5+
import org.springframework.web.bind.annotation.GetMapping;
6+
import org.springframework.web.bind.annotation.RestController;
7+
import org.springframework.web.reactive.function.client.WebClient;
8+
9+
import static org.springframework.security.oauth2.client.web.reactive.function.client.ServerOAuth2AuthorizedClientExchangeFilterFunction.oauth2AuthorizedClient;
10+
11+
@RestController
12+
public class ArticlesController {
13+
14+
private WebClient webClient;
15+
16+
@GetMapping(value = "/articles")
17+
public String[] getArticles(
18+
@RegisteredOAuth2AuthorizedClient("articles-client-authorization-code") OAuth2AuthorizedClient authorizedClient
19+
) {
20+
return this.webClient
21+
.get()
22+
.uri("http://localhost:8090/articles")
23+
.attributes(oauth2AuthorizedClient(authorizedClient))
24+
.retrieve()
25+
.bodyToMono(String[].class)
26+
.block();
27+
}
28+
}

0 commit comments

Comments
 (0)