Return-Path: X-Original-To: apmail-cxf-commits-archive@www.apache.org Delivered-To: apmail-cxf-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 3292F9733 for ; Tue, 3 Apr 2012 15:04:43 +0000 (UTC) Received: (qmail 95521 invoked by uid 500); 3 Apr 2012 15:04:43 -0000 Delivered-To: apmail-cxf-commits-archive@cxf.apache.org Received: (qmail 95468 invoked by uid 500); 3 Apr 2012 15:04:43 -0000 Mailing-List: contact commits-help@cxf.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@cxf.apache.org Delivered-To: mailing list commits@cxf.apache.org Received: (qmail 95461 invoked by uid 99); 3 Apr 2012 15:04:43 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 03 Apr 2012 15:04:43 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 03 Apr 2012 15:04:40 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id 8FC0A23889BB; Tue, 3 Apr 2012 15:04:20 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1308968 - in /cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2: services/ tokens/bearer/ utils/ Date: Tue, 03 Apr 2012 15:04:20 -0000 To: commits@cxf.apache.org From: sergeyb@apache.org X-Mailer: svnmailer-1.0.8-patched Message-Id: <20120403150420.8FC0A23889BB@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: sergeyb Date: Tue Apr 3 15:04:19 2012 New Revision: 1308968 URL: http://svn.apache.org/viewvc?rev=1308968&view=rev Log: Finalizing with Java docs and comments to the oauth2 module for now Modified: cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/AbstractOAuthService.java cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/AccessTokenService.java cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/AuthorizationCodeGrantService.java cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/ImplicitGrantService.java cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/RedirectionBasedGrantService.java cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/tokens/bearer/BearerAccessToken.java cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/AuthorizationUtils.java cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/MD5SequenceGenerator.java Modified: cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/AbstractOAuthService.java URL: http://svn.apache.org/viewvc/cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/AbstractOAuthService.java?rev=1308968&r1=1308967&r2=1308968&view=diff ============================================================================== --- cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/AbstractOAuthService.java (original) +++ cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/AbstractOAuthService.java Tue Apr 3 15:04:19 2012 @@ -35,7 +35,7 @@ import org.apache.cxf.rs.security.oauth2 import org.apache.cxf.rs.security.oauth2.utils.OAuthConstants; /** - * Abstract utility class which OAuth services extend + * Abstract OAuth service */ public abstract class AbstractOAuthService { private static final Logger LOG = LogUtils.getL7dLogger(AbstractOAuthService.class); @@ -67,6 +67,14 @@ public abstract class AbstractOAuthServi protected Client getClient(MultivaluedMap params) { return getClient(params.getFirst(OAuthConstants.CLIENT_ID)); } + /** + * Get the {@link Client} reference + * @param clientId the provided client id + * @return Client the client reference + * @throws WebApplicationException if no matching Client is found, + * the error is returned directly to the end user without + * following the redirect URI if any + */ protected Client getClient(String clientId) { Client client = null; @@ -84,6 +92,11 @@ public abstract class AbstractOAuthServi } + /** + * HTTPS is the default transport for OAuth 2.0 services. + * By default this method will issue a warning for open + * endpoints + */ protected void checkTransportSecurity() { if (!mc.getSecurityContext().isSecure()) { LOG.warning("Unsecure HTTP, Transport Layer Security is recommended"); @@ -100,6 +113,12 @@ public abstract class AbstractOAuthServi Response.status(400).type(MediaType.APPLICATION_JSON).entity(error).build()); } + /** + * HTTPS is the default transport for OAuth 2.0 services, this property + * can be used to block all the requests issued over HTTP + * + * @param blockUnsecureRequests if set to true then HTTP requests will be blocked + */ public void setBlockUnsecureRequests(boolean blockUnsecureRequests) { this.blockUnsecureRequests = blockUnsecureRequests; } Modified: cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/AccessTokenService.java URL: http://svn.apache.org/viewvc/cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/AccessTokenService.java?rev=1308968&r1=1308967&r2=1308968&view=diff ============================================================================== --- cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/AccessTokenService.java (original) +++ cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/AccessTokenService.java Tue Apr 3 15:04:19 2012 @@ -44,26 +44,41 @@ import org.apache.cxf.rs.security.oauth2 import org.apache.cxf.rs.security.oauth2.utils.AuthorizationUtils; import org.apache.cxf.rs.security.oauth2.utils.OAuthConstants; - +/** + * OAuth2 Access Token Service implementation + */ @Path("/token") public class AccessTokenService extends AbstractOAuthService { private List grantHandlers = Collections.emptyList(); + /** + * Sets the list of optional grant handlers + * @param handlers the grant handlers + */ public void setGrantHandlers(List handlers) { grantHandlers = handlers; } + /** + * Processes an access token request + * @param params the form parameters representing the access token grant + * @return Access Token or the error + */ @POST @Consumes("application/x-www-form-urlencoded") @Produces("application/json") public Response handleTokenRequest(MultivaluedMap params) { + + // Make sure the client is authenticated Client client = authenticateClientIfNeeded(params); + // Find the grant handler AccessTokenGrantHandler handler = findGrantHandler(params); if (handler == null) { return createErrorResponse(params, OAuthConstants.UNSUPPORTED_GRANT_TYPE); } + // Create the access token ServerAccessToken serverToken = null; try { serverToken = handler.createAccessToken(client, params); @@ -74,15 +89,22 @@ public class AccessTokenService extends return createErrorResponse(params, OAuthConstants.INVALID_GRANT); } + // Extract the information to be of use for the client ClientAccessToken clientToken = new ClientAccessToken(serverToken.getTokenType(), serverToken.getTokenKey()); clientToken.setParameters(serverToken.getParameters()); + + + // Return it to the client return Response.ok(clientToken) .header(HttpHeaders.CACHE_CONTROL, "no-store") .header("Pragma", "no-cache") .build(); } + /** + * Make sure the client is authenticated + */ private Client authenticateClientIfNeeded(MultivaluedMap params) { Client client = null; SecurityContext sc = getMessageContext().getSecurityContext(); @@ -107,11 +129,12 @@ public class AccessTokenService extends Object clientIdProp = getMessageContext().get(OAuthConstants.CLIENT_ID); if (clientIdProp != null) { client = getClient(clientIdProp.toString()); - //TODO: - // consider matching client.getLoginName() against principal.getName() ? + // TODO: consider matching client.getUserSubject().getLoginName() + // against principal.getName() ? } } } else { + // the client id and secret are expected to be in the Basic scheme data String[] parts = AuthorizationUtils.getAuthorizationParts(getMessageContext()); if ("Basic".equals(parts[0])) { @@ -126,6 +149,7 @@ public class AccessTokenService extends return client; } + // Get the Client and check the id and secret private Client getAndValidateClient(String clientId, String clientSecret) { Client client = getClient(clientId); if (clientSecret == null || !client.getClientId().equals(clientId) @@ -135,6 +159,9 @@ public class AccessTokenService extends return client; } + /** + * Find the mathcing grant handler + */ protected AccessTokenGrantHandler findGrantHandler(MultivaluedMap params) { String grantType = params.getFirst(OAuthConstants.GRANT_TYPE); if (grantType != null) { @@ -143,6 +170,7 @@ public class AccessTokenService extends return handler; } } + // Lets try the default grant handler if (grantHandlers.size() == 0) { AuthorizationCodeGrantHandler handler = new AuthorizationCodeGrantHandler(); if (handler.getSupportedGrantTypes().contains(grantType)) { Modified: cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/AuthorizationCodeGrantService.java URL: http://svn.apache.org/viewvc/cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/AuthorizationCodeGrantService.java?rev=1308968&r1=1308967&r2=1308968&view=diff ============================================================================== --- cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/AuthorizationCodeGrantService.java (original) +++ cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/AuthorizationCodeGrantService.java Tue Apr 3 15:04:19 2012 @@ -41,7 +41,7 @@ import org.apache.cxf.rs.security.oauth2 * or denying the Client to access its resources. * If End User approves the access this resource will * redirect End User back to the Client, supplying - * a request token verifier (aka authorization code) + * the authorization code. */ @Path("/authorize") public class AuthorizationCodeGrantService extends RedirectionBasedGrantService { @@ -73,6 +73,7 @@ public class AuthorizationCodeGrantServi return createErrorResponse(params, redirectUri, OAuthConstants.ACCESS_DENIED); } + // return the code by appending it as a query parameter to the redirect URI UriBuilder ub = getRedirectUriBuilder(params.getFirst(OAuthConstants.STATE), redirectUri); ub.queryParam(OAuthConstants.AUTHORIZATION_CODE_VALUE, grant.getCode()); return Response.seeOther(ub.build()).build(); Modified: cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/ImplicitGrantService.java URL: http://svn.apache.org/viewvc/cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/ImplicitGrantService.java?rev=1308968&r1=1308967&r2=1308968&view=diff ============================================================================== --- cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/ImplicitGrantService.java (original) +++ cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/ImplicitGrantService.java Tue Apr 3 15:04:19 2012 @@ -34,10 +34,10 @@ import org.apache.cxf.rs.security.oauth2 /** + * Redirection-based Implicit Grant Service + * * This resource handles the End User authorising - * or denying the Client to access its resources. - * If End User approves the access this resource will - * return the token directly. + * or denying the Client embedded in the Web agent. * * We can consider having a single authorization service dealing with either * authorization code or implicit grant. @@ -68,6 +68,8 @@ public class ImplicitGrantService extend token = preAuthorizedToken; } + + // return the code by appending it as a fragment parameter to the redirect URI StringBuilder sb = getUriWithFragment(params.getFirst(OAuthConstants.STATE), redirectUri); sb.append(OAuthConstants.ACCESS_TOKEN).append("=").append(token.getTokenKey()); Modified: cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/RedirectionBasedGrantService.java URL: http://svn.apache.org/viewvc/cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/RedirectionBasedGrantService.java?rev=1308968&r1=1308967&r2=1308968&view=diff ============================================================================== --- cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/RedirectionBasedGrantService.java (original) +++ cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/RedirectionBasedGrantService.java Tue Apr 3 15:04:19 2012 @@ -51,11 +51,7 @@ import org.apache.cxf.security.SecurityC /** - * This resource handles the End User authorising - * or denying the Client to access its resources. - * If End User approves the access this resource will - * redirect End User back to the Client, supplying - * a request token verifier (aka authorization code) + * The Base Redirection-Based Grant Service */ public abstract class RedirectionBasedGrantService extends AbstractOAuthService { private String supportedResponseType; @@ -69,6 +65,12 @@ public abstract class RedirectionBasedGr this.isClientConfidential = isConfidential; } + /** + * Handles the initial authorization request by preparing + * the authorization challenge data and returning it to the user. + * Typically the data are expected to be presented in the HTML form + * @return the authorization data + */ @GET @Produces({"application/xhtml+xml", "text/html", "application/xml", "application/json" }) public Response authorize() { @@ -76,6 +78,10 @@ public abstract class RedirectionBasedGr return startAuthorization(params); } + /** + * Processes the end user decision + * @return The grant value, authorization code or the token + */ @GET @Path("/decision") public Response authorizeDecision() { @@ -83,6 +89,10 @@ public abstract class RedirectionBasedGr return completeAuthorization(params); } + /** + * Processes the end user decision + * @return The grant value, authorization code or the token + */ @POST @Path("/decision") @Consumes("application/x-www-form-urlencoded") @@ -90,22 +100,37 @@ public abstract class RedirectionBasedGr return completeAuthorization(params); } + /** + * Starts the authorization process + */ protected Response startAuthorization(MultivaluedMap params) { + // Make sure the end user has authenticated, check if HTTPS is used SecurityContext sc = getAndValidateSecurityContext(); - Client client = getClient(params); + Client client = getClient(params); + + // Validate the provided request URI, if any, against the ones Client provided + // during the registration String redirectUri = validateRedirectUri(client, params.getFirst(OAuthConstants.REDIRECT_URI)); + // Enforce the client confidentiality requirements if (!OAuthUtils.isGrantSupportedForClient(client, isClientConfidential, supportedGrantType)) { return createErrorResponse(params, redirectUri, OAuthConstants.UNAUTHORIZED_CLIENT); } + + // Check response_type String responseType = params.getFirst(OAuthConstants.RESPONSE_TYPE); if (responseType == null || !responseType.equals(supportedResponseType)) { return createErrorResponse(params, redirectUri, OAuthConstants.UNSUPPORTED_RESPONSE_TYPE); } + + // Get the requested scopes List requestedScope = OAuthUtils.parseScope(params.getFirst(OAuthConstants.SCOPE)); + // Create a UserSubject representing the end user UserSubject userSubject = createUserSubject(sc); + + // Request a new grant only if no pre-authorized token is available ServerAccessToken preauthorizedToken = getDataProvider().getPreauthorizedToken( client, userSubject, supportedGrantType); if (preauthorizedToken != null) { @@ -118,6 +143,7 @@ public abstract class RedirectionBasedGr preauthorizedToken); } + // Convert the requested scopes to OAuthPermission instances List permissions = null; try { permissions = getDataProvider().convertScopeToPermissions(client, requestedScope); @@ -125,13 +151,16 @@ public abstract class RedirectionBasedGr return createErrorResponse(params, redirectUri, OAuthConstants.INVALID_SCOPE); } + // Return the authorization challenge data to the end user OAuthAuthorizationData data = createAuthorizationData(client, params, permissions); return Response.ok(data).build(); } - + /** + * Create the authorization challenge data + */ protected OAuthAuthorizationData createAuthorizationData( Client client, MultivaluedMap params, List perms) { @@ -166,9 +195,14 @@ public abstract class RedirectionBasedGr return secData; } + /** + * Completes the authorization process + */ protected Response completeAuthorization(MultivaluedMap params) { + // Make sure the end user has authenticated, check if HTTPS is used SecurityContext securityContext = getAndValidateSecurityContext(); + // Make sure the session is valid if (!compareRequestAndSessionTokens(params.getFirst(OAuthConstants.SESSION_AUTHENTICITY_TOKEN))) { throw new WebApplicationException(400); } @@ -178,13 +212,16 @@ public abstract class RedirectionBasedGr Client client = getClient(params); String redirectUri = validateRedirectUri(client, params.getFirst(OAuthConstants.REDIRECT_URI)); + // Get the end user decision value String decision = params.getFirst(OAuthConstants.AUTHORIZATION_DECISION_KEY); boolean allow = OAuthConstants.AUTHORIZATION_DECISION_ALLOW.equals(decision); - + + // Return the error if denied if (!allow) { return createErrorResponse(params, redirectUri, OAuthConstants.ACCESS_DENIED); } + // Check if the end user may have had a chance to down-scope the requested scopes List requestedScope = OAuthUtils.parseScope(params.getFirst(OAuthConstants.SCOPE)); List approvedScope = new LinkedList(); for (String rScope : requestedScope) { @@ -199,6 +236,7 @@ public abstract class RedirectionBasedGr UserSubject userSubject = createUserSubject(securityContext); + // Request a new grant return createGrant(params, client, redirectUri, Modified: cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/tokens/bearer/BearerAccessToken.java URL: http://svn.apache.org/viewvc/cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/tokens/bearer/BearerAccessToken.java?rev=1308968&r1=1308967&r2=1308968&view=diff ============================================================================== --- cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/tokens/bearer/BearerAccessToken.java (original) +++ cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/tokens/bearer/BearerAccessToken.java Tue Apr 3 15:04:19 2012 @@ -23,6 +23,9 @@ import org.apache.cxf.rs.security.oauth2 import org.apache.cxf.rs.security.oauth2.utils.OAuthConstants; import org.apache.cxf.rs.security.oauth2.utils.OAuthUtils; +/** + * Simple Bearer Access Token implementations + */ public class BearerAccessToken extends ServerAccessToken { public BearerAccessToken(Client client, long lifetime) { Modified: cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/AuthorizationUtils.java URL: http://svn.apache.org/viewvc/cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/AuthorizationUtils.java?rev=1308968&r1=1308967&r2=1308968&view=diff ============================================================================== --- cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/AuthorizationUtils.java (original) +++ cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/AuthorizationUtils.java Tue Apr 3 15:04:19 2012 @@ -29,7 +29,9 @@ import javax.ws.rs.core.Response; import org.apache.cxf.common.util.Base64Utility; import org.apache.cxf.jaxrs.ext.MessageContext; - +/** + * Authorization helpers + */ public final class AuthorizationUtils { private AuthorizationUtils() { } Modified: cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/MD5SequenceGenerator.java URL: http://svn.apache.org/viewvc/cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/MD5SequenceGenerator.java?rev=1308968&r1=1308967&r2=1308968&view=diff ============================================================================== --- cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/MD5SequenceGenerator.java (original) +++ cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/MD5SequenceGenerator.java Tue Apr 3 15:04:19 2012 @@ -25,8 +25,7 @@ import org.apache.cxf.rs.security.oauth2 /** * The utility MD5 sequence generator which can be used for generating - * request or access token keys and secrets as well as request token - * verifiers + * random values */ public class MD5SequenceGenerator { public String generate(byte[] input) throws OAuthServiceException {