cxf-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From build...@apache.org
Subject svn commit: r953895 - in /websites/production/cxf/content: cache/docs.pageCache docs/jax-rs-oauth2.html
Date Fri, 05 Jun 2015 10:47:01 GMT
Author: buildbot
Date: Fri Jun  5 10:47:01 2015
New Revision: 953895

Log:
Production update by buildbot for cxf

Modified:
    websites/production/cxf/content/cache/docs.pageCache
    websites/production/cxf/content/docs/jax-rs-oauth2.html

Modified: websites/production/cxf/content/cache/docs.pageCache
==============================================================================
Binary files - no diff available.

Modified: websites/production/cxf/content/docs/jax-rs-oauth2.html
==============================================================================
--- websites/production/cxf/content/docs/jax-rs-oauth2.html (original)
+++ websites/production/cxf/content/docs/jax-rs-oauth2.html Fri Jun  5 10:47:01 2015
@@ -118,11 +118,11 @@ Apache CXF -- JAX-RS OAuth2
            <!-- Content -->
            <div class="wiki-content">
 <div id="ConfluenceContent"><h1 id="JAX-RSOAuth2-JAX-RS:OAuth2">JAX-RS: OAuth2</h1><p><style
type="text/css">/*<![CDATA[*/
-div.rbtoc1430923637640 {padding: 0px;}
-div.rbtoc1430923637640 ul {list-style: disc;margin-left: 0px;}
-div.rbtoc1430923637640 li {margin-left: 0px;padding-left: 0px;}
+div.rbtoc1433501218341 {padding: 0px;}
+div.rbtoc1433501218341 ul {list-style: disc;margin-left: 0px;}
+div.rbtoc1433501218341 li {margin-left: 0px;padding-left: 0px;}
 
-/*]]>*/</style></p><div class="toc-macro rbtoc1430923637640">
+/*]]>*/</style></p><div class="toc-macro rbtoc1433501218341">
 <ul class="toc-indentation"><li><a shape="rect" href="#JAX-RSOAuth2-JAX-RS:OAuth2">JAX-RS:
OAuth2</a></li><li><a shape="rect" href="#JAX-RSOAuth2-Introduction">Introduction</a></li><li><a
shape="rect" href="#JAX-RSOAuth2-Mavendependencies">Maven dependencies</a></li><li><a
shape="rect" href="#JAX-RSOAuth2-ClientRegistration">Client Registration</a></li><li><a
shape="rect" href="#JAX-RSOAuth2-DevelopingOAuth2Servers">Developing OAuth2 Servers</a>
 <ul class="toc-indentation"><li><a shape="rect" href="#JAX-RSOAuth2-AuthorizationService">Authorization
Service</a>
 <ul class="toc-indentation"><li><a shape="rect" href="#JAX-RSOAuth2-HowtocreateAuthorizationView">How
to create Authorization View</a></li><li><a shape="rect" href="#JAX-RSOAuth2-EndUserNameinAuthorizationForm">EndUser
Name in Authorization Form</a></li><li><a shape="rect" href="#JAX-RSOAuth2-PublicClients(Devices)">Public
Clients (Devices)</a>
@@ -144,7 +144,7 @@ div.rbtoc1430923637640 li {margin-left:
 </li><li><a shape="rect" href="#JAX-RSOAuth2-CustomizingEndUserSubjectinitialization">Customizing
End User Subject initialization</a></li><li><a shape="rect" href="#JAX-RSOAuth2-ProtectingresourceswithOAuthfilters">Protecting
resources with OAuth filters</a>
 <ul class="toc-indentation"><li><a shape="rect" href="#JAX-RSOAuth2-OAuth2tokensandSOAPendpoints">OAuth2
tokens and SOAP endpoints</a></li></ul>
 </li><li><a shape="rect" href="#JAX-RSOAuth2-Howtogettheuserloginname">How
to get the user login name</a></li><li><a shape="rect" href="#JAX-RSOAuth2-Client-sidesupport">Client-side
support</a>
-<ul class="toc-indentation"><li><a shape="rect" href="#JAX-RSOAuth2-OAuth2clientfilters">OAuth2
client filters</a></li></ul>
+<ul class="toc-indentation"><li><a shape="rect" href="#JAX-RSOAuth2-AdvancedOAuth2clientapplications">Advanced
OAuth2 client applications</a></li><li><a shape="rect" href="#JAX-RSOAuth2-OAuth2clientapplicationswithcode-grantfilters">OAuth2
client applications with code-grant filters</a></li><li><a shape="rect"
href="#JAX-RSOAuth2-OAuth2clientauthenticatorsfornon-dynamicclients">OAuth2 client authenticators
for non-dynamic clients</a></li></ul>
 </li><li><a shape="rect" href="#JAX-RSOAuth2-OAuth2withouttheExplicitAuthorization">OAuth2
without the Explicit Authorization</a></li><li><a shape="rect" href="#JAX-RSOAuth2-OAuthWithoutaBrowser">OAuth
Without a Browser</a></li><li><a shape="rect" href="#JAX-RSOAuth2-Reportingerrordetails">Reporting
error details</a></li><li><a shape="rect" href="#JAX-RSOAuth2-OAuth2andJOSE">OAuth2
and JOSE</a></li><li><a shape="rect" href="#JAX-RSOAuth2-OAuth2andOIDC">OAuth2
and OIDC</a></li><li><a shape="rect" href="#JAX-RSOAuth2-Designconsiderations">Design
considerations</a>
 <ul class="toc-indentation"><li><a shape="rect" href="#JAX-RSOAuth2-ControllingtheAccesstoResourceServer">Controlling
the Access to Resource Server</a>
 <ul class="toc-indentation"><li><a shape="rect" href="#JAX-RSOAuth2-Sharingthesameaccesspathbetweenendusersandclients">Sharing
the same access path between end users and clients</a></li><li><a shape="rect"
href="#JAX-RSOAuth2-Providingdifferentaccesspointstoendusersandclients">Providing different
access points to end users and clients</a></li></ul>
@@ -515,7 +515,7 @@ public class ThirdPartyAccessService {
     }
 }
 ]]></script>
-</div></div><p>org.apache.cxf.rs.security.oauth2.provider.OAuthContextProvider
will have to be registered as jaxrs:provider for it to work.</p><h1 id="JAX-RSOAuth2-Client-sidesupport">Client-side
support</h1><p>When developing a third party application which needs to participate
in OAuth2 flows one has to write the code that will redirect users to OAuth2 AuthorizationCodeGrantService,
interact with AccessTokenService in order to exchange code grants for access tokens as well
as correctly build Authorization OAuth2 headers when accessing the end users' resources. JAX-RS
makes it straightforward to support the redirection, while <a shape="rect" class="external-link"
href="http://svn.apache.org/repos/asf/cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/client/OAuthClientUtils.java">OAuthClientUtils</a>
class makes it possible to encapsulate most of the complexity away from the client application
code.</p><p>For example, the following custom c
 ode can be used by the third-party application:</p><div class="code panel pdl" style="border-width:
1px;"><div class="codeContent panelContent pdl">
+</div></div><p>org.apache.cxf.rs.security.oauth2.provider.OAuthContextProvider
will have to be registered as jaxrs:provider for it to work.</p><h1 id="JAX-RSOAuth2-Client-sidesupport">Client-side
support</h1><p>When developing a third party application which needs to participate
in OAuth2 flows one has to deal with redirecting users to OAuth2 AuthorizationCodeGrantService,
interacting with AccessTokenService in order to exchange code grants for access tokens as
well as correctly building Authorization OAuth2 headers when accessing the end users' resources.</p><h2
id="JAX-RSOAuth2-AdvancedOAuth2clientapplications">Advanced OAuth2 client applications</h2><p>In
a number of cases an OAuth2 client application supporting the code flow needs to have an OAuth2-specific
code written directly. Such clients qualify as advanced given that writing such a code requires
thel understanding of OAuth2 specifics. That said,</p><p>JAX-RS makes it straightforward
to support the redirection, while <a sha
 pe="rect" class="external-link" href="http://svn.apache.org/repos/asf/cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/client/OAuthClientUtils.java">OAuthClientUtils</a>
class makes it possible to encapsulate most of the complexity away from the client application
code, so ultimately the code required to support is typically not that complex at all, while
at the same it offers the most flexibility.</p><p>For example, the following custom
code can be used by the third-party application:</p><div class="code panel pdl" style="border-width:
1px;"><div class="codeContent panelContent pdl">
 <script class="theme: Default; brush: java; gutter: false" type="syntaxhighlighter"><![CDATA[public
class OAuthClientManager {
 	
 	private WebClient accessTokenService;
@@ -595,7 +595,103 @@ try {
 
 
 ]]></script>
-</div></div><p>The client code directly dealing with OAuth2 specifics can
be the most flelxible option: the client which has both access and refresh tokens can check
the current access token expiry time and if it is known to have expiried then it can proactively</p><p>refresh
the tokens, avoiding doing a futile HTTP request that is bound to return 401. Or/and indeed
it can take care of JAX-RS NotAuthorizedException (401) and refresh the tokens. Sophisticated
clients might want to check which scopes have been approved for a given access token and dynamically
decide if a given HTTP service call can be made or not. Clients can also proactively revoke
the tokens using a token revocation mechanism.</p><h2 id="JAX-RSOAuth2-OAuth2clientfilters">OAuth2
client filters</h2><p>Not all clients that may need to access an OAuth2-protected
application server can be modified. Futhermore, not all OAuth2 clients can participate in
advanced flows such as an authorization code flow and need to be initi
 alized with access and refresh tokens.</p><p>CXF HTTPConduit HttpAuthSupplier
supporting access and refresh tokens is shipped starting from CXF 3.0.5 .</p><p>org.apache.cxf.rs.security.oauth2.client.BearerAuthSupplier
supports creating HTTP Authorization header from bearer access tokens, refreshing them proactively
or in response to 401 failures and recreating HTTP Authorization from the refreshed token.</p><p>It
is not possible to refresh a token from a JAX-RS ClientRequestFilter because such a filter
does not handle HTTP responses so it can not detect 401 (returned by a server if the access
token has expired), while HTTPConduit HttpAuthSupplier gets a chance to react to 401 and retry.</p><p>Here
is a configuration example:</p><p>&#160;</p><div class="code panel
pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
+</div></div><p>The client code directly dealing with OAuth2 specifics can
be the most flelxible option: the client which has both access and refresh tokens can check
the current access token expiry time and if it is known to have expiried then it can proactively</p><p>refresh
the tokens, avoiding doing a futile HTTP request that is bound to return 401. Or/and indeed
it can take care of JAX-RS NotAuthorizedException (401) and refresh the tokens. Sophisticated
clients might want to check which scopes have been approved for a given access token and dynamically
decide if a given HTTP service call can be made or not. Clients can also proactively revoke
the tokens using a token revocation mechanism.</p><h2 id="JAX-RSOAuth2-OAuth2clientapplicationswithcode-grantfilters">OAuth2
client applications with code-grant filters</h2><p>The code in the previous section
shows the client application code directly supporting OAuth2 dynamics (redirection, the access
token acquisition). Starting from CXF
  3.0.6 a simpler option is possible with the help of ClientCodeRequestFilter. This filter
manages the initial redirection, exchanging code grants for tokens, persisting the request
state, and then making the token and the state available to the application code, for example,
the following code does not deal itself with teh redirection or interacting with OAuth2 servers:</p><div
class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent
pdl">
+<script class="theme: Default; brush: java; gutter: false" type="syntaxhighlighter"><![CDATA[import
org.apache.cxf.jaxrs.client.WebClient;
+import org.apache.cxf.rs.security.oauth2.client.ClientTokenContext;
+
+@Path(&quot;reserve&quot;)
+public class ReservationService {
+
+private WebClient socialService;
+private WebClient restaurantService;
+
+@GET
+@Path(&quot;table&quot;)
+@Produces(&quot;text/html&quot;)
+public Response reserve(@Context ClientTokenContext context) {
+    // Check if token is available
+    if (context.getToken() == null) {
+       return redirectToFailureHandler(NO_CODE_GRANT);
+    }
+    // Prepare Authorization header
+    socialService.authorization(context.getToken());
+    
+    // Get the state that was captured by the filter before redirecting the user to OAuth2
server
+    ReservationRequest request = context.getState(ReservationRequest.class);
+    
+    // Work with the service on behalf of a user    
+    Calendar c = null;
+    try {
+      c = socialService.get(Calendar.class);
+    } catch (RuntimeException ex) {
+      return redirectToFailureHandler(CALENDAR_ACCESS_PROBLEM);
+    }
+        
+    CalendarEntry entry = c.getEntry(request.getHour());
+    if (entry.getEventDescription() == null || entry.getEventDescription().trim().isEmpty())
{ 
+        String address = restaurantService.post(new Form().param(&quot;name&quot;,
request.getReserveName()) 
+                                         .param(&quot;phone&quot;, request.getContactPhone())

+                                         .param(&quot;hour&quot;, Integer.toString(request.getHour())),
+                                          String.class);
+        if (address == null) {
+            return redirectToFailureHandler(NO_RESERVATION);
+        }
+            
+        // update the user&#39;s calendar
+        Response response = socialService.form(new Form().param(&quot;hour&quot;,
Integer.toString(request.getHour()))
+                                         .param(&quot;description&quot;, &quot;Table
reserved at &quot; + address));
+        boolean calendarUpdated = response.getStatus() == 200 || response.getStatus() ==
204;
+            
+        return Response.ok(new ReservationConfirmation(address, request.getHour(), calendarUpdated))
+                           .build();
+        } else {
+            return redirectToFailureHandler(CALENDAR_BUSY);
+        }
+    }
+}
+
+]]></script>
+</div></div><p>&#160;</p><p>The filter is configured as
follows:</p><p>&#160;</p><p>&#160;</p><div class="code
panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
+<script class="theme: Default; brush: xml; gutter: false" type="syntaxhighlighter"><![CDATA[&lt;beans&gt;
+    
+&lt;jaxrs:server id=&quot;reservationsServer&quot; address=&quot;/reservations&quot;&gt;
+        &lt;jaxrs:serviceBeans&gt;
+           &lt;ref bean=&quot;restaurantReserveService&quot;/&gt;
+        &lt;/jaxrs:serviceBeans&gt;
+        &lt;jaxrs:providers&gt;
+           &lt;!-- other providers --&gt;
+
+           &lt;bean class=&quot;oauth2.thirdparty.ClientTokenContextProviderImpl&quot;/&gt;
+           &lt;bean class=&quot;org.apache.cxf.rs.security.oauth2.client.ClientCodeRequestFilter&quot;&gt;
+               &lt;property name=&quot;authorizationServiceUri&quot; value=&quot;http://localhost:8080/services/authorize&quot;/&gt;
+               &lt;property name=&quot;accessTokenServiceClient&quot; ref=&quot;atServiceClient&quot;/&gt;
+               &lt;property name=&quot;startUri&quot; value=&quot;reserve/table&quot;/&gt;
+               &lt;property name=&quot;clientCodeStateManager&quot; ref=&quot;codeManager&quot;/&gt;
+               &lt;property name=&quot;consumer&quot; ref=&quot;consumer&quot;/&gt;
+           &lt;/bean&gt;
+        &lt;/jaxrs:providers&gt;
+     &lt;/jaxrs:server&gt;
+     &lt;bean id=&quot;codeManager&quot; class=&quot;oauth2.thirdparty.ClientCodeStateManagerImpl&quot;/&gt;
+
+     &lt;!-- the consumer pre-registered with OAuth2 servers --&gt;
+     &lt;bean id=&quot;consumer&quot; class=&quot;org.apache.cxf.rs.security.oauth2.client.Consumer&quot;&gt;
+         &lt;property name=&quot;key&quot; value=&quot;123456789&quot;/&gt;
+         &lt;property name=&quot;secret&quot; value=&quot;987654321&quot;/&gt;
+     &lt;/bean&gt;
+
+     &lt;!-- WebClient for communicating with OAuth2 AccessTokenService --&gt;
+    &lt;jaxrs-client:client id=&quot;atServiceClient&quot; serviceClass=&quot;org.apache.cxf.jaxrs.client.WebClient&quot;
+         address=&quot;http://localhost:8080/services/oauth2Token/token&quot;&gt;
+         &lt;jaxrs-client:headers&gt;
+            &lt;entry key=&quot;Accept&quot; value=&quot;application/json&quot;/&gt;
+         &lt;/jaxrs-client:headers&gt;
+     &lt;/jaxrs-client:client&gt;
+
+&lt;/beans&gt;
+
+
+]]></script>
+</div></div><p>&#160;ClientCodeRequestFilter redirects to 'authorizationServiceUri'
when a 'startUri' is matched.</p><p>In the above example the filter uses a custom
'clientCodeStateManager' (org.apache.cxf.rs.security.oauth2.client.ClientCodeStateManager
implementation) for keeping the original request state for it to be available later on to
the applicationc code - this is optional and is only needed if the redirection request depends
on the request parameters (example, Oauth2 scope values are dynamic such as updateCalendar-7
where '7' is the hour) . By default, CXF ships some state managers out of the box, at the
moment these are MemoryClientCodeStateManager and JoseClientCodeStateManager implementations,
the latter signs and/or encrypts the request state and saves it in the HTTP session.</p><h2
id="JAX-RSOAuth2-OAuth2clientauthenticatorsfornon-dynamicclients">OAuth2 client authenticators
for non-dynamic clients</h2><p>Not all clients that may need to access an OAuth2-protected
a
 pplication server can be modified. Furthermore, not all OAuth2 clients can participate in
advanced flows such as an authorization code flow and need to be initialized with access and
refresh tokens.</p><p>CXF HTTPConduit HttpAuthSupplier supporting access and refresh
tokens is shipped starting from CXF 3.0.5 .</p><p>org.apache.cxf.rs.security.oauth2.client.BearerAuthSupplier
supports creating HTTP Authorization header from bearer access tokens, refreshing them proactively
or in response to 401 failures and recreating HTTP Authorization from the refreshed token.</p><p>It
is not possible to refresh a token from a JAX-RS ClientRequestFilter because such a filter
does not handle HTTP responses so it can not detect 401 (returned by a server if the access
token has expired), while HTTPConduit HttpAuthSupplier gets a chance to react to 401 and retry.</p><p>Here
is a configuration example:</p><p>&#160;</p><div class="code panel
pdl" style="border-width: 1px;"><div class="codeContent panelCo
 ntent pdl">
 <script class="theme: Default; brush: xml; gutter: false" type="syntaxhighlighter"><![CDATA[&lt;beans&gt;
 &lt;bean id=&quot;consumer&quot; class=&quot;org.apache.cxf.rs.security.oauth2.client.Consumer&quot;&gt;
    &lt;property name=&quot;clientId&quot; value=&quot;1&quot;/&gt;



Mime
View raw message