You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by se...@apache.org on 2012/04/03 17:04:20 UTC
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/
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<String, String> 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<AccessTokenGrantHandler> grantHandlers = Collections.emptyList();
+ /**
+ * Sets the list of optional grant handlers
+ * @param handlers the grant handlers
+ */
public void setGrantHandlers(List<AccessTokenGrantHandler> 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<String, String> 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<String, String> 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<String, String> 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<String, String> 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<String> 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<OAuthPermission> 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<String, String> params, List<OAuthPermission> perms) {
@@ -166,9 +195,14 @@ public abstract class RedirectionBasedGr
return secData;
}
+ /**
+ * Completes the authorization process
+ */
protected Response completeAuthorization(MultivaluedMap<String, String> 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<String> requestedScope = OAuthUtils.parseScope(params.getFirst(OAuthConstants.SCOPE));
List<String> approvedScope = new LinkedList<String>();
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 {