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/03/07 14:52:47 UTC
svn commit: r1297971 - in
/cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2:
common/ filters/ grants/ grants/clientcred/ grants/code/ provider/
services/ tokens/bearer/ utils/
Author: sergeyb
Date: Wed Mar 7 13:52:46 2012
New Revision: 1297971
URL: http://svn.apache.org/viewvc?rev=1297971&view=rev
Log:
[CXF-4112,CXF-4151] A lof of refactoring to do with supporting different grants, preauthorized tokens, etc
Added:
cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/AccessTokenRegistration.java (with props)
cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/ImplicitGrantService.java (with props)
cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/RedirectionBasedGrantService.java (with props)
Modified:
cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/Client.java
cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/OAuthAuthorizationData.java
cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/OAuthContext.java
cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/OAuthPermission.java
cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/UserSubject.java
cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/filters/OAuthRequestFilter.java
cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/AbstractGrantHandler.java
cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/clientcred/ClientCredentialsGrantHandler.java
cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/AuthorizationCodeGrantHandler.java
cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/AuthorizationCodeRegistration.java
cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/ServerAuthorizationCodeGrant.java
cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/OAuthDataProvider.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/tokens/bearer/BearerAccessToken.java
cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/OAuthConstants.java
cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/OAuthUtils.java
Added: cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/AccessTokenRegistration.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/AccessTokenRegistration.java?rev=1297971&view=auto
==============================================================================
--- cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/AccessTokenRegistration.java (added)
+++ cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/AccessTokenRegistration.java Wed Mar 7 13:52:46 2012
@@ -0,0 +1,65 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cxf.rs.security.oauth2.common;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Captures the information associated with the code grant registration request.
+ */
+public class AccessTokenRegistration {
+ private Client client;
+ private List<String> requestedScope = Collections.emptyList();
+ private List<String> approvedScope = Collections.emptyList();
+ private String grantType;
+ private UserSubject subject;
+
+ public void setClient(Client client) {
+ this.client = client;
+ }
+ public Client getClient() {
+ return client;
+ }
+
+ public void setRequestedScope(List<String> requestedScope) {
+ this.requestedScope = requestedScope;
+ }
+ public List<String> getRequestedScope() {
+ return requestedScope;
+ }
+ public void setSubject(UserSubject subject) {
+ this.subject = subject;
+ }
+ public UserSubject getSubject() {
+ return subject;
+ }
+ public void setGrantType(String grantType) {
+ this.grantType = grantType;
+ }
+ public String getGrantType() {
+ return grantType;
+ }
+ public void setApprovedScope(List<String> approvedScope) {
+ this.approvedScope = approvedScope;
+ }
+ public List<String> getApprovedScope() {
+ return approvedScope;
+ }
+}
Propchange: cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/AccessTokenRegistration.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/AccessTokenRegistration.java
------------------------------------------------------------------------------
svn:keywords = Rev Date
Modified: cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/Client.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/Client.java?rev=1297971&r1=1297970&r2=1297971&view=diff
==============================================================================
--- cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/Client.java (original)
+++ cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/Client.java Wed Mar 7 13:52:46 2012
@@ -35,11 +35,12 @@ public class Client {
private String applicationDescription;
private String applicationWebUri;
private String applicationLogoUri;
-
private List<String> redirectUris = Collections.emptyList();
+
private boolean isConfidential;
+ private List<String> allowedGrantTypes = Collections.emptyList();
- private String loginName;
+ private UserSubject subject;
public Client(String clientId, String clientSecret, boolean isConfidential) {
this.clientId = clientId;
@@ -137,24 +138,6 @@ public class Client {
return applicationLogoUri;
}
- /**
- * Gets the optional login name which does not necessarily matches
- * the clientId; can be used for enforcing the existing RBAC rules.
- *
- * @return the login name
- */
- public String getLoginName() {
- return loginName;
- }
-
- /**
- * Sets the optional login name
- * @param name the login name
- */
- public void setLoginName(String name) {
- this.loginName = name;
- }
-
public void setConfidential(boolean isConf) {
this.isConfidential = isConf;
}
@@ -170,4 +153,20 @@ public class Client {
public List<String> getRedirectUris() {
return redirectUris;
}
+
+ public void setAllowedGrantTypes(List<String> allowedGrantTypes) {
+ this.allowedGrantTypes = allowedGrantTypes;
+ }
+
+ public List<String> getAllowedGrantTypes() {
+ return allowedGrantTypes;
+ }
+
+ public void setSubject(UserSubject subject) {
+ this.subject = subject;
+ }
+
+ public UserSubject getSubject() {
+ return subject;
+ }
}
Modified: cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/OAuthAuthorizationData.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/OAuthAuthorizationData.java?rev=1297971&r1=1297970&r2=1297971&view=diff
==============================================================================
--- cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/OAuthAuthorizationData.java (original)
+++ cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/OAuthAuthorizationData.java Wed Mar 7 13:52:46 2012
@@ -37,6 +37,7 @@ public class OAuthAuthorizationData impl
private String redirectUri;
private String state;
private String proposedScope;
+
private String authenticityToken;
private String replyTo;
Modified: cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/OAuthContext.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/OAuthContext.java?rev=1297971&r1=1297970&r2=1297971&view=diff
==============================================================================
--- cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/OAuthContext.java (original)
+++ cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/OAuthContext.java Wed Mar 7 13:52:46 2012
@@ -47,7 +47,6 @@ public class OAuthContext {
return Collections.unmodifiableList(permissions);
}
-
public String getTokenGrantType() {
return tokenGrantType;
}
Modified: cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/OAuthPermission.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/OAuthPermission.java?rev=1297971&r1=1297970&r2=1297971&view=diff
==============================================================================
--- cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/OAuthPermission.java (original)
+++ cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/OAuthPermission.java Wed Mar 7 13:52:46 2012
@@ -25,7 +25,6 @@ import java.util.List;
* Provides the complete information about a given opaque permission.
*/
public class OAuthPermission extends Permission {
- private List<String> roles = Collections.emptyList();
private List<String> httpVerbs = Collections.emptyList();
private List<String> uris = Collections.emptyList();
@@ -33,19 +32,6 @@ public class OAuthPermission extends Per
super(permission, description);
}
- public OAuthPermission(String permission, String description, List<String> roles) {
- super(permission, description);
- this.roles = roles;
- }
-
- public void setRoles(List<String> roles) {
- this.roles = roles;
- }
-
- public List<String> getRoles() {
- return roles;
- }
-
public void setHttpVerbs(List<String> httpVerbs) {
this.httpVerbs = httpVerbs;
}
Modified: cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/UserSubject.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/UserSubject.java?rev=1297971&r1=1297970&r2=1297971&view=diff
==============================================================================
--- cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/UserSubject.java (original)
+++ cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/UserSubject.java Wed Mar 7 13:52:46 2012
@@ -28,7 +28,11 @@ import java.util.List;
public class UserSubject {
private String login;
- private List<String> roles;
+ private List<String> roles = Collections.emptyList();
+
+ public UserSubject(String login) {
+ this.login = login;
+ }
public UserSubject(String login, List<String> roles) {
this.login = login;
Modified: cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/filters/OAuthRequestFilter.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/filters/OAuthRequestFilter.java?rev=1297971&r1=1297970&r2=1297971&view=diff
==============================================================================
--- cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/filters/OAuthRequestFilter.java (original)
+++ cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/filters/OAuthRequestFilter.java Wed Mar 7 13:52:46 2012
@@ -94,10 +94,11 @@ public class OAuthRequestFilter implemen
throw new WebApplicationException(403);
}
- OAuthInfo info = new OAuthInfo(accessToken, matchingPermissions);
- SecurityContext sc = createSecurityContext(req, info);
+ SecurityContext sc = createSecurityContext(req, accessToken);
m.put(SecurityContext.class, sc);
- m.setContent(OAuthContext.class, createOAuthContext(info));
+ m.setContent(OAuthContext.class, new OAuthContext(accessToken.getSubject(),
+ matchingPermissions,
+ accessToken.getGrantType()));
return null;
}
@@ -192,66 +193,27 @@ public class OAuthRequestFilter implemen
}
protected SecurityContext createSecurityContext(HttpServletRequest request,
- final OAuthInfo info) {
- UserSubject subject = info.getToken().getSubject();
+ ServerAccessToken token) {
+ UserSubject endUserSubject = token.getSubject();
+ UserSubject clientSubject = token.getClient().getSubject();
- final UserSubject theSubject = subject;
- final String login = OAuthRequestFilter.this.useUserSubject
- ? (theSubject != null ? theSubject.getLogin() : null)
- : info.getToken().getClient().getLoginName();
+ final UserSubject theSubject =
+ OAuthRequestFilter.this.useUserSubject ? endUserSubject : clientSubject;
return new SecurityContext() {
public Principal getUserPrincipal() {
- return login != null ? new SimplePrincipal(login) : null;
+ return theSubject != null ? new SimplePrincipal(theSubject.getLogin()) : null;
}
public boolean isUserInRole(String role) {
- if (login == null) {
+ if (theSubject == null) {
return false;
}
- List<String> roles = null;
- if (OAuthRequestFilter.this.useUserSubject && theSubject != null) {
- roles = theSubject.getRoles();
- } else {
- roles = info.getRoles();
- }
- return roles == null ? false : roles.contains(role);
+ return theSubject.getRoles().contains(role);
}
-
};
}
- private OAuthContext createOAuthContext(OAuthInfo info) {
- return new OAuthContext(info.getToken().getSubject(),
- info.getMatchedPermissions(),
- info.getToken().getGrantType());
- }
-
- private static class OAuthInfo {
- private ServerAccessToken token;
- private List<OAuthPermission> permissions;
- public OAuthInfo(ServerAccessToken token,
- List<OAuthPermission> matchedPermissions) {
- this.token = token;
- this.permissions = matchedPermissions;
- }
- public ServerAccessToken getToken() {
- return token;
- }
-
- public List<String> getRoles() {
- List<String> authorities = new ArrayList<String>();
- for (OAuthPermission permission : permissions) {
- authorities.addAll(permission.getRoles());
- }
- return authorities;
- }
-
- public List<OAuthPermission> getMatchedPermissions() {
- return permissions;
- }
-
-
- }
+
}
Modified: cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/AbstractGrantHandler.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/AbstractGrantHandler.java?rev=1297971&r1=1297970&r2=1297971&view=diff
==============================================================================
--- cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/AbstractGrantHandler.java (original)
+++ cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/AbstractGrantHandler.java Wed Mar 7 13:52:46 2012
@@ -21,26 +21,27 @@ package org.apache.cxf.rs.security.oauth
import java.util.Collections;
import java.util.List;
-import java.util.UUID;
+import org.apache.cxf.rs.security.oauth2.common.AccessTokenRegistration;
+import org.apache.cxf.rs.security.oauth2.common.Client;
+import org.apache.cxf.rs.security.oauth2.common.ServerAccessToken;
+import org.apache.cxf.rs.security.oauth2.common.UserSubject;
import org.apache.cxf.rs.security.oauth2.provider.AccessTokenGrantHandler;
import org.apache.cxf.rs.security.oauth2.provider.OAuthDataProvider;
import org.apache.cxf.rs.security.oauth2.provider.OAuthServiceException;
-import org.apache.cxf.rs.security.oauth2.utils.MD5SequenceGenerator;
import org.apache.cxf.rs.security.oauth2.utils.OAuthConstants;
+import org.apache.cxf.rs.security.oauth2.utils.OAuthUtils;
public abstract class AbstractGrantHandler implements AccessTokenGrantHandler {
- private static final long DEFAULT_TOKEN_LIFETIME = 3600L;
-
- private long tokenLifetime = DEFAULT_TOKEN_LIFETIME;
- private List<String> supportedGrants;
+ private String supportedGrant;
private OAuthDataProvider dataProvider;
-
- protected AbstractGrantHandler(String grant) {
- supportedGrants = Collections.singletonList(grant);
+ private boolean isClientConfidential;
+ protected AbstractGrantHandler(String grant, boolean isClientConfidential) {
+ supportedGrant = grant;
+ this.isClientConfidential = isClientConfidential;
}
public void setDataProvider(OAuthDataProvider dataProvider) {
@@ -51,25 +52,30 @@ public abstract class AbstractGrantHandl
}
public List<String> getSupportedGrantTypes() {
- return supportedGrants;
+ return Collections.singletonList(supportedGrant);
}
- protected static String generateRandomTokenKey() throws OAuthServiceException {
- try {
- byte[] bytes = UUID.randomUUID().toString().getBytes("UTF-8");
- return new MD5SequenceGenerator().generate(bytes);
- } catch (Exception ex) {
- throw new OAuthServiceException(OAuthConstants.SERVER_ERROR, ex);
+ protected void checkIfGrantSupported(Client client) {
+ if (!OAuthUtils.isGrantSupportedForClient(client, isClientConfidential, supportedGrant)) {
+ throw new OAuthServiceException(OAuthConstants.UNAUTHORIZED_CLIENT);
}
}
-
- public void setTokenLifetime(long tokenLifetime) {
- this.tokenLifetime = tokenLifetime;
- }
-
- public long getTokenLifetime() {
- return tokenLifetime;
- }
-
+ protected ServerAccessToken doCreateAccessToken(Client client,
+ UserSubject subject,
+ List<String> requestedScope) {
+ ServerAccessToken token = dataProvider.getPreauthorizedToken(
+ client, subject, supportedGrant);
+ if (token != null) {
+ return token;
+ }
+
+ AccessTokenRegistration reg = new AccessTokenRegistration();
+ reg.setClient(client);
+ reg.setGrantType(supportedGrant);
+ reg.setSubject(subject);
+ reg.setRequestedScope(requestedScope);
+
+ return dataProvider.createAccessToken(reg);
+ }
}
Modified: cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/clientcred/ClientCredentialsGrantHandler.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/clientcred/ClientCredentialsGrantHandler.java?rev=1297971&r1=1297970&r2=1297971&view=diff
==============================================================================
--- cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/clientcred/ClientCredentialsGrantHandler.java (original)
+++ cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/clientcred/ClientCredentialsGrantHandler.java Wed Mar 7 13:52:46 2012
@@ -24,30 +24,26 @@ import org.apache.cxf.rs.security.oauth2
import org.apache.cxf.rs.security.oauth2.common.ServerAccessToken;
import org.apache.cxf.rs.security.oauth2.grants.AbstractGrantHandler;
import org.apache.cxf.rs.security.oauth2.provider.OAuthServiceException;
-import org.apache.cxf.rs.security.oauth2.tokens.bearer.BearerAccessToken;
import org.apache.cxf.rs.security.oauth2.utils.OAuthConstants;
+import org.apache.cxf.rs.security.oauth2.utils.OAuthUtils;
-public class ClientCredentialsGrantHandler extends AbstractGrantHandler {
+public class ClientCredentialsGrantHandler extends AbstractGrantHandler {
+
public ClientCredentialsGrantHandler() {
- super(OAuthConstants.CLIENT_CREDENTIALS_GRANT);
+ super(OAuthConstants.CLIENT_CREDENTIALS_GRANT, true);
}
public ServerAccessToken createAccessToken(Client client, MultivaluedMap<String, String> params)
throws OAuthServiceException {
- if (!client.isConfidential()) {
- throw new OAuthServiceException(OAuthConstants.UNAUTHORIZED_CLIENT);
- }
- BearerAccessToken token = new BearerAccessToken(client,
- generateRandomTokenKey(),
- getTokenLifetime(),
- System.currentTimeMillis() / 1000);
- token.setGrantType(OAuthConstants.CLIENT_CREDENTIALS_GRANT);
- // the OAuth filter will use Client.getLoginName() to initialize
- // the Principal when setting up the security context
-
- return token;
+ checkIfGrantSupported(client);
+ // the OAuth filter will use Client.getLoginName() to initialize
+ // the Principal when setting up the security context
+ // TODO: consider setting the UserSubject representing the authenticated Client instead
+ return doCreateAccessToken(client,
+ null,
+ OAuthUtils.parseScope(params.getFirst(OAuthConstants.SCOPE)));
}
Modified: cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/AuthorizationCodeGrantHandler.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/AuthorizationCodeGrantHandler.java?rev=1297971&r1=1297970&r2=1297971&view=diff
==============================================================================
--- cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/AuthorizationCodeGrantHandler.java (original)
+++ cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/AuthorizationCodeGrantHandler.java Wed Mar 7 13:52:46 2012
@@ -25,7 +25,6 @@ import org.apache.cxf.rs.security.oauth2
import org.apache.cxf.rs.security.oauth2.common.ServerAccessToken;
import org.apache.cxf.rs.security.oauth2.grants.AbstractGrantHandler;
import org.apache.cxf.rs.security.oauth2.provider.OAuthServiceException;
-import org.apache.cxf.rs.security.oauth2.tokens.bearer.BearerAccessToken;
import org.apache.cxf.rs.security.oauth2.utils.OAuthConstants;
import org.apache.cxf.rs.security.oauth2.utils.OAuthUtils;
@@ -34,11 +33,13 @@ import org.apache.cxf.rs.security.oauth2
public class AuthorizationCodeGrantHandler extends AbstractGrantHandler {
public AuthorizationCodeGrantHandler() {
- super(OAuthConstants.AUTHORIZATION_CODE_GRANT);
+ super(OAuthConstants.AUTHORIZATION_CODE_GRANT, true);
}
public ServerAccessToken createAccessToken(Client client, MultivaluedMap<String, String> params)
throws OAuthServiceException {
+ checkIfGrantSupported(client);
+
String codeValue = params.getFirst(OAuthConstants.AUTHORIZATION_CODE_VALUE);
ServerAuthorizationCodeGrant grant =
((AuthorizationCodeDataProvider)getDataProvider()).removeCodeGrant(codeValue);
@@ -48,22 +49,18 @@ public class AuthorizationCodeGrantHandl
if (OAuthUtils.isExpired(grant.getIssuedAt(), grant.getLifetime())) {
throw new OAuthServiceException(OAuthConstants.INVALID_GRANT);
}
-
+ if (!grant.getClient().getClientId().equals(client.getClientId())) {
+ throw new OAuthServiceException(OAuthConstants.INVALID_GRANT);
+ }
String expectedRedirectUri = grant.getRedirectUri();
if (expectedRedirectUri != null) {
String providedRedirectUri = params.getFirst(OAuthConstants.REDIRECT_URI);
- if (providedRedirectUri == null || !providedRedirectUri.equals(expectedRedirectUri)) {
+
+ if (providedRedirectUri != null && !providedRedirectUri.equals(expectedRedirectUri)) {
throw new OAuthServiceException(OAuthConstants.INVALID_REQUEST);
}
}
- BearerAccessToken token = new BearerAccessToken(client,
- generateRandomTokenKey(),
- getTokenLifetime(),
- System.currentTimeMillis() / 1000);
- token.setScopes(grant.getApprovedScopes());
- token.setSubject(grant.getSubject());
- token.setGrantType(OAuthConstants.AUTHORIZATION_CODE_GRANT);
- return token;
+ return doCreateAccessToken(client, grant.getSubject(), grant.getApprovedScopes());
}
}
Modified: cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/AuthorizationCodeRegistration.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/AuthorizationCodeRegistration.java?rev=1297971&r1=1297970&r2=1297971&view=diff
==============================================================================
--- cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/AuthorizationCodeRegistration.java (original)
+++ cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/AuthorizationCodeRegistration.java Wed Mar 7 13:52:46 2012
@@ -18,6 +18,7 @@
*/
package org.apache.cxf.rs.security.oauth2.grants.code;
+import java.util.Collections;
import java.util.List;
import org.apache.cxf.rs.security.oauth2.common.Client;
@@ -29,10 +30,8 @@ import org.apache.cxf.rs.security.oauth2
*/
public class AuthorizationCodeRegistration {
private Client client;
- private List<String> requestedScope;
- private List<String> approvedScope;
- private long lifetime;
- private long issuedAt;
+ private List<String> requestedScope = Collections.emptyList();
+ private List<String> approvedScope = Collections.emptyList();
private String redirectUri;
private UserSubject subject;
@@ -43,18 +42,6 @@ public class AuthorizationCodeRegistrati
return client;
}
- public void setLifetime(long lifetime) {
- this.lifetime = lifetime;
- }
- public long getLifetime() {
- return lifetime;
- }
- public void setIssuedAt(long issuedAt) {
- this.issuedAt = issuedAt;
- }
- public long getIssuedAt() {
- return issuedAt;
- }
public void setRedirectUri(String redirectUri) {
this.redirectUri = redirectUri;
}
Modified: cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/ServerAuthorizationCodeGrant.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/ServerAuthorizationCodeGrant.java?rev=1297971&r1=1297970&r2=1297971&view=diff
==============================================================================
--- cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/ServerAuthorizationCodeGrant.java (original)
+++ cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/ServerAuthorizationCodeGrant.java Wed Mar 7 13:52:46 2012
@@ -22,8 +22,8 @@ import java.util.Collections;
import java.util.List;
import org.apache.cxf.rs.security.oauth2.common.Client;
-import org.apache.cxf.rs.security.oauth2.common.OAuthPermission;
import org.apache.cxf.rs.security.oauth2.common.UserSubject;
+import org.apache.cxf.rs.security.oauth2.utils.OAuthUtils;
/**
@@ -33,10 +33,16 @@ public class ServerAuthorizationCodeGran
private long issuedAt;
private long lifetime;
private Client client;
- private List<OAuthPermission> approvedScopes = Collections.emptyList();
+ private List<String> approvedScopes = Collections.emptyList();
private UserSubject subject;
public ServerAuthorizationCodeGrant(Client client,
+ long lifetime) {
+ this(client, OAuthUtils.generateRandomTokenKey(), lifetime,
+ System.currentTimeMillis() / 1000);
+ }
+
+ public ServerAuthorizationCodeGrant(Client client,
String code,
long lifetime,
long issuedAt) {
@@ -60,12 +66,12 @@ public class ServerAuthorizationCodeGran
}
- public void setApprovedScopes(List<OAuthPermission> scopes) {
+ public void setApprovedScopes(List<String> scopes) {
this.approvedScopes = scopes;
}
- public List<OAuthPermission> getApprovedScopes() {
+ public List<String> getApprovedScopes() {
return approvedScopes;
}
Modified: cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/OAuthDataProvider.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/OAuthDataProvider.java?rev=1297971&r1=1297970&r2=1297971&view=diff
==============================================================================
--- cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/OAuthDataProvider.java (original)
+++ cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/OAuthDataProvider.java Wed Mar 7 13:52:46 2012
@@ -21,9 +21,11 @@ package org.apache.cxf.rs.security.oauth
import java.util.List;
+import org.apache.cxf.rs.security.oauth2.common.AccessTokenRegistration;
import org.apache.cxf.rs.security.oauth2.common.Client;
import org.apache.cxf.rs.security.oauth2.common.OAuthPermission;
import org.apache.cxf.rs.security.oauth2.common.ServerAccessToken;
+import org.apache.cxf.rs.security.oauth2.common.UserSubject;
/**
* OAuth provider responsible for persisting the information about
@@ -46,7 +48,7 @@ public interface OAuthDataProvider {
* @return AccessToken
* @throws OAuthServiceException
*/
- void persistAccessToken(ServerAccessToken accessToken) throws OAuthServiceException;
+ ServerAccessToken createAccessToken(AccessTokenRegistration accessToken) throws OAuthServiceException;
/**
* Get access token
@@ -57,6 +59,16 @@ public interface OAuthDataProvider {
ServerAccessToken getAccessToken(String accessToken) throws OAuthServiceException;
/**
+ * TODO: Consider introducing a dedicated entity representing a user pre authorization
+ * Get preauthorized access token
+ * @param accessToken the token key
+ * @return AccessToken
+ * @throws OAuthServiceException
+ */
+ ServerAccessToken getPreauthorizedToken(Client client, UserSubject subject, String grantType)
+ throws OAuthServiceException;
+
+ /**
* Refresh access token
* @param clientId the client id
* @param refreshToken the token key
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=1297971&r1=1297970&r2=1297971&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 Wed Mar 7 13:52:46 2012
@@ -73,7 +73,6 @@ public class AccessTokenService extends
if (serverToken == null) {
return createErrorResponse(params, OAuthConstants.INVALID_GRANT);
}
- getDataProvider().persistAccessToken(serverToken);
ClientAccessToken clientToken = new ClientAccessToken(serverToken.getTokenType(),
serverToken.getTokenKey());
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=1297971&r1=1297970&r2=1297971&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 Wed Mar 7 13:52:46 2012
@@ -19,37 +19,21 @@
package org.apache.cxf.rs.security.oauth2.services;
-import java.security.Principal;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.LinkedList;
import java.util.List;
-import java.util.Set;
-import java.util.UUID;
-import javax.servlet.http.HttpSession;
-import javax.ws.rs.Consumes;
-import javax.ws.rs.GET;
-import javax.ws.rs.POST;
import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
-import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
-import org.apache.cxf.common.util.StringUtils;
import org.apache.cxf.rs.security.oauth2.common.Client;
-import org.apache.cxf.rs.security.oauth2.common.OAuthAuthorizationData;
-import org.apache.cxf.rs.security.oauth2.common.OAuthPermission;
+import org.apache.cxf.rs.security.oauth2.common.ServerAccessToken;
import org.apache.cxf.rs.security.oauth2.common.UserSubject;
import org.apache.cxf.rs.security.oauth2.grants.code.AuthorizationCodeDataProvider;
import org.apache.cxf.rs.security.oauth2.grants.code.AuthorizationCodeRegistration;
import org.apache.cxf.rs.security.oauth2.grants.code.ServerAuthorizationCodeGrant;
import org.apache.cxf.rs.security.oauth2.provider.OAuthServiceException;
import org.apache.cxf.rs.security.oauth2.utils.OAuthConstants;
-import org.apache.cxf.security.LoginSecurityContext;
-import org.apache.cxf.security.SecurityContext;
/**
@@ -60,182 +44,38 @@ import org.apache.cxf.security.SecurityC
* a request token verifier (aka authorization code)
*/
@Path("/authorize")
-public class AuthorizationCodeGrantService extends AbstractOAuthService {
- private static final long DEFAULT_CODE_GRANT_LIFETIME = 3600L;
-
- private long grantLifetime = DEFAULT_CODE_GRANT_LIFETIME;
-
- @GET
- @Produces({"application/xhtml+xml", "text/html", "application/xml", "application/json" })
- public Response authorize() {
- MultivaluedMap<String, String> params = getQueryParameters();
- return startAuthorization(params);
- }
-
- @GET
- @Path("/decision")
- public Response authorizeDecision() {
- MultivaluedMap<String, String> params = getQueryParameters();
- return completeAuthorization(params);
- }
-
- @POST
- @Path("/decision")
- @Consumes("application/x-www-form-urlencoded")
- public Response authorizeDecisionForm(MultivaluedMap<String, String> params) {
- return completeAuthorization(params);
- }
-
- protected Response startAuthorization(MultivaluedMap<String, String> params) {
- getAndValidateSecurityContext();
-
- Client client = getClient(params);
- String redirectUri = validateRedirectUri(client, params.getFirst(OAuthConstants.REDIRECT_URI));
- if (!client.isConfidential()) {
- return createErrorResponse(params, redirectUri, OAuthConstants.UNAUTHORIZED_CLIENT);
- }
- String responseType = params.getFirst(OAuthConstants.RESPONSE_TYPE);
- if (responseType == null || !responseType.equals(OAuthConstants.CODE_RESPONSE_TYPE)) {
- return createErrorResponse(params, redirectUri, OAuthConstants.UNSUPPORTED_RESPONSE_TYPE);
- }
-
- List<OAuthPermission> permissions = null;
- try {
- permissions = convertScopeToPermissions(client, params.getFirst(OAuthConstants.SCOPE));
- } catch (OAuthServiceException ex) {
- return createErrorResponse(params, redirectUri, OAuthConstants.INVALID_SCOPE);
- }
- OAuthAuthorizationData data =
- createAuthorizationData(client, params, permissions);
- return Response.ok(data).build();
-
- }
-
- public void setGrantLifetime(long lifetime) {
- this.grantLifetime = lifetime;
+public class AuthorizationCodeGrantService extends RedirectionBasedGrantService {
+ public AuthorizationCodeGrantService() {
+ super(OAuthConstants.CODE_RESPONSE_TYPE, OAuthConstants.AUTHORIZATION_CODE_GRANT, true);
}
- protected List<OAuthPermission> convertScopeToPermissions(Client client, String scope)
- throws OAuthServiceException {
- List<String> list = parseScope(scope);
-
- List<OAuthPermission> permissions = getDataProvider()
- .convertScopeToPermissions(client, list);
-
- return permissions;
- }
-
- protected OAuthAuthorizationData createAuthorizationData(
- Client client, MultivaluedMap<String, String> params, List<OAuthPermission> perms) {
-
- OAuthAuthorizationData secData = new OAuthAuthorizationData();
-
- addAuthenticityTokenToSession(secData);
-
- secData.setPermissions(perms);
-
- StringBuilder sb = new StringBuilder();
- for (OAuthPermission perm : perms) {
- if (sb.length() > 0) {
- sb.append(" ");
- }
- sb.append(perm.getPermission());
- }
- secData.setProposedScope(sb.toString());
-
- secData.setClientId(client.getClientId());
- secData.setRedirectUri(params.getFirst(OAuthConstants.REDIRECT_URI));
- secData.setState(params.getFirst(OAuthConstants.STATE));
-
- secData.setApplicationName(client.getApplicationName());
- secData.setApplicationWebUri(client.getApplicationWebUri());
- secData.setApplicationDescription(client.getApplicationDescription());
- secData.setApplicationLogoUri(client.getApplicationLogoUri());
-
- String replyTo = getMessageContext().getUriInfo()
- .getAbsolutePathBuilder().path("decision").build().toString();
- secData.setReplyTo(replyTo);
-
- return secData;
- }
-
- protected Response completeAuthorization(MultivaluedMap<String, String> params) {
- SecurityContext securityContext = getAndValidateSecurityContext();
-
- if (!compareRequestAndSessionTokens(params.getFirst(OAuthConstants.SESSION_AUTHENTICITY_TOKEN))) {
- throw new WebApplicationException(400);
- }
- //TODO: additionally we can check that the Principal that got authenticated
- // in startAuthorization is the same that got authenticated in completeAuthorization
-
- Client client = getClient(params);
- String originalRedirectUri = params.getFirst(OAuthConstants.REDIRECT_URI);
- String actualRedirectUri = validateRedirectUri(client, originalRedirectUri);
-
- String decision = params.getFirst(OAuthConstants.AUTHORIZATION_DECISION_KEY);
- boolean allow = OAuthConstants.AUTHORIZATION_DECISION_ALLOW.equals(decision);
-
- if (!allow) {
- return createErrorResponse(params, actualRedirectUri, OAuthConstants.ACCESS_DENIED);
- }
-
+ protected Response createGrant(MultivaluedMap<String, String> params,
+ Client client,
+ String redirectUri,
+ List<String> requestedScope,
+ List<String> approvedScope,
+ UserSubject userSubject,
+ ServerAccessToken preauthorizedToken) {
+ // in this flow the code is still created, the preauthorized token
+ // will be retrieved by the authorization code grant handler
AuthorizationCodeRegistration codeReg = new AuthorizationCodeRegistration();
codeReg.setClient(client);
- codeReg.setRedirectUri(originalRedirectUri);
- codeReg.setLifetime(grantLifetime);
- codeReg.setIssuedAt(System.currentTimeMillis() / 1000);
-
- List<String> requestedScope = parseScope(params.getFirst(OAuthConstants.SCOPE));
+ codeReg.setRedirectUri(redirectUri);
codeReg.setRequestedScope(requestedScope);
-
- List<String> approvedScope = new LinkedList<String>();
- for (String rScope : requestedScope) {
- String param = params.getFirst(rScope + "_status");
- if (param != null && OAuthConstants.AUTHORIZATION_DECISION_ALLOW.equals(param)) {
- approvedScope.add(rScope);
- }
- }
- if (!requestedScope.containsAll(approvedScope)) {
- return createErrorResponse(params, actualRedirectUri, OAuthConstants.INVALID_SCOPE);
- }
- // the decision was allow but the approved scopes end up being empty
- // in this case we default to the requestedScope
- if (approvedScope.isEmpty()) {
- approvedScope = requestedScope;
- }
codeReg.setApprovedScope(approvedScope);
-
- List<String> roleNames = Collections.emptyList();
- if (securityContext instanceof LoginSecurityContext) {
- roleNames = new ArrayList<String>();
- Set<Principal> roles = ((LoginSecurityContext)securityContext).getUserRoles();
- for (Principal p : roles) {
- roleNames.add(p.getName());
- }
- }
- codeReg.setSubject(new UserSubject(securityContext.getUserPrincipal().getName(), roleNames));
+ codeReg.setSubject(userSubject);
ServerAuthorizationCodeGrant grant = null;
try {
grant = ((AuthorizationCodeDataProvider)getDataProvider()).createCodeGrant(codeReg);
} catch (OAuthServiceException ex) {
- return createErrorResponse(params, actualRedirectUri, OAuthConstants.ACCESS_DENIED);
+ return createErrorResponse(params, redirectUri, OAuthConstants.ACCESS_DENIED);
}
- UriBuilder ub = getRedirectUriBuilder(params.getFirst(OAuthConstants.STATE), actualRedirectUri);
+ UriBuilder ub = getRedirectUriBuilder(params.getFirst(OAuthConstants.STATE), redirectUri);
ub.queryParam(OAuthConstants.AUTHORIZATION_CODE_VALUE, grant.getCode());
- return Response.seeOther(ub.build()).build();
- }
-
- private SecurityContext getAndValidateSecurityContext() {
- SecurityContext securityContext =
- (SecurityContext)getMessageContext().get(SecurityContext.class.getName());
- if (securityContext == null || securityContext.getUserPrincipal() == null) {
- throw new WebApplicationException(401);
- }
- checkTransportSecurity();
- return securityContext;
+ return Response.seeOther(ub.build()).build();
}
protected Response createErrorResponse(MultivaluedMap<String, String> params,
@@ -246,62 +86,13 @@ public class AuthorizationCodeGrantServi
return Response.seeOther(ub.build()).build();
}
- private List<String> parseScope(String requestedScope) {
- List<String> list = new LinkedList<String>();
- if (requestedScope != null) {
- String[] scopeValues = requestedScope.split(" ");
- for (String scope : scopeValues) {
- if (!StringUtils.isEmpty(scope)) {
- list.add(scope);
- }
- }
- }
- return list;
- }
-
- private UriBuilder getRedirectUriBuilder(String state, String redirectUri) {
+ protected UriBuilder getRedirectUriBuilder(String state, String redirectUri) {
UriBuilder ub = UriBuilder.fromUri(redirectUri);
if (state != null) {
ub.queryParam(OAuthConstants.STATE, state);
}
return ub;
}
-
- protected String validateRedirectUri(Client client, String redirectUri) {
-
- List<String> uris = client.getRedirectUris();
- if (redirectUri != null) {
- String webUri = client.getApplicationWebUri();
- if (uris.size() > 0 && !uris.contains(redirectUri)
- || webUri != null && !redirectUri.startsWith(webUri)) {
- redirectUri = null;
- }
- } else if (uris.size() == 1) {
- redirectUri = uris.get(0);
- }
- if (redirectUri == null) {
- reportInvalidRequestError("Client Redirect Uri is invalid");
- }
- return redirectUri;
- }
-
- private void addAuthenticityTokenToSession(OAuthAuthorizationData secData) {
- HttpSession session = getMessageContext().getHttpServletRequest().getSession();
- String value = UUID.randomUUID().toString();
- secData.setAuthenticityToken(value);
- session.setAttribute(OAuthConstants.SESSION_AUTHENTICITY_TOKEN, value);
- }
-
- private boolean compareRequestAndSessionTokens(String requestToken) {
- HttpSession session = getMessageContext().getHttpServletRequest().getSession();
- String sessionToken = (String)session.getAttribute(OAuthConstants.SESSION_AUTHENTICITY_TOKEN);
-
- if (StringUtils.isEmpty(sessionToken)) {
- return false;
- }
-
- session.removeAttribute(OAuthConstants.SESSION_AUTHENTICITY_TOKEN);
- return requestToken.equals(sessionToken);
- }
-
}
+
+
Added: 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=1297971&view=auto
==============================================================================
--- cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/ImplicitGrantService.java (added)
+++ cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/ImplicitGrantService.java Wed Mar 7 13:52:46 2012
@@ -0,0 +1,101 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.cxf.rs.security.oauth2.services;
+
+import java.net.URI;
+import java.util.List;
+
+import javax.ws.rs.Path;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+
+import org.apache.cxf.rs.security.oauth2.common.AccessTokenRegistration;
+import org.apache.cxf.rs.security.oauth2.common.Client;
+import org.apache.cxf.rs.security.oauth2.common.ServerAccessToken;
+import org.apache.cxf.rs.security.oauth2.common.UserSubject;
+import org.apache.cxf.rs.security.oauth2.utils.OAuthConstants;
+
+
+/**
+ * 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.
+ *
+ * We can consider having a single authorization service dealing with either
+ * authorization code or implicit grant.
+ */
+@Path("/authorize-implicit")
+public class ImplicitGrantService extends RedirectionBasedGrantService {
+ public ImplicitGrantService() {
+ super(OAuthConstants.TOKEN_RESPONSE_TYPE, OAuthConstants.IMPLICIT_GRANT, false);
+ }
+
+ protected Response createGrant(MultivaluedMap<String, String> params,
+ Client client,
+ String redirectUri,
+ List<String> requestedScope,
+ List<String> approvedScope,
+ UserSubject userSubject,
+ ServerAccessToken preAuthorizedToken) {
+ ServerAccessToken token = null;
+ if (preAuthorizedToken != null) {
+ AccessTokenRegistration reg = new AccessTokenRegistration();
+ reg.setClient(client);
+ reg.setGrantType(OAuthConstants.IMPLICIT_GRANT);
+ reg.setSubject(userSubject);
+ reg.setRequestedScope(requestedScope);
+ reg.setApprovedScope(approvedScope);
+ token = getDataProvider().createAccessToken(reg);
+ } else {
+ token = preAuthorizedToken;
+ }
+
+
+ StringBuilder sb = getUriWithFragment(params.getFirst(OAuthConstants.STATE), redirectUri);
+ sb.append(OAuthConstants.ACCESS_TOKEN).append("=").append(token.getTokenKey());
+ sb.append(OAuthConstants.ACCESS_TOKEN_TYPE).append("=").append(token.getTokenType());
+ //TODO: token parameters should also be included probably
+ // though it's not obvious the embedded client can deal with
+ // MAC tokens or other sophisticated tokens
+ return Response.seeOther(URI.create(sb.toString())).build();
+ }
+
+ protected Response createErrorResponse(MultivaluedMap<String, String> params,
+ String redirectUri,
+ String error) {
+ StringBuilder sb = getUriWithFragment(params.getFirst(OAuthConstants.STATE), redirectUri);
+ sb.append(OAuthConstants.ERROR_KEY).append("=").append(error);
+ return Response.seeOther(URI.create(sb.toString())).build();
+ }
+
+ private StringBuilder getUriWithFragment(String state, String redirectUri) {
+ StringBuilder sb = new StringBuilder();
+ sb.append(redirectUri);
+ sb.append("#");
+ if (state != null) {
+ sb.append(OAuthConstants.STATE).append("=").append(state);
+ }
+ return sb;
+ }
+
+}
+
+
Propchange: cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/ImplicitGrantService.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/ImplicitGrantService.java
------------------------------------------------------------------------------
svn:keywords = Rev Date
Added: 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=1297971&view=auto
==============================================================================
--- cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/RedirectionBasedGrantService.java (added)
+++ cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/RedirectionBasedGrantService.java Wed Mar 7 13:52:46 2012
@@ -0,0 +1,284 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.cxf.rs.security.oauth2.services;
+
+import java.security.Principal;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+import java.util.UUID;
+
+import javax.servlet.http.HttpSession;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+
+import org.apache.cxf.common.util.StringUtils;
+import org.apache.cxf.rs.security.oauth2.common.Client;
+import org.apache.cxf.rs.security.oauth2.common.OAuthAuthorizationData;
+import org.apache.cxf.rs.security.oauth2.common.OAuthPermission;
+import org.apache.cxf.rs.security.oauth2.common.ServerAccessToken;
+import org.apache.cxf.rs.security.oauth2.common.UserSubject;
+import org.apache.cxf.rs.security.oauth2.provider.OAuthServiceException;
+import org.apache.cxf.rs.security.oauth2.utils.OAuthConstants;
+import org.apache.cxf.rs.security.oauth2.utils.OAuthUtils;
+import org.apache.cxf.security.LoginSecurityContext;
+import org.apache.cxf.security.SecurityContext;
+
+
+/**
+ * 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)
+ */
+public abstract class RedirectionBasedGrantService extends AbstractOAuthService {
+ private String supportedResponseType;
+ private String supportedGrantType;
+ private boolean isClientConfidential;
+ protected RedirectionBasedGrantService(String supportedResponseType,
+ String supportedGrantType,
+ boolean isConfidential) {
+ this.supportedResponseType = supportedResponseType;
+ this.supportedGrantType = supportedGrantType;
+ this.isClientConfidential = isConfidential;
+ }
+
+ @GET
+ @Produces({"application/xhtml+xml", "text/html", "application/xml", "application/json" })
+ public Response authorize() {
+ MultivaluedMap<String, String> params = getQueryParameters();
+ return startAuthorization(params);
+ }
+
+ @GET
+ @Path("/decision")
+ public Response authorizeDecision() {
+ MultivaluedMap<String, String> params = getQueryParameters();
+ return completeAuthorization(params);
+ }
+
+ @POST
+ @Path("/decision")
+ @Consumes("application/x-www-form-urlencoded")
+ public Response authorizeDecisionForm(MultivaluedMap<String, String> params) {
+ return completeAuthorization(params);
+ }
+
+ protected Response startAuthorization(MultivaluedMap<String, String> params) {
+ SecurityContext sc = getAndValidateSecurityContext();
+
+ Client client = getClient(params);
+ String redirectUri = validateRedirectUri(client, params.getFirst(OAuthConstants.REDIRECT_URI));
+
+ if (!OAuthUtils.isGrantSupportedForClient(client, isClientConfidential, supportedGrantType)) {
+ return createErrorResponse(params, redirectUri, OAuthConstants.UNAUTHORIZED_CLIENT);
+ }
+ String responseType = params.getFirst(OAuthConstants.RESPONSE_TYPE);
+ if (responseType == null || !responseType.equals(supportedResponseType)) {
+ return createErrorResponse(params, redirectUri, OAuthConstants.UNSUPPORTED_RESPONSE_TYPE);
+ }
+ List<String> requestedScope = OAuthUtils.parseScope(params.getFirst(OAuthConstants.SCOPE));
+
+ UserSubject userSubject = createUserSubject(sc);
+ ServerAccessToken preauthorizedToken = getDataProvider().getPreauthorizedToken(
+ client, userSubject, supportedGrantType);
+ if (preauthorizedToken != null) {
+ return createGrant(params,
+ client,
+ redirectUri,
+ requestedScope,
+ Collections.<String>emptyList(),
+ userSubject,
+ preauthorizedToken);
+ }
+
+ List<OAuthPermission> permissions = null;
+ try {
+ permissions = getDataProvider().convertScopeToPermissions(client, requestedScope);
+ } catch (OAuthServiceException ex) {
+ return createErrorResponse(params, redirectUri, OAuthConstants.INVALID_SCOPE);
+ }
+
+ OAuthAuthorizationData data =
+ createAuthorizationData(client, params, permissions);
+ return Response.ok(data).build();
+
+ }
+
+
+ protected OAuthAuthorizationData createAuthorizationData(
+ Client client, MultivaluedMap<String, String> params, List<OAuthPermission> perms) {
+
+ OAuthAuthorizationData secData = new OAuthAuthorizationData();
+
+ addAuthenticityTokenToSession(secData);
+
+ secData.setPermissions(perms);
+
+ StringBuilder sb = new StringBuilder();
+ for (OAuthPermission perm : perms) {
+ if (sb.length() > 0) {
+ sb.append(" ");
+ }
+ sb.append(perm.getPermission());
+ }
+ secData.setProposedScope(sb.toString());
+
+ secData.setClientId(client.getClientId());
+ secData.setRedirectUri(params.getFirst(OAuthConstants.REDIRECT_URI));
+ secData.setState(params.getFirst(OAuthConstants.STATE));
+
+ secData.setApplicationName(client.getApplicationName());
+ secData.setApplicationWebUri(client.getApplicationWebUri());
+ secData.setApplicationDescription(client.getApplicationDescription());
+ secData.setApplicationLogoUri(client.getApplicationLogoUri());
+
+ String replyTo = getMessageContext().getUriInfo()
+ .getAbsolutePathBuilder().path("decision").build().toString();
+ secData.setReplyTo(replyTo);
+
+ return secData;
+ }
+
+ protected Response completeAuthorization(MultivaluedMap<String, String> params) {
+ SecurityContext securityContext = getAndValidateSecurityContext();
+
+ if (!compareRequestAndSessionTokens(params.getFirst(OAuthConstants.SESSION_AUTHENTICITY_TOKEN))) {
+ throw new WebApplicationException(400);
+ }
+ //TODO: additionally we can check that the Principal that got authenticated
+ // in startAuthorization is the same that got authenticated in completeAuthorization
+
+ Client client = getClient(params);
+ String redirectUri = validateRedirectUri(client, params.getFirst(OAuthConstants.REDIRECT_URI));
+
+ String decision = params.getFirst(OAuthConstants.AUTHORIZATION_DECISION_KEY);
+ boolean allow = OAuthConstants.AUTHORIZATION_DECISION_ALLOW.equals(decision);
+
+ if (!allow) {
+ return createErrorResponse(params, redirectUri, OAuthConstants.ACCESS_DENIED);
+ }
+
+ List<String> requestedScope = OAuthUtils.parseScope(params.getFirst(OAuthConstants.SCOPE));
+ List<String> approvedScope = new LinkedList<String>();
+ for (String rScope : requestedScope) {
+ String param = params.getFirst(rScope + "_status");
+ if (param != null && OAuthConstants.AUTHORIZATION_DECISION_ALLOW.equals(param)) {
+ approvedScope.add(rScope);
+ }
+ }
+ if (!requestedScope.containsAll(approvedScope)) {
+ return createErrorResponse(params, redirectUri, OAuthConstants.INVALID_SCOPE);
+ }
+
+ UserSubject userSubject = createUserSubject(securityContext);
+
+ return createGrant(params,
+ client,
+ redirectUri,
+ requestedScope,
+ approvedScope,
+ userSubject,
+ null);
+
+ }
+
+ private UserSubject createUserSubject(SecurityContext securityContext) {
+ List<String> roleNames = Collections.emptyList();
+ if (securityContext instanceof LoginSecurityContext) {
+ roleNames = new ArrayList<String>();
+ Set<Principal> roles = ((LoginSecurityContext)securityContext).getUserRoles();
+ for (Principal p : roles) {
+ roleNames.add(p.getName());
+ }
+ }
+ return
+ new UserSubject(securityContext.getUserPrincipal().getName(), roleNames);
+ }
+
+ protected abstract Response createErrorResponse(MultivaluedMap<String, String> params,
+ String redirectUri,
+ String error);
+
+ protected abstract Response createGrant(MultivaluedMap<String, String> params,
+ Client client,
+ String redirectUri,
+ List<String> requestedScope,
+ List<String> approvedScope,
+ UserSubject userSubject,
+ ServerAccessToken preAuthorizedToken);
+
+ private SecurityContext getAndValidateSecurityContext() {
+ SecurityContext securityContext =
+ (SecurityContext)getMessageContext().get(SecurityContext.class.getName());
+ if (securityContext == null || securityContext.getUserPrincipal() == null) {
+ throw new WebApplicationException(401);
+ }
+ checkTransportSecurity();
+ return securityContext;
+ }
+
+ protected String validateRedirectUri(Client client, String redirectUri) {
+
+ List<String> uris = client.getRedirectUris();
+ if (redirectUri != null) {
+ String webUri = client.getApplicationWebUri();
+ if (uris.size() > 0 && !uris.contains(redirectUri)
+ || webUri != null && !redirectUri.startsWith(webUri)) {
+ redirectUri = null;
+ }
+ } else if (uris.size() == 1) {
+ redirectUri = uris.get(0);
+ }
+ if (redirectUri == null) {
+ reportInvalidRequestError("Client Redirect Uri is invalid");
+ }
+ return redirectUri;
+ }
+
+ private void addAuthenticityTokenToSession(OAuthAuthorizationData secData) {
+ HttpSession session = getMessageContext().getHttpServletRequest().getSession();
+ String value = UUID.randomUUID().toString();
+ secData.setAuthenticityToken(value);
+ session.setAttribute(OAuthConstants.SESSION_AUTHENTICITY_TOKEN, value);
+ }
+
+ private boolean compareRequestAndSessionTokens(String requestToken) {
+ HttpSession session = getMessageContext().getHttpServletRequest().getSession();
+ String sessionToken = (String)session.getAttribute(OAuthConstants.SESSION_AUTHENTICITY_TOKEN);
+
+ if (StringUtils.isEmpty(sessionToken)) {
+ return false;
+ }
+
+ session.removeAttribute(OAuthConstants.SESSION_AUTHENTICITY_TOKEN);
+ return requestToken.equals(sessionToken);
+ }
+
+}
Propchange: cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/RedirectionBasedGrantService.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/RedirectionBasedGrantService.java
------------------------------------------------------------------------------
svn:keywords = Rev Date
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=1297971&r1=1297970&r2=1297971&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 Wed Mar 7 13:52:46 2012
@@ -21,9 +21,18 @@ package org.apache.cxf.rs.security.oauth
import org.apache.cxf.rs.security.oauth2.common.Client;
import org.apache.cxf.rs.security.oauth2.common.ServerAccessToken;
import org.apache.cxf.rs.security.oauth2.utils.OAuthConstants;
+import org.apache.cxf.rs.security.oauth2.utils.OAuthUtils;
public class BearerAccessToken extends ServerAccessToken {
public BearerAccessToken(Client client,
+ long lifetime) {
+ super(client,
+ OAuthConstants.BEARER_TOKEN_TYPE,
+ OAuthUtils.generateRandomTokenKey(),
+ lifetime,
+ System.currentTimeMillis() / 1000);
+ }
+ public BearerAccessToken(Client client,
String tokenKey,
long lifetime,
long issuedAt) {
Modified: cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/OAuthConstants.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/OAuthConstants.java?rev=1297971&r1=1297970&r2=1297971&view=diff
==============================================================================
--- cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/OAuthConstants.java (original)
+++ cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/OAuthConstants.java Wed Mar 7 13:52:46 2012
@@ -38,6 +38,7 @@ public final class OAuthConstants {
// Well-known grant types
public static final String AUTHORIZATION_CODE_GRANT = "authorization_code";
public static final String CLIENT_CREDENTIALS_GRANT = "client_credentials";
+ public static final String IMPLICIT_GRANT = "implicit";
// etc
// Well-known token types
Modified: cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/OAuthUtils.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/OAuthUtils.java?rev=1297971&r1=1297970&r2=1297971&view=diff
==============================================================================
--- cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/OAuthUtils.java (original)
+++ cxf/trunk/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/OAuthUtils.java Wed Mar 7 13:52:46 2012
@@ -18,11 +18,17 @@
*/
package org.apache.cxf.rs.security.oauth2.utils;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.UUID;
+
import javax.ws.rs.core.MultivaluedMap;
import org.apache.cxf.common.util.StringUtils;
import org.apache.cxf.jaxrs.impl.MetadataMap;
import org.apache.cxf.jaxrs.model.URITemplate;
+import org.apache.cxf.rs.security.oauth2.common.Client;
+import org.apache.cxf.rs.security.oauth2.provider.OAuthServiceException;
/**
* Various utility methods
@@ -32,6 +38,36 @@ public final class OAuthUtils {
private OAuthUtils() {
}
+ public static boolean isGrantSupportedForClient(Client client,
+ boolean isConfidential,
+ String grantType) {
+ List<String> allowedGrants = client.getAllowedGrantTypes();
+ return isConfidential == client.isConfidential()
+ && (allowedGrants.isEmpty() || allowedGrants.contains(grantType));
+ }
+
+ public static List<String> parseScope(String requestedScope) {
+ List<String> list = new LinkedList<String>();
+ if (requestedScope != null) {
+ String[] scopeValues = requestedScope.split(" ");
+ for (String scope : scopeValues) {
+ if (!StringUtils.isEmpty(scope)) {
+ list.add(scope);
+ }
+ }
+ }
+ return list;
+ }
+
+ public static String generateRandomTokenKey() throws OAuthServiceException {
+ try {
+ byte[] bytes = UUID.randomUUID().toString().getBytes("UTF-8");
+ return new MD5SequenceGenerator().generate(bytes);
+ } catch (Exception ex) {
+ throw new OAuthServiceException(OAuthConstants.SERVER_ERROR, ex);
+ }
+ }
+
public static boolean isExpired(Long issuedAt, Long lifetime) {
return lifetime != -1
&& issuedAt + lifetime < System.currentTimeMillis() / 1000;