Author: lindner Date: Mon Nov 9 21:10:57 2009 New Revision: 834234 URL: http://svn.apache.org/viewvc?rev=834234&view=rev Log: SHINIDG-1216 | OAuth Proxy should allow for viewer access on secured owner pages.
Modified: incubator/shindig/trunk/java/common/conf/shindig.properties incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth/GadgetOAuthTokenStore.java incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth/OAuthFetcherConfig.java incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth/OAuthRequest.java incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/oauth/GadgetOAuthCallbackGeneratorTest.java incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/oauth/GadgetTokenStoreTest.java incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/oauth/OAuthFetcherConfigTest.java incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/oauth/OAuthRequestTest.java Modified: incubator/shindig/trunk/java/common/conf/shindig.properties URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/common/conf/shindig.properties?rev=834234&r1=834233&r2=834234&view=diff ============================================================================== --- incubator/shindig/trunk/java/common/conf/shindig.properties (original) +++ incubator/shindig/trunk/java/common/conf/shindig.properties Mon Nov 9 21:10:57 2009 @@ -39,6 +39,11 @@ shindig.signing.global-callback-url=http://localhost:8080/gadgets/oauthcallback shindig.signing.enable-signed-callbacks=true +# Set to true if you want to allow the use of 3-legged OAuth tokens when viewer != owner. +# This setting is not recommeneded for pages that allow user-controlled javascript, since +# that javascript could be used to make unauthorized requests on behalf of the viewer of the page +shindig.signing.viewer-access-tokens-enabled=false + # If enabled here, configuration values can be found in container configuration files. shindig.locked-domain.enabled=false Modified: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth/GadgetOAuthTokenStore.java URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth/GadgetOAuthTokenStore.java?rev=834234&r1=834233&r2=834234&view=diff ============================================================================== --- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth/GadgetOAuthTokenStore.java (original) +++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth/GadgetOAuthTokenStore.java Mon Nov 9 21:10:57 2009 @@ -72,12 +72,14 @@ * - the OAuth request/authorization/access URLs. * - what HTTP method to use for request token and access token requests * - where the OAuth parameters are located. + * - Information from the OAuth Fetcher config to determine if owner pages are secure * * Note that most of that work gets skipped for signed fetch, we just look up the consumer key * and secret for that. Signed fetch always sticks the parameters in the query string. */ public AccessorInfo getOAuthAccessor(SecurityToken securityToken, - OAuthArguments arguments, OAuthClientState clientState, OAuthResponseParams responseParams) + OAuthArguments arguments, OAuthClientState clientState, OAuthResponseParams responseParams, + OAuthFetcherConfig fetcherConfig) throws OAuthRequestException { AccessorInfoBuilder accessorBuilder = new AccessorInfoBuilder(); @@ -108,11 +110,12 @@ } // Should we use the OAuth access token? We never do this unless the client allows it, and - // if owner == viewer. - if (arguments.mayUseToken() - && securityToken.getOwnerId() != null - && securityToken.getOwnerId().equals(securityToken.getViewerId())) { - lookupToken(securityToken, consumer, arguments, clientState, accessorBuilder, responseParams); + // if owner == viewer or owner pages are secure. + if (arguments.mayUseToken() && securityToken.getViewerId() != null) { + if ((fetcherConfig != null && fetcherConfig.isViewerAccessTokensEnabled()) || + securityToken.getViewerId().equals(securityToken.getOwnerId())) { + lookupToken(securityToken, consumer, arguments, clientState, accessorBuilder, responseParams); + } } return accessorBuilder.create(responseParams); Modified: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth/OAuthFetcherConfig.java URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth/OAuthFetcherConfig.java?rev=834234&r1=834233&r2=834234&view=diff ============================================================================== --- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth/OAuthFetcherConfig.java (original) +++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth/OAuthFetcherConfig.java Mon Nov 9 21:10:57 2009 @@ -34,41 +34,54 @@ private final GadgetOAuthTokenStore tokenStore; private final TimeSource clock; private final OAuthCallbackGenerator oauthCallbackGenerator; + private final boolean viewerAccessTokensEnabled; @Inject public OAuthFetcherConfig( @Named(OAUTH_STATE_CRYPTER) BlobCrypter stateCrypter, GadgetOAuthTokenStore tokenStore, TimeSource clock, - OAuthCallbackGenerator oauthCallbackGenerator) { + OAuthCallbackGenerator oauthCallbackGenerator, + @Named("shindig.signing.viewer-access-tokens-enabled") boolean viewerAccessTokensEnabled) { this.stateCrypter = stateCrypter; this.tokenStore = tokenStore; this.clock = clock; this.oauthCallbackGenerator = oauthCallbackGenerator; + this.viewerAccessTokensEnabled = viewerAccessTokensEnabled; } /** - * Used to encrypt state stored on the client. + * @return A BlobCrypter Used to encrypt state stored on the client. */ public BlobCrypter getStateCrypter() { return stateCrypter; } /** - * Persistent token storage. + * @return the persistent token storage. */ public GadgetOAuthTokenStore getTokenStore() { return tokenStore; } /** - * Clock + * @return the Clock */ public TimeSource getClock() { return clock; } - + + /** + * @return callback Url generator + */ public OAuthCallbackGenerator getOAuthCallbackGenerator() { return oauthCallbackGenerator; } + + /** + * @return true if the owner pages do not allow user controlled javascript + */ + public boolean isViewerAccessTokensEnabled() { + return viewerAccessTokensEnabled; + } } Modified: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth/OAuthRequest.java URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth/OAuthRequest.java?rev=834234&r1=834233&r2=834234&view=diff ============================================================================== --- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth/OAuthRequest.java (original) +++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth/OAuthRequest.java Mon Nov 9 21:10:57 2009 @@ -67,7 +67,8 @@ * this works (The spec is at http://oauth.net/core/1.0/). * * The combination protocol works by sending identity information in all requests, and allows the - * OAuth dance to happen as well when owner == viewer. This lets OAuth service providers build up + * OAuth dance to happen as well when owner == viewer (by default) or for any viewer when the + * OAuthFetcherConfig#isViewerAccessTokensEnabled parameter is true. This lets OAuth service providers build up * an identity mapping from ids on social network sites to their own local ids. */ public class OAuthRequest { @@ -193,7 +194,7 @@ try { accessorInfo = fetcherConfig.getTokenStore().getOAuthAccessor( realRequest.getSecurityToken(), realRequest.getOAuthArguments(), clientState, - responseParams); + responseParams, fetcherConfig); response = fetchWithRetry(); } catch (OAuthRequestException e) { // No data for us. @@ -316,17 +317,17 @@ String pageOwner = realRequest.getSecurityToken().getOwnerId(); String pageViewer = realRequest.getSecurityToken().getViewerId(); String stateOwner = clientState.getOwner(); - if (pageOwner == null) { + if (pageOwner == null || pageViewer == null) { throw responseParams.oauthRequestException(OAuthError.UNAUTHENTICATED, "Unauthenticated"); } - if (!pageOwner.equals(pageViewer)) { + if (!fetcherConfig.isViewerAccessTokensEnabled() && !pageOwner.equals(pageViewer)) { throw responseParams.oauthRequestException(OAuthError.NOT_OWNER, - "Only page owners can grant OAuth approval"); + "Non-Secure Owner Page -- Only page owners can grant OAuth approval"); } - if (stateOwner != null && !stateOwner.equals(pageOwner)) { + if (stateOwner != null && !stateOwner.equals(pageViewer)) { throw responseParams.oauthRequestException(OAuthError.UNKNOWN_PROBLEM, "Client state belongs to a different person " + - "(state owner=" + stateOwner + ", pageOwner=" + pageOwner + ')'); + "(state owner=" + stateOwner + ", pageViewer=" + pageViewer + ')'); } } Modified: incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/oauth/GadgetOAuthCallbackGeneratorTest.java URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/oauth/GadgetOAuthCallbackGeneratorTest.java?rev=834234&r1=834233&r2=834234&view=diff ============================================================================== --- incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/oauth/GadgetOAuthCallbackGeneratorTest.java (original) +++ incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/oauth/GadgetOAuthCallbackGeneratorTest.java Mon Nov 9 21:10:57 2009 @@ -67,7 +67,7 @@ securityToken = new BasicSecurityToken("viewer", "viewer", "app", "container.com", "gadget", "0", "default", MAKE_REQUEST_URL); gadget = control.createMock(Gadget.class); - fetcherConfig = new OAuthFetcherConfig(null, null, null, null); + fetcherConfig = new OAuthFetcherConfig(null, null, null, null, false); responseParams = new OAuthResponseParams(null, null, null); } Modified: incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/oauth/GadgetTokenStoreTest.java URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/oauth/GadgetTokenStoreTest.java?rev=834234&r1=834233&r2=834234&view=diff ============================================================================== --- incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/oauth/GadgetTokenStoreTest.java (original) +++ incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/oauth/GadgetTokenStoreTest.java Mon Nov 9 21:10:57 2009 @@ -25,6 +25,7 @@ import org.apache.shindig.common.crypto.BasicBlobCrypter; import org.apache.shindig.common.crypto.BlobCrypter; import org.apache.shindig.common.testing.FakeGadgetToken; +import org.apache.shindig.common.util.FakeTimeSource; import org.apache.shindig.gadgets.FakeGadgetSpecFactory; import org.apache.shindig.gadgets.oauth.AccessorInfo.HttpMethod; import org.apache.shindig.gadgets.oauth.AccessorInfo.OAuthParamLocation; @@ -81,6 +82,8 @@ private BlobCrypter stateCrypter; private OAuthClientState clientState; private OAuthResponseParams responseParams; + private OAuthFetcherConfig fetcherConfig; + private OAuthFetcherConfig fetcherConfigSecureOwner; @Before public void setUp() throws Exception { @@ -103,13 +106,15 @@ stateCrypter = new BasicBlobCrypter("abcdefghijklmnop".getBytes()); clientState = new OAuthClientState(stateCrypter); responseParams = new OAuthResponseParams(socialToken, null, stateCrypter); + fetcherConfig = new OAuthFetcherConfig(stateCrypter, store, new FakeTimeSource(), null, false); + fetcherConfigSecureOwner = new OAuthFetcherConfig(stateCrypter, store, new FakeTimeSource(), null, true); } @Test public void testGetOAuthAccessor_signedFetch() throws Exception { OAuthArguments arguments = new OAuthArguments(); arguments.setUseToken(UseToken.NEVER); - AccessorInfo info = store.getOAuthAccessor(socialToken, arguments, clientState, responseParams); + AccessorInfo info = store.getOAuthAccessor(socialToken, arguments, clientState, responseParams, fetcherConfig); assertEquals(OAuthParamLocation.URI_QUERY, info.getParamLocation()); assertEquals("keyname", info.getConsumer().getKeyName()); assertEquals("key", info.getConsumer().getConsumer().consumerKey); @@ -124,7 +129,7 @@ OAuthArguments arguments = new OAuthArguments(); arguments.setUseToken(UseToken.IF_AVAILABLE); try { - store.getOAuthAccessor(socialToken, arguments, clientState, responseParams); + store.getOAuthAccessor(socialToken, arguments, clientState, responseParams, fetcherConfig); fail(); } catch (OAuthRequestException e) { assertEquals("BAD_OAUTH_CONFIGURATION", responseParams.getError()); @@ -142,7 +147,7 @@ OAuthArguments arguments = new OAuthArguments(); arguments.setUseToken(UseToken.NEVER); arguments.setServiceName("hmac"); - AccessorInfo info = store.getOAuthAccessor(socialToken, arguments, clientState, responseParams); + AccessorInfo info = store.getOAuthAccessor(socialToken, arguments, clientState, responseParams, fetcherConfig); assertEquals(OAuthParamLocation.URI_QUERY, info.getParamLocation()); Assert.assertNull(info.getConsumer().getKeyName()); assertEquals("hmac", info.getConsumer().getConsumer().consumerKey); @@ -163,7 +168,7 @@ OAuthArguments arguments = new OAuthArguments(); arguments.setUseToken(UseToken.NEVER); arguments.setServiceName("hmac"); - AccessorInfo info = store.getOAuthAccessor(socialToken, arguments, clientState, responseParams); + AccessorInfo info = store.getOAuthAccessor(socialToken, arguments, clientState, responseParams, fetcherConfig); assertEquals("keyname", info.getConsumer().getKeyName()); assertEquals("key", info.getConsumer().getConsumer().consumerKey); } @@ -178,7 +183,7 @@ backingStore.setConsumerKeyAndSecret(index, cks); OAuthArguments arguments = new OAuthArguments(); arguments.setUseToken(UseToken.NEVER); - AccessorInfo info = store.getOAuthAccessor(socialToken, arguments, clientState, responseParams); + AccessorInfo info = store.getOAuthAccessor(socialToken, arguments, clientState, responseParams, fetcherConfig); assertEquals(OAuthParamLocation.URI_QUERY, info.getParamLocation()); Assert.assertNull(info.getConsumer().getKeyName()); assertEquals("hmac", info.getConsumer().getConsumer().consumerKey); @@ -199,7 +204,7 @@ OAuthArguments arguments = new OAuthArguments(); arguments.setServiceName("testservice"); arguments.setUseToken(UseToken.IF_AVAILABLE); - AccessorInfo info = store.getOAuthAccessor(socialToken, arguments, clientState, responseParams); + AccessorInfo info = store.getOAuthAccessor(socialToken, arguments, clientState, responseParams, fetcherConfig); assertEquals(OAuthParamLocation.URI_QUERY, info.getParamLocation()); Assert.assertNull(info.getConsumer().getKeyName()); assertEquals("hmac", info.getConsumer().getConsumer().consumerKey); @@ -221,7 +226,7 @@ arguments.setServiceName("testservice"); arguments.setUseToken(UseToken.IF_AVAILABLE); AccessorInfo info = store.getOAuthAccessor(privateToken, arguments, clientState, - responseParams); + responseParams, fetcherConfig); assertEquals(OAuthParamLocation.URI_QUERY, info.getParamLocation()); Assert.assertNull(info.getConsumer().getKeyName()); assertEquals("hmac", info.getConsumer().getConsumer().consumerKey); @@ -248,7 +253,7 @@ arguments.setServiceName("testservice"); arguments.setUseToken(UseToken.IF_AVAILABLE); AccessorInfo info = store.getOAuthAccessor(privateToken, arguments, clientState, - responseParams); + responseParams, fetcherConfig); assertEquals(OAuthParamLocation.URI_QUERY, info.getParamLocation()); Assert.assertNull(info.getConsumer().getKeyName()); assertEquals("hmac", info.getConsumer().getConsumer().consumerKey); @@ -258,7 +263,7 @@ assertEquals("secret", info.getAccessor().tokenSecret); // Friend views page - info = store.getOAuthAccessor(socialToken, arguments, clientState, responseParams); + info = store.getOAuthAccessor(socialToken, arguments, clientState, responseParams, fetcherConfig); assertEquals(OAuthParamLocation.URI_QUERY, info.getParamLocation()); Assert.assertNull(info.getConsumer().getKeyName()); assertEquals("hmac", info.getConsumer().getConsumer().consumerKey); @@ -279,7 +284,7 @@ OAuthArguments arguments = new OAuthArguments(); arguments.setServiceName("testservice"); arguments.setUseToken(UseToken.ALWAYS); - AccessorInfo info = store.getOAuthAccessor(socialToken, arguments, clientState, responseParams); + AccessorInfo info = store.getOAuthAccessor(socialToken, arguments, clientState, responseParams, fetcherConfig); assertEquals(OAuthParamLocation.URI_QUERY, info.getParamLocation()); Assert.assertNull(info.getConsumer().getKeyName()); assertEquals("hmac", info.getConsumer().getConsumer().consumerKey); @@ -295,7 +300,7 @@ arguments.setServiceName("no such service"); arguments.setUseToken(UseToken.ALWAYS); try { - store.getOAuthAccessor(socialToken, arguments, clientState, responseParams); + store.getOAuthAccessor(socialToken, arguments, clientState, responseParams, fetcherConfig); fail(); } catch (OAuthRequestException e) { assertEquals("BAD_OAUTH_CONFIGURATION", responseParams.getError()); @@ -309,7 +314,7 @@ arguments.setUseToken(UseToken.ALWAYS); privateToken.setAppUrl("http://www.example.com/body.xml"); AccessorInfo info = store.getOAuthAccessor(privateToken, arguments, clientState, - responseParams); + responseParams, fetcherConfig); assertEquals( FakeOAuthServiceProvider.REQUEST_TOKEN_URL, info.getConsumer().getConsumer().serviceProvider.requestTokenURL); @@ -330,7 +335,7 @@ arguments.setUseToken(UseToken.ALWAYS); privateToken.setAppUrl("http://www.example.com/header.xml"); AccessorInfo info = store.getOAuthAccessor(privateToken, arguments, clientState, - responseParams); + responseParams, fetcherConfig); assertEquals( FakeOAuthServiceProvider.REQUEST_TOKEN_URL, info.getConsumer().getConsumer().serviceProvider.requestTokenURL); @@ -353,7 +358,7 @@ new TokenInfo("access", "secret", "sessionhandle", 12345L), responseParams); AccessorInfo info = store.getOAuthAccessor(privateToken, arguments, clientState, - responseParams); + responseParams, fetcherConfig); assertNull(info.getAccessor().requestToken); assertEquals("access", info.getAccessor().accessToken); assertEquals("secret", info.getAccessor().tokenSecret); @@ -375,7 +380,7 @@ clientState.setTokenExpireMillis(56789L); AccessorInfo info = store.getOAuthAccessor(privateToken, arguments, clientState, - responseParams); + responseParams, fetcherConfig); assertNull(info.getAccessor().requestToken); assertEquals("clienttoken", info.getAccessor().accessToken); assertEquals("clienttokensecret", info.getAccessor().tokenSecret); @@ -395,7 +400,7 @@ clientState.setRequestTokenSecret("requestsecret"); AccessorInfo info = store.getOAuthAccessor(privateToken, arguments, clientState, - responseParams); + responseParams, fetcherConfig); assertEquals("request", info.getAccessor().requestToken); assertEquals("requestsecret", info.getAccessor().tokenSecret); assertNull(info.getAccessor().accessToken); @@ -412,7 +417,7 @@ new TokenInfo("access", "secret", null, 0), responseParams); AccessorInfo info = store.getOAuthAccessor(privateToken, arguments, clientState, - responseParams); + responseParams, fetcherConfig); assertNull(info.getAccessor().requestToken); assertEquals("access", info.getAccessor().accessToken); assertEquals("secret", info.getAccessor().tokenSecret); @@ -427,7 +432,7 @@ arguments.setRequestTokenSecret("preapprovedsecret"); AccessorInfo info = store.getOAuthAccessor(privateToken, arguments, clientState, - responseParams); + responseParams, fetcherConfig); assertNull(info.getAccessor().accessToken); assertEquals("preapproved", info.getAccessor().requestToken); assertEquals("preapprovedsecret", info.getAccessor().tokenSecret); @@ -442,14 +447,14 @@ new TokenInfo("access", "secret", null, 0), responseParams); AccessorInfo info = store.getOAuthAccessor(privateToken, arguments, clientState, - responseParams); + responseParams, fetcherConfig); assertNull(info.getAccessor().requestToken); assertEquals("access", info.getAccessor().accessToken); assertEquals("secret", info.getAccessor().tokenSecret); store.removeToken(privateToken, null, arguments, responseParams); - info = store.getOAuthAccessor(privateToken, arguments, clientState, responseParams); + info = store.getOAuthAccessor(privateToken, arguments, clientState, responseParams, fetcherConfig); assertNull(info.getAccessor().requestToken); assertNull(info.getAccessor().accessToken); assertNull(info.getAccessor().tokenSecret); Modified: incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/oauth/OAuthFetcherConfigTest.java URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/oauth/OAuthFetcherConfigTest.java?rev=834234&r1=834233&r2=834234&view=diff ============================================================================== --- incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/oauth/OAuthFetcherConfigTest.java (original) +++ incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/oauth/OAuthFetcherConfigTest.java Mon Nov 9 21:10:57 2009 @@ -36,9 +36,10 @@ GadgetOAuthTokenStore tokenStore = mock(GadgetOAuthTokenStore.class); OAuthCallbackGenerator callbackGenerator = mock(OAuthCallbackGenerator.class); OAuthFetcherConfig config = new OAuthFetcherConfig(crypter, tokenStore, new TimeSource(), - callbackGenerator); + callbackGenerator, false); assertEquals(crypter, config.getStateCrypter()); assertEquals(tokenStore, config.getTokenStore()); assertEquals(callbackGenerator, config.getOAuthCallbackGenerator()); + assertFalse(config.isViewerAccessTokensEnabled()); } } Modified: incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/oauth/OAuthRequestTest.java URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/oauth/OAuthRequestTest.java?rev=834234&r1=834233&r2=834234&view=diff ============================================================================== --- incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/oauth/OAuthRequestTest.java (original) +++ incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/oauth/OAuthRequestTest.java Mon Nov 9 21:10:57 2009 @@ -100,7 +100,8 @@ new BasicBlobCrypter("abcdefghijklmnop".getBytes()), getOAuthStore(base), clock, - callbackGenerator); + callbackGenerator, + false); logger = Logger.getLogger(OAuthResponseParams.class.getName()); logger.addHandler(new Handler() { @@ -148,11 +149,11 @@ /** * Builds a nicely populated fake token store. */ - public static GadgetOAuthTokenStore getOAuthStore(BasicOAuthStore base) { + public GadgetOAuthTokenStore getOAuthStore(BasicOAuthStore base) { return getOAuthStore(base, new FakeGadgetSpecFactory()); } - private static GadgetOAuthTokenStore getOAuthStore(BasicOAuthStore base, + private GadgetOAuthTokenStore getOAuthStore(BasicOAuthStore base, GadgetSpecFactory specFactory) { if (base == null) { base = new BasicOAuthStore(); @@ -338,7 +339,8 @@ new BasicBlobCrypter("abcdefghijklmnop".getBytes()), getOAuthStore(base), clock, - createRealCallbackGenerator()); + createRealCallbackGenerator(), + false); MakeRequestClient client = makeNonSocialClient("owner", "owner", GADGET_URL); HttpResponse response = client.sendGet(FakeOAuthServiceProvider.RESOURCE_URL); @@ -356,7 +358,8 @@ new BasicBlobCrypter("abcdefghijklmnop".getBytes()), getOAuthStore(base), clock, - createRealCallbackGenerator()); + createRealCallbackGenerator(), + false); MakeRequestClient client = makeNonSocialClient("owner", "owner", GADGET_URL); HttpResponse response = client.sendGet(FakeOAuthServiceProvider.RESOURCE_URL); @@ -402,13 +405,22 @@ @Test public void testOAuthFlow_noViewer() throws Exception { - MakeRequestClient client = makeNonSocialClient("owner", null, GADGET_URL); + for (boolean secureOwner : Arrays.asList(true, false)) { + // Test both with/without secure owner pages + fetcherConfig = new OAuthFetcherConfig( + new BasicBlobCrypter("abcdefghijklmnop".getBytes()), + getOAuthStore(base), + clock, callbackGenerator, + secureOwner); - HttpResponse response = client.sendGet(FakeOAuthServiceProvider.RESOURCE_URL); - assertEquals("", response.getResponseAsString()); - assertEquals(403, response.getHttpStatusCode()); - assertEquals(-1, response.getCacheTtl()); - assertEquals(OAuthError.NOT_OWNER.toString(), response.getMetadata().get("oauthError")); + MakeRequestClient client = makeNonSocialClient("owner", null, GADGET_URL); + + HttpResponse response = client.sendGet(FakeOAuthServiceProvider.RESOURCE_URL); + assertEquals("", response.getResponseAsString()); + assertEquals(403, response.getHttpStatusCode()); + assertEquals(-1, response.getCacheTtl()); + assertEquals(OAuthError.UNAUTHENTICATED.toString(), response.getMetadata().get("oauthError")); + } } @Test @@ -416,7 +428,8 @@ fetcherConfig = new OAuthFetcherConfig( new BasicBlobCrypter("abcdefghijklmnop".getBytes()), getOAuthStore(base, null), - clock, callbackGenerator); + clock, callbackGenerator, + false); MakeRequestClient client = makeNonSocialClient("owner", "owner", GADGET_URL); setNoSpecOptions(client); @@ -447,7 +460,7 @@ fetcherConfig = new OAuthFetcherConfig( new BasicBlobCrypter("abcdefghijklmnop".getBytes()), getOAuthStore(base, null), - clock, null); + clock, null, false); MakeRequestClient client = makeNonSocialClient("owner", "owner", GADGET_URL); setNoSpecOptions(client); @@ -469,7 +482,7 @@ fetcherConfig = new OAuthFetcherConfig( new BasicBlobCrypter("abcdefghijklmnop".getBytes()), getOAuthStore(base, null), - clock, callbackGenerator); + clock, callbackGenerator, false); MakeRequestClient client = makeNonSocialClient("owner", "owner", GADGET_URL); setNoSpecOptions(client); @@ -496,7 +509,7 @@ fetcherConfig = new OAuthFetcherConfig( new BasicBlobCrypter("abcdefghijklmnop".getBytes()), getOAuthStore(base, null), - clock, callbackGenerator); + clock, callbackGenerator, false); MakeRequestClient client = makeNonSocialClient("owner", "owner", GADGET_URL); setNoSpecOptions(client); @@ -520,7 +533,7 @@ fetcherConfig = new OAuthFetcherConfig( new BasicBlobCrypter("abcdefghijklmnop".getBytes()), getOAuthStore(base, null), - clock, callbackGenerator); + clock, callbackGenerator, false); MakeRequestClient client = makeNonSocialClient("owner", "owner", GADGET_URL); setNoSpecOptions(client); @@ -541,7 +554,7 @@ fetcherConfig = new OAuthFetcherConfig( new BasicBlobCrypter("abcdefghijklmnop".getBytes()), getOAuthStore(base, null), - clock, callbackGenerator); + clock, callbackGenerator, false); MakeRequestClient client = makeNonSocialClient("owner", "owner", GADGET_URL); setNoSpecOptions(client); @@ -564,7 +577,7 @@ fetcherConfig = new OAuthFetcherConfig( new BasicBlobCrypter("abcdefghijklmnop".getBytes()), getOAuthStore(base, null), - clock, callbackGenerator); + clock, callbackGenerator, false); MakeRequestClient client = makeNonSocialClient("owner", "owner", GADGET_URL); setNoSpecOptions(client); @@ -585,7 +598,7 @@ fetcherConfig = new OAuthFetcherConfig( new BasicBlobCrypter("abcdefghijklmnop".getBytes()), getOAuthStore(base, null), - clock, null); + clock, null, false); MakeRequestClient client = makeNonSocialClient("owner", "owner", GADGET_URL); setNoSpecOptions(client); @@ -606,7 +619,7 @@ fetcherConfig = new OAuthFetcherConfig( new BasicBlobCrypter("abcdefghijklmnop".getBytes()), getOAuthStore(base, null), - clock, null); + clock, null, false); MakeRequestClient client = makeNonSocialClient("owner", "owner", GADGET_URL); setNoSpecOptions(client); @@ -641,6 +654,30 @@ } @Test + public void testAccessTokenOkForSecureOwnerPage() throws Exception { + fetcherConfig = new OAuthFetcherConfig( + new BasicBlobCrypter("abcdefghijklmnop".getBytes()), + getOAuthStore(base), + clock, + callbackGenerator, + true); + + MakeRequestClient client = makeNonSocialClient("owner", "owner", GADGET_URL); + + HttpResponse response = client.sendGet(FakeOAuthServiceProvider.RESOURCE_URL); + assertEquals("", response.getResponseAsString()); + client.approveToken("user_data=hello-oauth"); + + response = client.sendGet(FakeOAuthServiceProvider.RESOURCE_URL); + assertEquals("User data is hello-oauth", response.getResponseAsString()); + + MakeRequestClient friend = makeNonSocialClient("owner", "friend", GADGET_URL); + response = friend.sendGet(FakeOAuthServiceProvider.RESOURCE_URL); + assertEquals("", response.getResponseAsString()); + assertEquals(200, response.getHttpStatusCode()); + } + + @Test public void testParamsInHeader() throws Exception { serviceProvider.setParamLocation(OAuthParamLocation.AUTH_HEADER); MakeRequestClient client = makeNonSocialClient("owner", "owner", GADGET_URL_HEADER);