Modified: shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth/OAuthClientState.java URL: http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth/OAuthClientState.java?rev=1187358&r1=1187357&r2=1187358&view=diff ============================================================================== --- shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth/OAuthClientState.java (original) +++ shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth/OAuthClientState.java Fri Oct 21 14:19:33 2011 @@ -16,30 +16,29 @@ */ package org.apache.shindig.gadgets.oauth; +import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.Maps; +import org.apache.shindig.auth.AbstractSecurityToken; import org.apache.shindig.common.crypto.BlobCrypter; import org.apache.shindig.common.crypto.BlobCrypterException; +import org.apache.shindig.common.util.TimeSource; +import java.util.EnumSet; import java.util.Map; /** * Class to handle OAuth fetcher state stored client side. The state is * stored as a signed, encrypted, time stamped blob. */ -public class OAuthClientState { - /** - * Maximum age for our client state; if this is exceeded we start over. One - * hour is a fairly arbitrary time limit here. - */ - private static final int CLIENT_STATE_MAX_AGE_SECS = 3600; +public class OAuthClientState extends AbstractSecurityToken { + private static final EnumSet<Keys> MAP_KEYS = EnumSet.of(Keys.EXPIRES, Keys.OWNER); // Our client state is encrypted key/value pairs. These are the key names. private static final String REQ_TOKEN_KEY = "r"; private static final String REQ_TOKEN_SECRET_KEY = "rs"; private static final String ACCESS_TOKEN_KEY = "a"; private static final String ACCESS_TOKEN_SECRET_KEY = "as"; - private static final String OWNER_KEY = "o"; private static final String SESSION_HANDLE_KEY = "sh"; private static final String ACCESS_TOKEN_EXPIRATION_KEY = "e"; @@ -51,7 +50,7 @@ public class OAuthClientState { /** * Create a new, empty client state blob. - * + * * @param crypter */ public OAuthClientState(BlobCrypter crypter) { @@ -71,23 +70,32 @@ public class OAuthClientState { Map<String, String> state = null; if (stateBlob != null) { try { - state = crypter.unwrap(stateBlob, CLIENT_STATE_MAX_AGE_SECS); + state = crypter.unwrap(stateBlob); + if (state == null) { + state = Maps.newHashMap(); + } + loadFromMap(state); + state.remove(Keys.EXPIRES.getKey()); + state.remove(Keys.OWNER.getKey()); + enforceNotExpired(); } catch (BlobCrypterException e) { // Probably too old, pretend we never saw it at all. + state = null; } } if (state == null) { state = Maps.newHashMap(); + setOwner(null); + setExpiresAt(null); } - this.state = state; + this.state = state; } /** * @return true if there is no state to store with the client. */ public boolean isEmpty() { - // Might contain just a timestamp - return (state.isEmpty() || (state.size() == 1 && state.containsKey("t"))); + return (state.isEmpty() && getOwnerId() == null); } /** @@ -95,7 +103,10 @@ public class OAuthClientState { * @throws BlobCrypterException */ public String getEncryptedState() throws BlobCrypterException { - return crypter.wrap(state); + setExpires(); + Map<String, String> map = this.toMap(); + map.putAll(state); + return crypter.wrap(map); } /** @@ -173,11 +184,11 @@ public class OAuthClientState { * Owner of the OAuth token. */ public String getOwner() { - return state.get(OWNER_KEY); + return getOwnerId(); } public void setOwner(String owner) { - setNullCheck(OWNER_KEY, owner); + setOwnerId(owner); } private void setNullCheck(String key, String value) { @@ -187,4 +198,26 @@ public class OAuthClientState { state.put(key, value); } } + + public String getUpdatedToken() { + throw new UnsupportedOperationException(); + } + + public String getAuthenticationMode() { + throw new UnsupportedOperationException(); + } + + public boolean isAnonymous() { + throw new UnsupportedOperationException(); + } + + @Override + protected EnumSet<Keys> getMapKeys() { + return MAP_KEYS; + } + + @VisibleForTesting + protected AbstractSecurityToken setTimeSource(TimeSource timeSource) { + return super.setTimeSource(timeSource); + } }
Modified: shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/GadgetsHandlerService.java URL: http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/GadgetsHandlerService.java?rev=1187358&r1=1187357&r2=1187358&view=diff ============================================================================== --- shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/GadgetsHandlerService.java (original) +++ shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/GadgetsHandlerService.java Fri Oct 21 14:19:33 2011 @@ -264,7 +264,7 @@ public class GadgetsHandlerService { SecurityToken tokenData = convertAuthContext(request.getAuthContext(), request.getContainer(), request.getUrl().toString()); String token = securityTokenCodec.encodeToken(tokenData); - Long expiryTimeMs = securityTokenCodec.getTokenExpiration(tokenData); + Long expiryTimeMs = tokenData == null ? null : tokenData.getExpiresAt(); return createTokenResponse(request.getUrl(), token, fields, expiryTimeMs); } Modified: shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/oauth/OAuthClientStateTest.java URL: http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/oauth/OAuthClientStateTest.java?rev=1187358&r1=1187357&r2=1187358&view=diff ============================================================================== --- shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/oauth/OAuthClientStateTest.java (original) +++ shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/oauth/OAuthClientStateTest.java Fri Oct 21 14:19:33 2011 @@ -30,23 +30,23 @@ public class OAuthClientStateTest { private FakeTimeSource timeSource; private BasicBlobCrypter crypter; - + @Before public void setUp() throws Exception { crypter = new BasicBlobCrypter("abcdefghijklmnop".getBytes()); timeSource = new FakeTimeSource(); crypter.timeSource = timeSource; } - + private void assertEmpty(OAuthClientState state) { assertTrue(state.isEmpty()); assertNull(state.getRequestToken()); assertNull(state.getRequestTokenSecret()); assertNull(state.getAccessToken()); assertNull(state.getAccessTokenSecret()); - assertNull(state.getOwner()); + assertNull(state.getOwner()); } - + @Test public void testEncryptEmpty() throws Exception { OAuthClientState state = new OAuthClientState(crypter); @@ -55,7 +55,7 @@ public class OAuthClientStateTest { state = new OAuthClientState(crypter, encrypted); assertEmpty(state); } - + @Test public void testValuesSet() throws Exception { OAuthClientState state = new OAuthClientState(crypter); @@ -72,24 +72,24 @@ public class OAuthClientStateTest { assertEquals("reqtoken", state.getRequestToken()); assertEquals("reqtokensecret", state.getRequestTokenSecret()); } - + @Test public void testNullConstructorArg() throws Exception { OAuthClientState state = new OAuthClientState(crypter, null); assertEmpty(state); } - + @Test public void testExpired() throws Exception { OAuthClientState state = new OAuthClientState(crypter); + timeSource.incrementSeconds(-1 * (3600 + 180 + 1)); // expiry time + skew. + state.setTimeSource(timeSource); state.setRequestToken("reqtoken"); String encrypted = state.getEncryptedState(); - // expiry time + skew. - timeSource.incrementSeconds(3600 + 180 + 1); state = new OAuthClientState(crypter, encrypted); - assertNull(state.getRequestToken()); + assertNull(state.getRequestToken()); } - + @Test public void testNullValue() throws Exception { OAuthClientState state = new OAuthClientState(crypter); @@ -98,7 +98,7 @@ public class OAuthClientStateTest { state.setOwner("owner"); String encrypted = state.getEncryptedState(); state = new OAuthClientState(crypter, encrypted); - assertNull(state.getRequestToken()); + assertNull(state.getRequestToken()); assertEquals("owner", state.getOwner()); } } Modified: shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/oauth2/MockUtils.java URL: http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/oauth2/MockUtils.java?rev=1187358&r1=1187357&r2=1187358&view=diff ============================================================================== --- shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/oauth2/MockUtils.java (original) +++ shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/oauth2/MockUtils.java Fri Oct 21 14:19:33 2011 @@ -21,7 +21,9 @@ package org.apache.shindig.gadgets.oauth import com.google.common.collect.Maps; import com.google.inject.Provider; +import org.apache.shindig.auth.AbstractSecurityToken; import org.apache.shindig.auth.SecurityToken; +import org.apache.shindig.common.crypto.BlobExpiredException; import org.apache.shindig.common.servlet.Authority; import org.apache.shindig.common.uri.Uri; import org.apache.shindig.gadgets.AuthType; @@ -54,6 +56,7 @@ import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.Collections; +import java.util.EnumSet; import java.util.List; import java.util.Map; @@ -146,23 +149,12 @@ public class MockUtils { } } - static class DummySecurityToken implements SecurityToken { - private final String ownerId; - private final String viewerId; - private final String appUrl; + static class DummySecurityToken extends AbstractSecurityToken { - public DummySecurityToken(final String ownerId, final String viewerId, final String appUrl) { - this.ownerId = ownerId; - this.viewerId = viewerId; - this.appUrl = appUrl; - } - - public String getOwnerId() { - return this.ownerId; - } - - public String getViewerId() { - return this.viewerId; + public DummySecurityToken(String ownerId, String viewerId, String appUrl) { + setOwnerId(ownerId); + setViewerId(viewerId); + setAppUrl(appUrl); } public String getAppId() { @@ -177,10 +169,6 @@ public class MockUtils { return ""; } - public String getAppUrl() { - return this.appUrl; - } - public long getModuleId() { return 0; } @@ -189,10 +177,14 @@ public class MockUtils { return 0L; } - public boolean isExpired() { + public boolean isExpired(int maxAge) { return false; } + public AbstractSecurityToken enforceNotExpired(int maxAge) throws BlobExpiredException { + return this; + } + public String getUpdatedToken() { return ""; } @@ -210,7 +202,11 @@ public class MockUtils { } public String getActiveUrl() { - return this.appUrl; + return getAppUrl(); + } + + protected EnumSet<Keys> getMapKeys() { + return EnumSet.noneOf(Keys.class); } } @@ -504,7 +500,7 @@ public class MockUtils { refreshToken.setUser(MockUtils.USER); return refreshToken; } - + protected static String loadFile(String path) throws IOException { InputStream is = MockUtils.class.getClassLoader().getResourceAsStream(path); return IOUtils.toString(is,"UTF-8"); Modified: shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/GadgetsHandlerServiceTest.java URL: http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/GadgetsHandlerServiceTest.java?rev=1187358&r1=1187357&r2=1187358&view=diff ============================================================================== --- shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/GadgetsHandlerServiceTest.java (original) +++ shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/GadgetsHandlerServiceTest.java Fri Oct 21 14:19:33 2011 @@ -330,7 +330,6 @@ public class GadgetsHandlerServiceTest e createAuthContext(OWNER, VIEWER), ImmutableList.of("*")); replay(); tokenCodec.encodedToken = TOKEN; - tokenCodec.tokenExpiryTimeMs = TOKEN_EXPIRY_TIME_MS; GadgetsHandlerApi.TokenResponse response = gadgetHandler.getToken(request); assertEquals(TOKEN, response.getToken()); assertEquals(CURRENT_TIME_MS, response.getResponseTimeMs()); @@ -679,6 +678,7 @@ public class GadgetsHandlerServiceTest e if (viewerId != null) { EasyMock.expect(authContext.getViewerId()).andReturn(viewerId).once(); } + EasyMock.expect(authContext.getExpiresAt()).andReturn(TOKEN_EXPIRY_TIME_MS).anyTimes(); return authContext; } @@ -728,7 +728,6 @@ public class GadgetsHandlerServiceTest e public SecurityToken authContext = null; public SecurityTokenException exc = null; public String encodedToken = null; - public Long tokenExpiryTimeMs = null; public String encodeToken(SecurityToken authContext) throws SecurityTokenException { this.authContext = authContext; @@ -745,13 +744,5 @@ public class GadgetsHandlerServiceTest e } return authContext; } - - public Long getTokenExpiration(SecurityToken authContext) throws SecurityTokenException { - this.authContext = authContext; - if (exc != null) { - throw exc; - } - return tokenExpiryTimeMs; - } } } Modified: shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/GadgetsHandlerTest.java URL: http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/GadgetsHandlerTest.java?rev=1187358&r1=1187357&r2=1187358&view=diff ============================================================================== --- shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/GadgetsHandlerTest.java (original) +++ shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/GadgetsHandlerTest.java Fri Oct 21 14:19:33 2011 @@ -466,8 +466,6 @@ public class GadgetsHandlerTest extends Capture<SecurityToken> authContextCapture = new Capture<SecurityToken>(); EasyMock.expect(codec.encodeToken(EasyMock.capture(authContextCapture))).andReturn(TOKEN) .anyTimes(); - EasyMock.expect(codec.getTokenExpiration(EasyMock.capture(authContextCapture))) - .andReturn(EXPIRY_TIME_MS).anyTimes(); replay(codec); registerGadgetsHandler(codec); @@ -548,8 +546,6 @@ public class GadgetsHandlerTest extends EasyMock.expect(codec.encodeToken(EasyMock.isA(SecurityToken.class))).andReturn(TOKEN); EasyMock.expect(codec.encodeToken(EasyMock.isA(SecurityToken.class))).andThrow( new SecurityTokenException("blah")); - EasyMock.expect(codec.getTokenExpiration(EasyMock.isA(SecurityToken.class))) - .andReturn(EXPIRY_TIME_MS).anyTimes(); replay(codec); registerGadgetsHandler(codec); Modified: shindig/trunk/java/social-api/src/main/java/org/apache/shindig/social/core/oauth/OAuthSecurityToken.java URL: http://svn.apache.org/viewvc/shindig/trunk/java/social-api/src/main/java/org/apache/shindig/social/core/oauth/OAuthSecurityToken.java?rev=1187358&r1=1187357&r2=1187358&view=diff ============================================================================== --- shindig/trunk/java/social-api/src/main/java/org/apache/shindig/social/core/oauth/OAuthSecurityToken.java (original) +++ shindig/trunk/java/social-api/src/main/java/org/apache/shindig/social/core/oauth/OAuthSecurityToken.java Fri Oct 21 14:19:33 2011 @@ -17,21 +17,20 @@ */ package org.apache.shindig.social.core.oauth; +import java.util.EnumSet; + import org.apache.shindig.auth.AbstractSecurityToken; import org.apache.shindig.auth.AuthenticationMode; -import org.apache.shindig.auth.SecurityToken; /** * A SecurityToken that represents two/three legged OAuth requests */ -public class OAuthSecurityToken extends AbstractSecurityToken implements SecurityToken { - private final String userId; - private final String appUrl; - private final String appId; - private final String domain; - private final String container; +public class OAuthSecurityToken extends AbstractSecurityToken { + private static final EnumSet<Keys> MAPKEYS = EnumSet.of( + Keys.VIEWER, Keys.OWNER, Keys.APP_URL, Keys.APP_ID, Keys.DOMAIN, Keys.CONTAINER, Keys.EXPIRES + ); + private final String authMode; - private final Long expiresAt; public OAuthSecurityToken(String userId, String appUrl, String appId, String domain, String container, Long expiresAt) { @@ -40,45 +39,20 @@ public class OAuthSecurityToken extends public OAuthSecurityToken(String userId, String appUrl, String appId, String domain, String container, Long expiresAt, String authMode) { - this.userId = userId; - this.appUrl = appUrl; - this.appId = appId; - this.domain = domain; - this.container = container; - this.authMode = authMode; - this.expiresAt = expiresAt; - } - - public String getOwnerId() { - return userId; - } - - public String getViewerId() { - return userId; - } - - public String getAppId() { - return appId; - } - public String getDomain() { - return domain; - } - - public String getContainer() { - return container; - } - - public String getAppUrl() { - return appUrl; - } - - public Long getExpiresAt() { - return expiresAt; + setViewerId(userId); + setOwnerId(userId); + setAppUrl(appUrl); + setAppId(appId); + setDomain(domain); + setContainer(container); + setExpiresAt(expiresAt); + this.authMode = authMode; } // We don't support this concept yet. We probably don't need to as opensocial calls don't // currently depend on the app instance id. + @Override public long getModuleId() { throw new UnsupportedOperationException(); } @@ -91,6 +65,7 @@ public class OAuthSecurityToken extends return authMode; } + @Override public String getTrustedJson() { throw new UnsupportedOperationException(); } @@ -98,4 +73,9 @@ public class OAuthSecurityToken extends public boolean isAnonymous() { return false; } + + @Override + protected EnumSet<Keys> getMapKeys() { + return MAPKEYS; + } }
