Files
spring-cloud-static/Dalston.SR5/multi/multi__more_detail.html
2017-12-22 20:14:47 -05:00

84 lines
11 KiB
HTML

<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>74.&nbsp;More Detail</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="multi_spring-cloud.html" title="Spring Cloud"><link rel="up" href="multi__spring_cloud_security.html" title="Part&nbsp;X.&nbsp;Spring Cloud Security"><link rel="prev" href="multi__quickstart.html" title="73.&nbsp;Quickstart"><link rel="next" href="multi__configuring_authentication_downstream_of_a_zuul_proxy.html" title="75.&nbsp;Configuring Authentication Downstream of a Zuul Proxy"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">74.&nbsp;More Detail</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__quickstart.html">Prev</a>&nbsp;</td><th width="60%" align="center">Part&nbsp;X.&nbsp;Spring Cloud Security</th><td width="20%" align="right">&nbsp;<a accesskey="n" href="multi__configuring_authentication_downstream_of_a_zuul_proxy.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h2 class="title"><a name="_more_detail" href="#_more_detail"></a>74.&nbsp;More Detail</h2></div></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_single_sign_on" href="#_single_sign_on"></a>74.1&nbsp;Single Sign On</h2></div></div></div><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>All of the OAuth2 SSO and resource server features moved to Spring Boot
in version 1.3. You can find documentation in the
<a class="link" href="http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/" target="_top">Spring Boot user guide</a>.</p></td></tr></table></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_token_relay" href="#_token_relay"></a>74.2&nbsp;Token Relay</h2></div></div></div><p>A Token Relay is where an OAuth2 consumer acts as a Client and
forwards the incoming token to outgoing resource requests. The
consumer can be a pure Client (like an SSO application) or a Resource
Server.</p><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_client_token_relay" href="#_client_token_relay"></a>74.2.1&nbsp;Client Token Relay</h3></div></div></div><p>If your app is a user facing OAuth2 client (i.e. has declared
<code class="literal">@EnableOAuth2Sso</code> or <code class="literal">@EnableOAuth2Client</code>) then it has an
<code class="literal">OAuth2ClientContext</code> in request scope from Spring Boot. You can
create your own <code class="literal">OAuth2RestTemplate</code> from this context and an
autowired <code class="literal">OAuth2ProtectedResourceDetails</code>, and then the context will
always forward the access token downstream, also refreshing the access
token automatically if it expires. (These are features of Spring
Security and Spring Boot.)</p><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>Spring Boot (1.4.1) does not create an
<code class="literal">OAuth2ProtectedResourceDetails</code> automatically if you are using
<code class="literal">client_credentials</code> tokens. In that case you need to create your own
<code class="literal">ClientCredentialsResourceDetails</code> and configure it with
<code class="literal">@ConfigurationProperties("security.oauth2.client")</code>.</p></td></tr></table></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_client_token_relay_in_zuul_proxy" href="#_client_token_relay_in_zuul_proxy"></a>74.2.2&nbsp;Client Token Relay in Zuul Proxy</h3></div></div></div><p>If your app also has a
<a class="link" href="http://cloud.spring.io/spring-cloud.html#netflix-zuul-reverse-proxy" target="_top">Spring
Cloud Zuul</a> embedded reverse proxy (using <code class="literal">@EnableZuulProxy</code>) then you
can ask it to forward OAuth2 access tokens downstream to the services
it is proxying. Thus the SSO app above can be enhanced simply like
this:</p><p><b>app.groovy.&nbsp;</b>
</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Controller</span></em>
<em><span class="hl-annotation" style="color: gray">@EnableOAuth2Sso</span></em>
<em><span class="hl-annotation" style="color: gray">@EnableZuulProxy</span></em>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> Application {
}</pre><p>
</p><p>and it will (in addition to logging the user in and grabbing a token)
pass the authentication token downstream to the <code class="literal">/proxy/*</code>
services. If those services are implemented with
<code class="literal">@EnableResourceServer</code> then they will get a valid token in the
correct header.</p><p>How does it work? The <code class="literal">@EnableOAuth2Sso</code> annotation pulls in
<code class="literal">spring-cloud-starter-security</code> (which you could do manually in a
traditional app), and that in turn triggers some autoconfiguration for
a <code class="literal">ZuulFilter</code>, which itself is activated because Zuul is on the
classpath (via <code class="literal">@EnableZuulProxy</code>). The
<a class="link" href="https://github.com/spring-cloud/spring-cloud-security/tree/master/src/main/java/org/springframework/cloud/security/oauth2/proxy/OAuth2TokenRelayFilter.java" target="_top">filter</a>
just extracts an access token from the currently authenticated user,
and puts it in a request header for the downstream requests.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_resource_server_token_relay" href="#_resource_server_token_relay"></a>74.2.3&nbsp;Resource Server Token Relay</h3></div></div></div><p>If your app has <code class="literal">@EnableResourceServer</code> you might want to relay the
incoming token downstream to other services. If you use a
<code class="literal">RestTemplate</code> to contact the downstream services then this is just a
matter of how to create the template with the right context.</p><p>If your service uses <code class="literal">UserInfoTokenServices</code> to authenticate incoming
tokens (i.e. it is using the <code class="literal">security.oauth2.user-info-uri</code>
configuration), then you can simply create an <code class="literal">OAuth2RestTemplate</code>
using an autowired <code class="literal">OAuth2ClientContext</code> (it will be populated by the
authentication process before it hits the backend code). Equivalently
(with Spring Boot 1.4), you could inject a
<code class="literal">UserInfoRestTemplateFactory</code> and grab its <code class="literal">OAuth2RestTemplate</code> in
your configuration. For example:</p><p><b>MyConfiguration.java.&nbsp;</b>
</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Bean</span></em>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> OAuth2RestTemplate restTemplate(UserInfoRestTemplateFactory factory) {
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> factory.getUserInfoRestTemplate();
}</pre><p>
</p><p>This rest template will then have the same <code class="literal">OAuth2ClientContext</code>
(request-scoped) that is used by the authentication filter, so you can
use it to send requests with the same access token.</p><p>If your app is not using <code class="literal">UserInfoTokenServices</code> but is still a client
(i.e. it declares <code class="literal">@EnableOAuth2Client</code> or <code class="literal">@EnableOAuth2Sso</code>), then
with Spring Security Cloud any <code class="literal">OAuth2RestOperations</code> that the user
creates from an <code class="literal">@Autowired</code> <code class="literal">@OAuth2Context</code> will also forward
tokens. This feature is implemented by default as an MVC handler
interceptor, so it only works in Spring MVC. If you are not using MVC
you could use a custom filter or AOP interceptor wrapping an
<code class="literal">AccessTokenContextRelay</code> to provide the same feature.</p><p>Here&#8217;s a basic
example showing the use of an autowired rest template created
elsewhere ("foo.com" is a Resource Server accepting the same tokens as
the surrounding app):</p><p><b>MyController.java.&nbsp;</b>
</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Autowired</span></em>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">private</span> OAuth2RestOperations restTemplate;
<em><span class="hl-annotation" style="color: gray">@RequestMapping("/relay")</span></em>
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> String relay() {
ResponseEntity&lt;String&gt; response =
restTemplate.getForEntity(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"https://foo.com/bar"</span>, String.<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span>);
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Success! ("</span> + response.getBody() + <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">")"</span>;
}</pre><p>
</p><p>If you don&#8217;t want to forward tokens (and that is a valid
choice, since you might want to act as yourself, rather than the
client that sent you the token), then you only need to create your own
<code class="literal">OAuth2Context</code> instead of autowiring the default one.</p><p>Feign clients will also pick up an interceptor that uses the
<code class="literal">OAuth2ClientContext</code> if it is available, so they should also do a
token relay anywhere where a <code class="literal">RestTemplate</code> would.</p></div></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__quickstart.html">Prev</a>&nbsp;</td><td width="20%" align="center"><a accesskey="u" href="multi__spring_cloud_security.html">Up</a></td><td width="40%" align="right">&nbsp;<a accesskey="n" href="multi__configuring_authentication_downstream_of_a_zuul_proxy.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">73.&nbsp;Quickstart&nbsp;</td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud.html">Home</a></td><td width="40%" align="right" valign="top">&nbsp;75.&nbsp;Configuring Authentication Downstream of a Zuul Proxy</td></tr></table></div></body></html>