Skip to content

Commit e8d4acc

Browse files
author
Dave Syer
committed
Add auth server features
1 parent ed1e34c commit e8d4acc

File tree

5 files changed

+156
-44
lines changed

5 files changed

+156
-44
lines changed

src/main/java/com/example/SocialApplication.java

Lines changed: 71 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@
1818
import java.io.IOException;
1919
import java.security.Principal;
2020
import java.util.ArrayList;
21+
import java.util.LinkedHashMap;
2122
import java.util.List;
23+
import java.util.Map;
2224

2325
import javax.servlet.Filter;
2426
import javax.servlet.FilterChain;
@@ -35,6 +37,8 @@
3537
import org.springframework.boot.context.embedded.FilterRegistrationBean;
3638
import org.springframework.boot.context.properties.ConfigurationProperties;
3739
import org.springframework.context.annotation.Bean;
40+
import org.springframework.context.annotation.Configuration;
41+
import org.springframework.core.annotation.Order;
3842
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
3943
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
4044
import org.springframework.security.oauth2.client.OAuth2ClientContext;
@@ -43,7 +47,10 @@
4347
import org.springframework.security.oauth2.client.filter.OAuth2ClientContextFilter;
4448
import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails;
4549
import org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeResourceDetails;
50+
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
4651
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableOAuth2Client;
52+
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
53+
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
4754
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;
4855
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
4956
import org.springframework.security.web.csrf.CsrfFilter;
@@ -59,14 +66,18 @@
5966
@SpringBootApplication
6067
@RestController
6168
@EnableOAuth2Client
69+
@EnableAuthorizationServer
70+
@Order(6)
6271
public class SocialApplication extends WebSecurityConfigurerAdapter {
63-
72+
6473
@Autowired
6574
OAuth2ClientContext oauth2ClientContext;
6675

67-
@RequestMapping("/user")
68-
public Principal user(Principal principal) {
69-
return principal;
76+
@RequestMapping({ "/user", "/me" })
77+
public Map<String, String> user(Principal principal) {
78+
Map<String, String> map = new LinkedHashMap<>();
79+
map.put("name", principal.getName());
80+
return map;
7081
}
7182

7283
@Override
@@ -84,6 +95,20 @@ protected void configure(HttpSecurity http) throws Exception {
8495
// @formatter:on
8596
}
8697

98+
@Configuration
99+
@EnableResourceServer
100+
protected static class ResourceServerConfiguration
101+
extends ResourceServerConfigurerAdapter {
102+
@Override
103+
public void configure(HttpSecurity http) throws Exception {
104+
// @formatter:off
105+
http
106+
.antMatcher("/me")
107+
.authorizeRequests().anyRequest().authenticated();
108+
// @formatter:on
109+
}
110+
}
111+
87112
public static void main(String[] args) {
88113
SpringApplication.run(SocialApplication.class, args);
89114
}
@@ -97,57 +122,51 @@ public FilterRegistrationBean oauth2ClientFilterRegistration(
97122
return registration;
98123
}
99124

100-
private Filter ssoFilter() {
101-
CompositeFilter filter = new CompositeFilter();
102-
List<Filter> filters = new ArrayList<>();
103-
OAuth2ClientAuthenticationProcessingFilter facebookFilter = new OAuth2ClientAuthenticationProcessingFilter("/login/facebook");
104-
OAuth2RestTemplate facebookTemplate = new OAuth2RestTemplate(facebook(), oauth2ClientContext);
105-
facebookFilter.setRestTemplate(facebookTemplate);
106-
facebookFilter.setTokenServices(new UserInfoTokenServices(facebookResource().getUserInfoUri(), facebook().getClientId()));
107-
filters.add(facebookFilter);
108-
OAuth2ClientAuthenticationProcessingFilter githubFilter = new OAuth2ClientAuthenticationProcessingFilter("/login/github");
109-
OAuth2RestTemplate githubTemplate = new OAuth2RestTemplate(github(), oauth2ClientContext);
110-
githubFilter.setRestTemplate(githubTemplate);
111-
githubFilter.setTokenServices(new UserInfoTokenServices(githubResource().getUserInfoUri(), github().getClientId()));
112-
filters.add(githubFilter);
113-
filter.setFilters(filters);
114-
return filter;
115-
}
116-
117125
@Bean
118-
@ConfigurationProperties("facebook.client")
119-
OAuth2ProtectedResourceDetails facebook() {
120-
return new AuthorizationCodeResourceDetails();
126+
@ConfigurationProperties("github")
127+
ClientResources github() {
128+
return new ClientResources();
121129
}
122130

123131
@Bean
124-
@ConfigurationProperties("facebook.resource")
125-
ResourceServerProperties facebookResource() {
126-
return new ResourceServerProperties();
132+
@ConfigurationProperties("facebook")
133+
ClientResources facebook() {
134+
return new ClientResources();
127135
}
128136

129-
@Bean
130-
@ConfigurationProperties("github.client")
131-
OAuth2ProtectedResourceDetails github() {
132-
return new AuthorizationCodeResourceDetails();
137+
private Filter ssoFilter() {
138+
CompositeFilter filter = new CompositeFilter();
139+
List<Filter> filters = new ArrayList<>();
140+
filters.add(ssoFilter(facebook(), "/login/facebook"));
141+
filters.add(ssoFilter(github(), "/login/github"));
142+
filter.setFilters(filters);
143+
return filter;
133144
}
134145

135-
@Bean
136-
@ConfigurationProperties("github.resource")
137-
ResourceServerProperties githubResource() {
138-
return new ResourceServerProperties();
146+
private Filter ssoFilter(ClientResources client, String path) {
147+
OAuth2ClientAuthenticationProcessingFilter facebookFilter = new OAuth2ClientAuthenticationProcessingFilter(
148+
path);
149+
OAuth2RestTemplate facebookTemplate = new OAuth2RestTemplate(client.getClient(),
150+
oauth2ClientContext);
151+
facebookFilter.setRestTemplate(facebookTemplate);
152+
facebookFilter.setTokenServices(new UserInfoTokenServices(
153+
client.getResource().getUserInfoUri(), client.getClient().getClientId()));
154+
return facebookFilter;
139155
}
140156

141157
private Filter csrfHeaderFilter() {
142158
return new OncePerRequestFilter() {
143159
@Override
144-
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
145-
FilterChain filterChain) throws ServletException, IOException {
146-
CsrfToken csrf = (CsrfToken) request.getAttribute(CsrfToken.class.getName());
160+
protected void doFilterInternal(HttpServletRequest request,
161+
HttpServletResponse response, FilterChain filterChain)
162+
throws ServletException, IOException {
163+
CsrfToken csrf = (CsrfToken) request
164+
.getAttribute(CsrfToken.class.getName());
147165
if (csrf != null) {
148166
Cookie cookie = WebUtils.getCookie(request, "XSRF-TOKEN");
149167
String token = csrf.getToken();
150-
if (cookie == null || token != null && !token.equals(cookie.getValue())) {
168+
if (cookie == null
169+
|| token != null && !token.equals(cookie.getValue())) {
151170
cookie = new Cookie("XSRF-TOKEN", token);
152171
cookie.setPath("/");
153172
response.addCookie(cookie);
@@ -165,3 +184,16 @@ private CsrfTokenRepository csrfTokenRepository() {
165184
}
166185

167186
}
187+
188+
class ClientResources {
189+
private OAuth2ProtectedResourceDetails client = new AuthorizationCodeResourceDetails();
190+
private ResourceServerProperties resource = new ResourceServerProperties();
191+
192+
public OAuth2ProtectedResourceDetails getClient() {
193+
return client;
194+
}
195+
196+
public ResourceServerProperties getResource() {
197+
return resource;
198+
}
199+
}

src/main/resources/application.yml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
security:
2+
oauth2:
3+
client:
4+
client-id: acme
5+
client-secret: acmesecret
6+
scope: read,write
7+
auto-approve-scopes: '.*'
8+
19
facebook:
210
client:
311
clientId: 233668646673605
@@ -27,4 +35,3 @@ spring:
2735
resources:
2836
chain:
2937
enabled: true
30-

src/main/resources/static/index.html

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@
1717
<h1>Login</h1>
1818
<div class="container" ng-show="!home.authenticated">
1919
<div>
20-
With Facebook: <a href="/login/facebook">click here</a>
20+
With Facebook: <a href="/login/facebook">click here</a>
2121
</div>
2222
<div>
23-
With Github: <a href="/login/github">click here</a>
23+
With Github: <a href="/login/github">click here</a>
2424
</div>
2525
</div>
2626
<div class="container" ng-show="home.authenticated">
@@ -39,8 +39,13 @@ <h1>Login</h1>
3939
}).controller("home", function($http, $location) {
4040
var self = this;
4141
$http.get("/user").success(function(data) {
42-
self.user = data.userAuthentication.details.name;
43-
self.authenticated = true;
42+
if (data.name) {
43+
self.user = data.name;
44+
self.authenticated = true;
45+
} else {
46+
self.user = "N/A";
47+
self.authenticated = false;
48+
}
4449
}).error(function() {
4550
self.user = "N/A";
4651
self.authenticated = false;
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/*
2+
* Copyright 2012-2015 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+
* http://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 com.example;
17+
18+
import java.security.Principal;
19+
20+
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
21+
import org.springframework.boot.autoconfigure.security.oauth2.client.EnableOAuth2Sso;
22+
import org.springframework.boot.builder.SpringApplicationBuilder;
23+
import org.springframework.context.annotation.Configuration;
24+
import org.springframework.web.bind.annotation.RequestMapping;
25+
import org.springframework.web.bind.annotation.RestController;
26+
27+
/**
28+
* Test client for use with social application (as an OAuth2 auth server). Remember to
29+
* access this app via its IP address (not "localhost"), otherwise the auth server will
30+
* steal your cookie.
31+
*
32+
* @author Dave Syer
33+
*
34+
*/
35+
@EnableAutoConfiguration
36+
@Configuration
37+
@EnableOAuth2Sso
38+
@RestController
39+
public class ClientApplication {
40+
41+
@RequestMapping("/")
42+
public String home(Principal user) {
43+
return "Hello " + user.getName();
44+
}
45+
46+
public static void main(String[] args) {
47+
new SpringApplicationBuilder(ClientApplication.class)
48+
.properties("spring.config.name=client").run(args);
49+
}
50+
51+
}

src/test/resources/client.yml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
server:
2+
port: 9999
3+
security:
4+
oauth2:
5+
client:
6+
client-id: acme
7+
client-secret: acmesecret
8+
access-token-uri: http://localhost:8080/oauth/token
9+
user-authorization-uri: http://localhost:8080/oauth/authorize
10+
resource:
11+
user-info-uri: http://localhost:8080/me
12+
13+
logging:
14+
level:
15+
org.springframework.security: DEBUG
16+
org.springframework.web: DEBUG
17+

0 commit comments

Comments
 (0)