Skip to content

Commit 23db092

Browse files
author
Steve Riesenberg
committed
Federated Identity sample
Issue spring-projectsgh-538 Issue spring-projectsgh-499 Issue spring-projectsgh-106
1 parent a661e1c commit 23db092

26 files changed

+1272
-5
lines changed

samples/custom-consent-authorizationserver/src/main/java/sample/config/AuthorizationServerConfig.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ public JWKSource<SecurityContext> jwkSource() {
103103

104104
@Bean
105105
public ProviderSettings providerSettings() {
106-
return ProviderSettings.builder().issuer("http://auth-server:9000").build();
106+
return ProviderSettings.builder().issuer("http://localhost:9000").build();
107107
}
108108

109109
@Bean

samples/custom-consent-authorizationserver/src/main/java/sample/config/DefaultSecurityConfig.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Excepti
3939
.authorizeRequests(authorizeRequests ->
4040
authorizeRequests.anyRequest().authenticated()
4141
)
42+
.cors(withDefaults())
4243
.formLogin(withDefaults());
4344
return http.build();
4445
}

samples/default-authorizationserver/src/main/java/sample/config/AuthorizationServerConfig.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ public class AuthorizationServerConfig {
5959
@Order(Ordered.HIGHEST_PRECEDENCE)
6060
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
6161
OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http);
62-
return http.formLogin(Customizer.withDefaults()).build();
62+
return http.cors(Customizer.withDefaults()).formLogin(Customizer.withDefaults()).build();
6363
}
6464

6565
// @formatter:off
@@ -107,7 +107,7 @@ public JWKSource<SecurityContext> jwkSource() {
107107

108108
@Bean
109109
public ProviderSettings providerSettings() {
110-
return ProviderSettings.builder().issuer("http://auth-server:9000").build();
110+
return ProviderSettings.builder().issuer("http://localhost:9000").build();
111111
}
112112

113113
@Bean
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
* Copyright 2020-2022 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 sample.config;
17+
18+
import org.springframework.context.annotation.Bean;
19+
import org.springframework.context.annotation.Configuration;
20+
import org.springframework.web.cors.CorsConfiguration;
21+
import org.springframework.web.cors.CorsConfigurationSource;
22+
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
23+
24+
@Configuration
25+
public class CorsConfig {
26+
27+
@Bean
28+
public CorsConfigurationSource corsConfigurationSource() {
29+
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
30+
CorsConfiguration config = new CorsConfiguration();
31+
config.addAllowedHeader("*");
32+
config.addAllowedMethod("*");
33+
config.addAllowedOrigin("http://127.0.0.1:4200");
34+
config.setAllowCredentials(true);
35+
source.registerCorsConfiguration("/**", config);
36+
return source;
37+
}
38+
39+
}

samples/default-authorizationserver/src/main/java/sample/config/DefaultSecurityConfig.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Excepti
4040
.authorizeRequests(authorizeRequests ->
4141
authorizeRequests.anyRequest().authenticated()
4242
)
43+
.cors(withDefaults())
4344
.formLogin(withDefaults());
4445
return http.build();
4546
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
* Copyright 2020-2022 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 sample.web;
17+
18+
import org.springframework.stereotype.Controller;
19+
import org.springframework.web.bind.annotation.GetMapping;
20+
21+
/**
22+
* @author Steve Riesenberg
23+
*/
24+
@Controller
25+
public class LoginController {
26+
27+
@GetMapping("/login")
28+
public String login() {
29+
return "login";
30+
}
31+
32+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<!DOCTYPE html>
2+
<html lang="en"
3+
xmlns="http://www.w3.org/1999/xhtml" xmlns:th="https://www.thymeleaf.org">
4+
<head>
5+
<meta charset="utf-8">
6+
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
7+
<title>Spring Security Example</title>
8+
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M" crossorigin="anonymous">
9+
<link href="https://getbootstrap.com/docs/4.0/examples/signin/signin.css" rel="stylesheet" crossorigin="anonymous"/>
10+
</head>
11+
<body>
12+
<div class="container">
13+
<form class="form-signin" method="post" th:action="@{/login}">
14+
<div th:if="${param.error}" class="alert alert-danger">
15+
Invalid username or password.
16+
</div>
17+
<div th:if="${param.logout}" class="alert alert-success">
18+
You have been logged out.
19+
</div>
20+
<h2 class="form-signin-heading">Sign In</h2>
21+
<p>
22+
<label for="username" class="sr-only">Username</label>
23+
<input type="text" id="username" name="username" class="form-control" placeholder="Username" required autofocus>
24+
</p>
25+
<p>
26+
<label for="password" class="sr-only">Password</label>
27+
<input type="password" id="password" name="password" class="form-control" placeholder="Password" required>
28+
</p>
29+
<button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>
30+
<a class="btn btn-light btn-block bg-white" href="/oauth2/authorization/google-idp" role="link" style="text-transform: none;">
31+
<img width="20" style="margin-right: 5px;" alt="Sign in with Google" src="https://upload.wikimedia.org/wikipedia/commons/thumb/5/53/Google_%22G%22_Logo.svg/512px-Google_%22G%22_Logo.svg.png" />
32+
Sign in with Google
33+
</a>
34+
<a class="btn btn-light btn-block bg-white" href="/oauth2/authorization/github-idp" role="link" style="text-transform: none;">
35+
<img width="24" style="margin-right: 5px;" alt="Sign in with GitHub" src="https://assets-git.f3mw1.com/images/modules/logos_page/GitHub-Mark.png" />
36+
Sign in with Github
37+
</a>
38+
</form>
39+
</div>
40+
</body>
41+
</html>
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
apply plugin: 'io.spring.convention.spring-sample-boot'
2+
3+
dependencies {
4+
compile 'org.springframework.boot:spring-boot-starter-web'
5+
compile 'org.springframework.boot:spring-boot-starter-security'
6+
compile 'org.springframework.boot:spring-boot-starter-oauth2-client'
7+
compile 'org.springframework.boot:spring-boot-starter-thymeleaf'
8+
compile 'org.thymeleaf.extras:thymeleaf-extras-springsecurity5'
9+
compile 'org.webjars:webjars-locator-core'
10+
compile 'org.webjars:bootstrap:3.4.1'
11+
compile 'org.webjars:jquery:3.4.1'
12+
compile 'org.springframework.boot:spring-boot-starter-jdbc'
13+
compile project(':spring-security-oauth2-authorization-server')
14+
runtimeOnly 'com.h2database:h2'
15+
16+
testCompile 'org.springframework.boot:spring-boot-starter-test'
17+
testCompile 'org.springframework.security:spring-security-test'
18+
testCompile 'net.sourceforge.htmlunit:htmlunit'
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
* Copyright 2020-2021 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 sample;
17+
18+
import org.springframework.boot.SpringApplication;
19+
import org.springframework.boot.autoconfigure.SpringBootApplication;
20+
21+
/**
22+
* @author Joe Grandja
23+
* @since 0.0.1
24+
*/
25+
@SpringBootApplication
26+
public class FederatedIdentityAuthorizationServerApplication {
27+
28+
public static void main(String[] args) {
29+
SpringApplication.run(FederatedIdentityAuthorizationServerApplication.class, args);
30+
}
31+
32+
}
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
/*
2+
* Copyright 2020-2021 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 sample.config;
17+
18+
import java.util.UUID;
19+
20+
import com.nimbusds.jose.jwk.JWKSet;
21+
import com.nimbusds.jose.jwk.RSAKey;
22+
import com.nimbusds.jose.jwk.source.JWKSource;
23+
import com.nimbusds.jose.proc.SecurityContext;
24+
import sample.jose.Jwks;
25+
import sample.security.FederatedIdentityConfigurer;
26+
27+
import org.springframework.context.annotation.Bean;
28+
import org.springframework.context.annotation.Configuration;
29+
import org.springframework.core.Ordered;
30+
import org.springframework.core.annotation.Order;
31+
import org.springframework.jdbc.core.JdbcTemplate;
32+
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase;
33+
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
34+
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
35+
import org.springframework.security.config.Customizer;
36+
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
37+
import org.springframework.security.config.annotation.web.configuration.OAuth2AuthorizationServerConfiguration;
38+
import org.springframework.security.oauth2.core.AuthorizationGrantType;
39+
import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
40+
import org.springframework.security.oauth2.core.oidc.OidcScopes;
41+
import org.springframework.security.oauth2.server.authorization.JdbcOAuth2AuthorizationConsentService;
42+
import org.springframework.security.oauth2.server.authorization.JdbcOAuth2AuthorizationService;
43+
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationConsentService;
44+
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService;
45+
import org.springframework.security.oauth2.server.authorization.client.JdbcRegisteredClientRepository;
46+
import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
47+
import org.springframework.security.oauth2.server.authorization.client.RegisteredClientRepository;
48+
import org.springframework.security.oauth2.server.authorization.config.ClientSettings;
49+
import org.springframework.security.oauth2.server.authorization.config.ProviderSettings;
50+
import org.springframework.security.web.SecurityFilterChain;
51+
52+
/**
53+
* @author Steve Riesenberg
54+
*/
55+
@Configuration(proxyBeanMethods = false)
56+
public class AuthorizationServerConfig {
57+
58+
@Bean
59+
@Order(Ordered.HIGHEST_PRECEDENCE)
60+
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
61+
OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http);
62+
http.apply(new FederatedIdentityConfigurer());
63+
64+
return http.cors(Customizer.withDefaults()).formLogin(Customizer.withDefaults()).build();
65+
}
66+
67+
@Bean
68+
public RegisteredClientRepository registeredClientRepository(JdbcTemplate jdbcTemplate) {
69+
// @formatter:off
70+
RegisteredClient confidentialClient = RegisteredClient.withId(UUID.randomUUID().toString())
71+
.clientId("messaging-client")
72+
.clientSecret("{noop}secret")
73+
.clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)
74+
.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
75+
.authorizationGrantType(AuthorizationGrantType.REFRESH_TOKEN)
76+
.authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS)
77+
.redirectUri("http://127.0.0.1:8080/login/oauth2/code/messaging-client-oidc")
78+
.redirectUri("http://127.0.0.1:8080/authorized")
79+
.scope(OidcScopes.OPENID)
80+
.scope("message.read")
81+
.scope("message.write")
82+
.clientSettings(ClientSettings.builder().requireAuthorizationConsent(true).build())
83+
.build();
84+
RegisteredClient publicClient = RegisteredClient.withId(UUID.randomUUID().toString())
85+
.clientId("public-client")
86+
.clientAuthenticationMethod(ClientAuthenticationMethod.NONE)
87+
.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
88+
.redirectUri("http://127.0.0.1:4200")
89+
.redirectUri("http://127.0.0.1:4200/silent-renew.html")
90+
.scope(OidcScopes.OPENID)
91+
.scope("message.read")
92+
.scope("message.write")
93+
.clientSettings(ClientSettings.builder().requireAuthorizationConsent(true).requireProofKey(true).build())
94+
.build();
95+
// @formatter:on
96+
97+
// Save registered client in db as if in-memory
98+
JdbcRegisteredClientRepository registeredClientRepository = new JdbcRegisteredClientRepository(jdbcTemplate);
99+
registeredClientRepository.save(confidentialClient);
100+
registeredClientRepository.save(publicClient);
101+
102+
return registeredClientRepository;
103+
}
104+
105+
@Bean
106+
public OAuth2AuthorizationService authorizationService(JdbcTemplate jdbcTemplate, RegisteredClientRepository registeredClientRepository) {
107+
return new JdbcOAuth2AuthorizationService(jdbcTemplate, registeredClientRepository);
108+
}
109+
110+
@Bean
111+
public OAuth2AuthorizationConsentService authorizationConsentService(JdbcTemplate jdbcTemplate, RegisteredClientRepository registeredClientRepository) {
112+
return new JdbcOAuth2AuthorizationConsentService(jdbcTemplate, registeredClientRepository);
113+
}
114+
115+
@Bean
116+
public JWKSource<SecurityContext> jwkSource() {
117+
RSAKey rsaKey = Jwks.generateRsa();
118+
JWKSet jwkSet = new JWKSet(rsaKey);
119+
return (jwkSelector, securityContext) -> jwkSelector.select(jwkSet);
120+
}
121+
122+
@Bean
123+
public ProviderSettings providerSettings() {
124+
return ProviderSettings.builder().issuer("http://localhost:9000").build();
125+
}
126+
127+
@Bean
128+
public EmbeddedDatabase embeddedDatabase() {
129+
// @formatter:off
130+
return new EmbeddedDatabaseBuilder()
131+
.generateUniqueName(true)
132+
.setType(EmbeddedDatabaseType.H2)
133+
.setScriptEncoding("UTF-8")
134+
.addScript("org/springframework/security/oauth2/server/authorization/oauth2-authorization-schema.sql")
135+
.addScript("org/springframework/security/oauth2/server/authorization/oauth2-authorization-consent-schema.sql")
136+
.addScript("org/springframework/security/oauth2/server/authorization/client/oauth2-registered-client-schema.sql")
137+
.build();
138+
// @formatter:on
139+
}
140+
141+
}

0 commit comments

Comments
 (0)