Skip to content

Commit 07eb026

Browse files
author
Matt Raible
committed
Add Zuul support
1 parent 6e51b89 commit 07eb026

File tree

5 files changed

+101
-24
lines changed

5 files changed

+101
-24
lines changed

spring-boot+cloud/api-gateway/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
</dependency>
4343
<dependency>
4444
<groupId>org.springframework.cloud</groupId>
45-
<artifactId>spring-cloud-starter-oauth2</artifactId>
45+
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
4646
</dependency>
4747
<dependency>
4848
<groupId>com.okta.spring</groupId>

spring-boot+cloud/api-gateway/src/main/java/com/example/apigateway/ApiGatewayApplication.java

Lines changed: 4 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@
55
import lombok.Data;
66
import org.springframework.boot.SpringApplication;
77
import org.springframework.boot.autoconfigure.SpringBootApplication;
8-
import org.springframework.boot.context.properties.ConfigurationProperties;
98
import org.springframework.boot.web.servlet.FilterRegistrationBean;
109
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
1110
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
11+
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
1212
import org.springframework.cloud.openfeign.EnableFeignClients;
1313
import org.springframework.cloud.openfeign.FeignClient;
1414
import org.springframework.context.annotation.Bean;
@@ -17,12 +17,7 @@
1717
import org.springframework.hateoas.Resources;
1818
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
1919
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
20-
import org.springframework.security.oauth2.client.DefaultOAuth2ClientContext;
2120
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService;
22-
import org.springframework.security.oauth2.client.OAuth2ClientContext;
23-
import org.springframework.security.oauth2.client.OAuth2RestTemplate;
24-
import org.springframework.security.oauth2.client.token.DefaultAccessTokenRequest;
25-
import org.springframework.security.oauth2.client.token.grant.client.ClientCredentialsResourceDetails;
2621
import org.springframework.web.bind.annotation.CrossOrigin;
2722
import org.springframework.web.bind.annotation.GetMapping;
2823
import org.springframework.web.bind.annotation.RestController;
@@ -38,6 +33,7 @@
3833
@EnableFeignClients
3934
@EnableCircuitBreaker
4035
@EnableDiscoveryClient
36+
@EnableZuulProxy
4137
@SpringBootApplication
4238
public class ApiGatewayApplication {
4339

@@ -81,19 +77,8 @@ public RequestInterceptor getUserFeignClientInterceptor(OAuth2AuthorizedClientSe
8177
}
8278

8379
@Bean
84-
@ConfigurationProperties("spring.security.oauth2.client")
85-
public ClientCredentialsResourceDetails oauth2RemoteResource() {
86-
return new ClientCredentialsResourceDetails();
87-
}
88-
89-
@Bean
90-
public OAuth2ClientContext oauth2ClientContext() {
91-
return new DefaultOAuth2ClientContext(new DefaultAccessTokenRequest());
92-
}
93-
94-
@Bean
95-
public OAuth2RestTemplate restTemplate() {
96-
return new OAuth2RestTemplate(oauth2RemoteResource(), oauth2ClientContext());
80+
public AuthorizationHeaderFilter authHeaderFilter(OAuth2AuthorizedClientService clientService) {
81+
return new AuthorizationHeaderFilter(clientService);
9782
}
9883
}
9984

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
package com.example.apigateway;
2+
3+
import com.netflix.zuul.ZuulFilter;
4+
import com.netflix.zuul.context.RequestContext;
5+
import org.springframework.core.Ordered;
6+
import org.springframework.security.core.Authentication;
7+
import org.springframework.security.core.context.SecurityContextHolder;
8+
import org.springframework.security.oauth2.client.OAuth2AuthorizedClient;
9+
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService;
10+
import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
11+
import org.springframework.security.oauth2.core.OAuth2AccessToken;
12+
import org.springframework.security.oauth2.core.oidc.OidcUserInfo;
13+
14+
import java.util.Optional;
15+
16+
import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.PRE_TYPE;
17+
18+
public class AuthorizationHeaderFilter extends ZuulFilter {
19+
20+
private final OAuth2AuthorizedClientService clientService;
21+
22+
public AuthorizationHeaderFilter(OAuth2AuthorizedClientService clientService) {
23+
this.clientService = clientService;
24+
}
25+
26+
@Override
27+
public String filterType() {
28+
return PRE_TYPE;
29+
}
30+
31+
@Override
32+
public int filterOrder() {
33+
return Ordered.LOWEST_PRECEDENCE;
34+
}
35+
36+
@Override
37+
public boolean shouldFilter() {
38+
return true;
39+
}
40+
41+
@Override
42+
public Object run() {
43+
RequestContext ctx = RequestContext.getCurrentContext();
44+
Optional<String> authorizationHeader = getAuthorizationHeader();
45+
authorizationHeader.ifPresent(s -> ctx.addZuulRequestHeader("Authorization", s));
46+
return null;
47+
}
48+
49+
private Optional<String> getAuthorizationHeader() {
50+
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
51+
OAuth2AuthenticationToken oauthToken = (OAuth2AuthenticationToken) authentication;
52+
OAuth2AuthorizedClient client = clientService.loadAuthorizedClient(
53+
oauthToken.getAuthorizedClientRegistrationId(),
54+
oauthToken.getName());
55+
56+
OAuth2AccessToken accessToken = client.getAccessToken();
57+
58+
if (accessToken == null) {
59+
return Optional.empty();
60+
} else {
61+
String tokenType = accessToken.getTokenType().getValue();
62+
String authorizationHeaderValue = String.format("%s %s", tokenType, accessToken.getTokenValue());
63+
return Optional.of(authorizationHeaderValue);
64+
}
65+
}
66+
}

spring-boot+cloud/api-gateway/src/main/resources/application.properties

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,13 @@ spring.application.name=api-gateway
22
okta.oauth2.issuer=https://dev-737523.oktapreview.com/oauth2/default
33
okta.oauth2.client-id=0oafx05pu2pxhjgkC0h7
44
okta.oauth2.client-secret=ozxBeuk7nE-oLhkUvINe1cxR3LITquTp7Jt2NvX7
5-
okta.oauth2.scopes=openid,profile,offline_access
65
feign.hystrix.enabled=true
76
hystrix.shareSecurityContext=true
87

9-
spring.security.oauth2.client.provider.okta.issuer-uri=${okta.oauth2.issuer}
10-
spring.security.oauth2.client.registration.okta.client-id=${okta.oauth2.client-id}
11-
spring.security.oauth2.client.registration.okta.client-secret=${okta.oauth2.client-secret}
8+
zuul.routes.car-service.path=/cars
9+
zuul.routes.car-service.url=http://localhost:8090
10+
11+
zuul.routes.home.path=/home
12+
zuul.routes.home.url=http://localhost:8090
13+
14+
zuul.sensitive-headers=Cookie,Set-Cookie
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package com.example.carservice;
2+
3+
import org.slf4j.Logger;
4+
import org.slf4j.LoggerFactory;
5+
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
6+
import org.springframework.web.bind.annotation.GetMapping;
7+
import org.springframework.web.bind.annotation.RestController;
8+
9+
import java.security.Principal;
10+
11+
@RestController
12+
public class HomeController {
13+
14+
private final static Logger log = LoggerFactory.getLogger(HomeController.class);
15+
16+
@GetMapping("/home")
17+
public String howdy(Principal principal) {
18+
String username = principal.getName();
19+
JwtAuthenticationToken token = (JwtAuthenticationToken) principal;
20+
log.info("claims: " + token.getTokenAttributes());
21+
return "Hello, " + username;
22+
}
23+
}

0 commit comments

Comments
 (0)