* Refactor OAuth so that it doesn't require private keys when we aren't 
signing anything.
 * Rename constant serviceAccountCredentials to p12PrivateKeyCredentials as 
this better describes the credential value.


Project: http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/repo
Commit: 
http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/commit/6c839f13
Tree: http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/tree/6c839f13
Diff: http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/diff/6c839f13

Branch: refs/heads/master
Commit: 6c839f135a0756afb8ed5c72c43ceabda3d5cdcf
Parents: 37e0397
Author: Adrian Cole <[email protected]>
Authored: Tue Nov 11 10:40:47 2014 -0800
Committer: Adrian Cole <[email protected]>
Committed: Tue Nov 11 16:20:58 2014 -0800

----------------------------------------------------------------------
 .../GoogleCloudStorageApiMetadata.java          |   4 +-
 .../BaseGoogleCloudStorageExpectTest.java       |  15 ++-
 google-compute-engine/pom.xml                   |   2 +-
 .../GoogleComputeEngineApiMetadata.java         |   4 +-
 .../config/GoogleComputeEngineProperties.java   |   2 +-
 .../BaseGoogleComputeEngineApiMockTest.java     |   3 -
 .../BaseGoogleComputeEngineExpectTest.java      |   6 +-
 .../internal/GoogleComputeEngineTestModule.java |   6 +-
 .../internal/TestProperties.java                |  13 +-
 oauth/README                                    |   6 -
 oauth/pom.xml                                   |   4 +-
 .../org/jclouds/oauth/v2/JWSAlgorithms.java     |  75 +++++++++++
 .../java/org/jclouds/oauth/v2/OAuthApi.java     |   8 +-
 .../org/jclouds/oauth/v2/OAuthApiMetadata.java  |   8 +-
 .../org/jclouds/oauth/v2/OAuthConstants.java    |  78 -----------
 .../oauth/v2/binders/OAuthTokenBinder.java      |  76 -----------
 .../jclouds/oauth/v2/binders/TokenBinder.java   |  77 +++++++++++
 .../jclouds/oauth/v2/config/Authentication.java |  35 -----
 .../jclouds/oauth/v2/config/CredentialType.java |  20 ++-
 .../java/org/jclouds/oauth/v2/config/OAuth.java |  35 +++++
 .../v2/config/OAuthAuthenticationModule.java    |  10 +-
 .../oauth/v2/config/OAuthHttpApiModule.java     |   2 +-
 .../jclouds/oauth/v2/config/OAuthModule.java    |  45 ++++---
 .../oauth/v2/config/OAuthProperties.java        |  18 +--
 .../jclouds/oauth/v2/config/OAuthScopes.java    |   3 +-
 .../org/jclouds/oauth/v2/domain/Header.java     |   2 +-
 .../oauth/v2/domain/OAuthCredentials.java       | 129 ------------------
 .../v2/filters/BearerTokenAuthenticator.java    |   7 +-
 .../oauth/v2/filters/OAuthAuthenticator.java    |  15 +--
 .../oauth/v2/functions/BuildTokenRequest.java   |  92 ++++++-------
 .../v2/functions/OAuthCredentialsSupplier.java  | 130 -------------------
 .../oauth/v2/functions/PrivateKeySupplier.java  | 105 +++++++++++++++
 .../v2/functions/SignOrProduceMacForToken.java  |  59 +++------
 .../jclouds/oauth/v2/OAuthApiMetadataTest.java  |   5 +-
 .../org/jclouds/oauth/v2/OAuthTestUtils.java    |   7 +-
 .../oauth/v2/binders/OAuthTokenBinderTest.java  |  75 -----------
 .../oauth/v2/binders/TokenBinderTest.java       |  74 +++++++++++
 .../oauth/v2/features/OAuthApiLiveTest.java     |  17 +--
 .../functions/OAuthCredentialsFromPKTest.java   |  62 ---------
 .../functions/OAuthCredentialsSupplierTest.java |  56 --------
 .../v2/functions/PrivateKeySupplierTest.java    |  83 ++++++++++++
 .../oauth/v2/functions/SignerFunctionTest.java  |   9 +-
 .../v2/handlers/OAuthErrorHandlerTest.java      |  16 +--
 .../oauth/v2/internal/BaseOAuthApiLiveTest.java |   7 +-
 .../BaseOAuthAuthenticatedApiLiveTest.java      |  14 +-
 45 files changed, 630 insertions(+), 889 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/6c839f13/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/GoogleCloudStorageApiMetadata.java
----------------------------------------------------------------------
diff --git 
a/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/GoogleCloudStorageApiMetadata.java
 
b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/GoogleCloudStorageApiMetadata.java
index 4cf6a49..604e4ed 100644
--- 
a/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/GoogleCloudStorageApiMetadata.java
+++ 
b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/GoogleCloudStorageApiMetadata.java
@@ -21,7 +21,7 @@ import static 
org.jclouds.googlecloudstorage.reference.GoogleCloudStorageConstan
 import static 
org.jclouds.googlecloudstorage.reference.GoogleCloudStorageConstants.OPERATION_COMPLETE_INTERVAL;
 import static 
org.jclouds.googlecloudstorage.reference.GoogleCloudStorageConstants.OPERATION_COMPLETE_TIMEOUT;
 import static org.jclouds.oauth.v2.config.OAuthProperties.AUDIENCE;
-import static 
org.jclouds.oauth.v2.config.OAuthProperties.SIGNATURE_OR_MAC_ALGORITHM;
+import static org.jclouds.oauth.v2.config.OAuthProperties.JWS_ALG;
 import static org.jclouds.reflect.Reflection2.typeToken;
 
 import java.net.URI;
@@ -60,7 +60,7 @@ public class GoogleCloudStorageApiMetadata extends 
BaseHttpApiMetadata<GoogleClo
       Properties properties = BaseHttpApiMetadata.defaultProperties();
       properties.put("oauth.endpoint", 
"https://accounts.google.com/o/oauth2/token";);
       properties.put(AUDIENCE, "https://accounts.google.com/o/oauth2/token";);
-      properties.put(SIGNATURE_OR_MAC_ALGORITHM, "RS256");
+      properties.put(JWS_ALG, "RS256");
       properties.put(PROPERTY_SESSION_INTERVAL, 3600);
       properties.put(OPERATION_COMPLETE_INTERVAL, 2000);
       properties.put(OPERATION_COMPLETE_TIMEOUT, 600000);

http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/6c839f13/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/internal/BaseGoogleCloudStorageExpectTest.java
----------------------------------------------------------------------
diff --git 
a/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/internal/BaseGoogleCloudStorageExpectTest.java
 
b/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/internal/BaseGoogleCloudStorageExpectTest.java
index bf09591..d0976c7 100644
--- 
a/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/internal/BaseGoogleCloudStorageExpectTest.java
+++ 
b/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/internal/BaseGoogleCloudStorageExpectTest.java
@@ -27,6 +27,8 @@ import static org.jclouds.crypto.Pems.privateKeySpec;
 import static org.jclouds.crypto.Pems.publicKeySpec;
 import static org.jclouds.crypto.PemsTest.PRIVATE_KEY;
 import static org.jclouds.crypto.PemsTest.PUBLIC_KEY;
+import static org.jclouds.oauth.v2.JWSAlgorithms.NONE;
+import static org.jclouds.oauth.v2.config.OAuthProperties.JWS_ALG;
 
 import java.io.IOException;
 import java.net.URI;
@@ -49,13 +51,13 @@ import org.jclouds.http.HttpRequest;
 import org.jclouds.http.HttpResponse;
 import org.jclouds.io.Payload;
 import org.jclouds.io.payloads.ByteSourcePayload;
-import org.jclouds.oauth.v2.OAuthConstants;
-import org.jclouds.oauth.v2.config.OAuthProperties;
+import org.jclouds.oauth.v2.functions.BuildTokenRequest;
+import org.jclouds.oauth.v2.functions.BuildTokenRequest.TestBuildTokenRequest;
 import org.jclouds.rest.internal.BaseRestApiExpectTest;
 import org.jclouds.ssh.SshKeys;
+
 import com.google.common.base.Joiner;
 import com.google.common.base.Supplier;
-import com.google.common.base.Suppliers;
 import com.google.common.io.ByteSource;
 import com.google.common.io.Resources;
 import com.google.inject.Binder;
@@ -89,9 +91,8 @@ public class BaseGoogleCloudStorageExpectTest<T> extends 
BaseRestApiExpectTest<T
       return new Module() {
          @Override
          public void configure(Binder binder) {
-            // Predicatable time
-            binder.bind(new TypeLiteral<Supplier<Long>>() {
-            }).toInstance(Suppliers.ofInstance(0L));
+            // Predictable time
+            
binder.bind(BuildTokenRequest.class).to(TestBuildTokenRequest.class);
             try {
                KeyFactory keyfactory = KeyFactory.getInstance("RSA");
                PrivateKey privateKey = 
keyfactory.generatePrivate(privateKeySpec(ByteSource.wrap(PRIVATE_KEY
@@ -135,7 +136,7 @@ public class BaseGoogleCloudStorageExpectTest<T> extends 
BaseRestApiExpectTest<T
    protected Properties setupProperties() {
       Properties props = super.setupProperties();
       // use no sig algorithm for expect tests (means no credential is 
required either)
-      props.put(OAuthProperties.SIGNATURE_OR_MAC_ALGORITHM, 
OAuthConstants.NO_ALGORITHM);
+      props.put(JWS_ALG, NONE);
       return props;
    }
 

http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/6c839f13/google-compute-engine/pom.xml
----------------------------------------------------------------------
diff --git a/google-compute-engine/pom.xml b/google-compute-engine/pom.xml
index 38de821..dd9a379 100644
--- a/google-compute-engine/pom.xml
+++ b/google-compute-engine/pom.xml
@@ -37,7 +37,7 @@
         <test.google-compute-engine.credential>Private key (PEM encoded PKCS12 
file or literal) associated with the 
client_email</test.google-compute-engine.credential>
         <!-- Add this property to use a different project, or avoid looking up 
the project for each test. -->
         
<test.jclouds.google-compute-engine.project-name></test.jclouds.google-compute-engine.project-name>
-        
<test.jclouds.oauth.credential-type>serviceAccountCredentials</test.jclouds.oauth.credential-type>
+        
<test.jclouds.oauth.credential-type>p12PrivateKeyCredentials</test.jclouds.oauth.credential-type>
         
<test.google-compute-engine.api-version>v1</test.google-compute-engine.api-version>
         <test.google-compute-engine.build-version/>
         
<test.google-compute-engine.template>imageNameMatches=debian-7-wheezy-v[0-9]*,locationId=us-central1-a,minRam=2048</test.google-compute-engine.template>

http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/6c839f13/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/GoogleComputeEngineApiMetadata.java
----------------------------------------------------------------------
diff --git 
a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/GoogleComputeEngineApiMetadata.java
 
b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/GoogleComputeEngineApiMetadata.java
index 32da0eb..4ddea1b 100644
--- 
a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/GoogleComputeEngineApiMetadata.java
+++ 
b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/GoogleComputeEngineApiMetadata.java
@@ -23,7 +23,7 @@ import static 
org.jclouds.googlecomputeengine.config.GoogleComputeEngineProperti
 import static 
org.jclouds.googlecomputeengine.config.GoogleComputeEngineProperties.OPERATION_COMPLETE_TIMEOUT;
 import static 
org.jclouds.googlecomputeengine.config.GoogleComputeEngineProperties.PROJECT_NAME;
 import static org.jclouds.oauth.v2.config.OAuthProperties.AUDIENCE;
-import static 
org.jclouds.oauth.v2.config.OAuthProperties.SIGNATURE_OR_MAC_ALGORITHM;
+import static org.jclouds.oauth.v2.config.OAuthProperties.JWS_ALG;
 import static org.jclouds.reflect.Reflection2.typeToken;
 
 import java.net.URI;
@@ -58,7 +58,7 @@ public class GoogleComputeEngineApiMetadata extends 
BaseHttpApiMetadata<GoogleCo
       Properties properties = BaseHttpApiMetadata.defaultProperties();
       properties.put("oauth.endpoint", 
"https://accounts.google.com/o/oauth2/token";);
       properties.put(AUDIENCE, "https://accounts.google.com/o/oauth2/token";);
-      properties.put(SIGNATURE_OR_MAC_ALGORITHM, "RS256");
+      properties.put(JWS_ALG, "RS256");
       properties.put(PROPERTY_SESSION_INTERVAL, 3600);
       properties.put(OPERATION_COMPLETE_INTERVAL, 500);
       properties.put(OPERATION_COMPLETE_TIMEOUT, 600000);

http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/6c839f13/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/config/GoogleComputeEngineProperties.java
----------------------------------------------------------------------
diff --git 
a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/config/GoogleComputeEngineProperties.java
 
b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/config/GoogleComputeEngineProperties.java
index 4f2be3d..e554fc0 100644
--- 
a/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/config/GoogleComputeEngineProperties.java
+++ 
b/google-compute-engine/src/main/java/org/jclouds/googlecomputeengine/config/GoogleComputeEngineProperties.java
@@ -24,7 +24,7 @@ import com.google.common.annotations.Beta;
 public final class GoogleComputeEngineProperties {
 
    /**
-    * How requests are authorized using OAuth. Defaults to {@link 
org.jclouds.oauth.v2.config.CredentialType#SERVICE_ACCOUNT_CREDENTIALS}.
+    * How requests are authorized using OAuth. Defaults to {@link 
org.jclouds.oauth.v2.config.CredentialType#P12_PRIVATE_KEY_CREDENTIALS}.
     *
     * @see org.jclouds.oauth.v2.config.CredentialType
     */

http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/6c839f13/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/internal/BaseGoogleComputeEngineApiMockTest.java
----------------------------------------------------------------------
diff --git 
a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/internal/BaseGoogleComputeEngineApiMockTest.java
 
b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/internal/BaseGoogleComputeEngineApiMockTest.java
index ab691e8..0f53fba 100644
--- 
a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/internal/BaseGoogleComputeEngineApiMockTest.java
+++ 
b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/internal/BaseGoogleComputeEngineApiMockTest.java
@@ -23,9 +23,7 @@ import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
 import static 
org.jclouds.googlecomputeengine.config.GoogleComputeEngineProperties.CREDENTIAL_TYPE;
 import static 
org.jclouds.googlecomputeengine.config.GoogleComputeEngineProperties.IMAGE_PROJECTS;
 import static 
org.jclouds.googlecomputeengine.config.GoogleComputeEngineProperties.PROJECT_NAME;
-import static org.jclouds.oauth.v2.OAuthConstants.NO_ALGORITHM;
 import static 
org.jclouds.oauth.v2.config.CredentialType.BEARER_TOKEN_CREDENTIALS;
-import static 
org.jclouds.oauth.v2.config.OAuthProperties.SIGNATURE_OR_MAC_ALGORITHM;
 import static org.jclouds.util.Strings2.toStringAndClose;
 import static org.testng.Assert.assertEquals;
 
@@ -74,7 +72,6 @@ public class BaseGoogleComputeEngineApiMockTest {
       overrides.put(PROJECT_NAME, "party");
       overrides.put(IMAGE_PROJECTS, "debian-cloud");
       overrides.put(CREDENTIAL_TYPE, BEARER_TOKEN_CREDENTIALS.toString());
-      overrides.put(SIGNATURE_OR_MAC_ALGORITHM, NO_ALGORITHM); // TODO: this 
should be implied by the above.
       return ContextBuilder.newBuilder(new 
GoogleComputeEngineProviderMetadata())
             .credentials(identity, credential)
             .endpoint(url(""))

http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/6c839f13/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/internal/BaseGoogleComputeEngineExpectTest.java
----------------------------------------------------------------------
diff --git 
a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/internal/BaseGoogleComputeEngineExpectTest.java
 
b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/internal/BaseGoogleComputeEngineExpectTest.java
index bf9bead..220f5f0 100644
--- 
a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/internal/BaseGoogleComputeEngineExpectTest.java
+++ 
b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/internal/BaseGoogleComputeEngineExpectTest.java
@@ -21,8 +21,8 @@ import static com.google.common.base.Throwables.propagate;
 import static com.google.common.io.BaseEncoding.base64Url;
 import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
 import static 
org.jclouds.googlecomputeengine.config.GoogleComputeEngineProperties.PROJECT_NAME;
-import static org.jclouds.oauth.v2.OAuthConstants.NO_ALGORITHM;
-import static 
org.jclouds.oauth.v2.config.OAuthProperties.SIGNATURE_OR_MAC_ALGORITHM;
+import static org.jclouds.oauth.v2.JWSAlgorithms.NONE;
+import static org.jclouds.oauth.v2.config.OAuthProperties.JWS_ALG;
 import static org.jclouds.util.Strings2.toStringAndClose;
 
 import java.io.IOException;
@@ -78,7 +78,7 @@ public class BaseGoogleComputeEngineExpectTest<T> extends 
BaseRestApiExpectTest<
       Properties props = super.setupProperties();
       props.put(PROJECT_NAME, "party");
       // use no sig algorithm for expect tests (means no credential is 
required either)
-      props.put(SIGNATURE_OR_MAC_ALGORITHM, NO_ALGORITHM);
+      props.put(JWS_ALG, NONE);
       return props;
    }
 

http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/6c839f13/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/internal/GoogleComputeEngineTestModule.java
----------------------------------------------------------------------
diff --git 
a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/internal/GoogleComputeEngineTestModule.java
 
b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/internal/GoogleComputeEngineTestModule.java
index 219b716..8541fc5 100644
--- 
a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/internal/GoogleComputeEngineTestModule.java
+++ 
b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/internal/GoogleComputeEngineTestModule.java
@@ -37,10 +37,11 @@ import java.security.interfaces.RSAPublicKey;
 import java.util.concurrent.atomic.AtomicInteger;
 
 import org.jclouds.crypto.Crypto;
+import org.jclouds.oauth.v2.functions.BuildTokenRequest;
+import org.jclouds.oauth.v2.functions.BuildTokenRequest.TestBuildTokenRequest;
 import org.jclouds.ssh.SshKeys;
 
 import com.google.common.base.Supplier;
-import com.google.common.base.Suppliers;
 import com.google.common.io.ByteSource;
 import com.google.inject.Binder;
 import com.google.inject.Module;
@@ -67,8 +68,7 @@ enum GoogleComputeEngineTestModule implements Module {
 
    @Override public void configure(Binder binder) {
       // Predictable time
-      binder.bind(new TypeLiteral<Supplier<Long>>() {
-      }).toInstance(Suppliers.ofInstance(0L));
+      binder.bind(BuildTokenRequest.class).to(TestBuildTokenRequest.class);
 
       // Predictable ssh keys
       Crypto crypto = createMock(Crypto.class);

http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/6c839f13/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/internal/TestProperties.java
----------------------------------------------------------------------
diff --git 
a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/internal/TestProperties.java
 
b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/internal/TestProperties.java
index a9a3efd..7c43910 100644
--- 
a/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/internal/TestProperties.java
+++ 
b/google-compute-engine/src/test/java/org/jclouds/googlecomputeengine/internal/TestProperties.java
@@ -18,10 +18,8 @@ package org.jclouds.googlecomputeengine.internal;
 
 import static 
org.jclouds.googlecomputeengine.config.GoogleComputeEngineProperties.CREDENTIAL_TYPE;
 import static 
org.jclouds.googlecomputeengine.config.GoogleComputeEngineProperties.PROJECT_NAME;
-import static org.jclouds.oauth.v2.OAuthConstants.NO_ALGORITHM;
 import static org.jclouds.oauth.v2.OAuthTestUtils.setCredential;
-import static 
org.jclouds.oauth.v2.config.CredentialType.BEARER_TOKEN_CREDENTIALS;
-import static 
org.jclouds.oauth.v2.config.OAuthProperties.SIGNATURE_OR_MAC_ALGORITHM;
+import static 
org.jclouds.oauth.v2.config.CredentialType.P12_PRIVATE_KEY_CREDENTIALS;
 
 import java.util.Properties;
 
@@ -33,12 +31,9 @@ public final class TestProperties {
    public static Properties apply(Properties props) {
       setIfTestSystemPropertyPresent(props, PROJECT_NAME);
       setIfTestSystemPropertyPresent(props, CREDENTIAL_TYPE);
-      if (props.containsKey(CREDENTIAL_TYPE)) {
-         if (CredentialType.fromValue(props.getProperty(CREDENTIAL_TYPE)) == 
BEARER_TOKEN_CREDENTIALS) {
-            props.put(SIGNATURE_OR_MAC_ALGORITHM, NO_ALGORITHM); // TODO: this 
should be implied by the above.
-         } else {
-            setCredential(props, "google-compute-engine.credential");
-         }
+      if (props.containsKey(CREDENTIAL_TYPE)
+            && CredentialType.fromValue(props.getProperty(CREDENTIAL_TYPE)) == 
P12_PRIVATE_KEY_CREDENTIALS) {
+         setCredential(props, "google-compute-engine.credential");
       }
       return props;
    }

http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/6c839f13/oauth/README
----------------------------------------------------------------------
diff --git a/oauth/README b/oauth/README
index 32b571a..1c5f73b 100644
--- a/oauth/README
+++ b/oauth/README
@@ -6,11 +6,6 @@ Mandatory:
 oauth.endpoint - the endpoint to use for authentication (e.g., 
"http://accounts.google.com/o/oauth2/token"; in Google Api's)
 oauth.audience - the "audience" of the token request (e.g., 
"http://accounts.google.com/o/oauth2/token"; in Google Api's)
 
-Optional:
-- each application may expose a Map<String,String> of additional claims to be 
added to the token request,
-these should be annotated/named with "oauth.additional-claims"
-oauth.signature-or-mac-algorithm  - the algorithms to use when signing the 
token request.
-
 Running the live test:
 
 mvn clean install -Plive\
@@ -18,5 +13,4 @@ mvn clean install -Plive\
  -Dtest.oauth.credential=<accout pk in pem format>\
  -Dtest.oauth.endpoint=https://accounts.google.com/o/oauth2/token\
  -Dtest.jclouds.oauth.audience=https://accounts.google.com/o/oauth2/token\
- -Dtest.jclouds.oauth.signature-or-mac-algorithm=RS256\
  -Dtest.jclouds.oauth.scopes=https://www.googleapis.com/auth/prediction
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/6c839f13/oauth/pom.xml
----------------------------------------------------------------------
diff --git a/oauth/pom.xml b/oauth/pom.xml
index a13d15b..275ce4b 100644
--- a/oauth/pom.xml
+++ b/oauth/pom.xml
@@ -35,7 +35,7 @@
     <test.oauth.identity>FIX_ME</test.oauth.identity>
     <test.oauth.credential>FIX_ME</test.oauth.credential>
     <test.oauth.endpoint>FIX_ME</test.oauth.endpoint>
-    
<test.jclouds.oauth.signature-or-mac-algorithm>FIX_ME</test.jclouds.oauth.signature-or-mac-algorithm>
+    <test.jclouds.oauth.jws-alg>RS256</test.jclouds.oauth.jws-alg>
     <test.jclouds.oauth.audience>FIX_ME</test.jclouds.oauth.audience>
     <test.jclouds.oauth.scopes>FIX_ME</test.jclouds.oauth.scopes>
     <test.oauth.api-version>2</test.oauth.api-version>
@@ -121,7 +121,7 @@
                     
<test.oauth.endpoint>${test.oauth.endpoint}</test.oauth.endpoint>
                     
<test.oauth.api-version>${test.oauth.api-version}</test.oauth.api-version>
                     
<test.oauth.build-version>${test.oauth.build-version}</test.oauth.build-version>
-                    
<test.jclouds.oauth.signature-or-mac-algorithm>${test.jclouds.oauth.signature-or-mac-algorithm}</test.jclouds.oauth.signature-or-mac-algorithm>
+                    
<test.jclouds.oauth.jws-alg>${test.jclouds.oauth.jws-alg}</test.jclouds.oauth.jws-alg>
                     
<test.jclouds.oauth.audience>${test.jclouds.oauth.audience}</test.jclouds.oauth.audience>
                     
<test.jclouds.oauth.scopes>${test.jclouds.oauth.scopes}</test.jclouds.oauth.scopes>
                   </systemPropertyVariables>

http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/6c839f13/oauth/src/main/java/org/jclouds/oauth/v2/JWSAlgorithms.java
----------------------------------------------------------------------
diff --git a/oauth/src/main/java/org/jclouds/oauth/v2/JWSAlgorithms.java 
b/oauth/src/main/java/org/jclouds/oauth/v2/JWSAlgorithms.java
new file mode 100644
index 0000000..072fc53
--- /dev/null
+++ b/oauth/src/main/java/org/jclouds/oauth/v2/JWSAlgorithms.java
@@ -0,0 +1,75 @@
+/*
+ * 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.jclouds.oauth.v2;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.security.KeyFactory;
+import java.security.NoSuchAlgorithmException;
+import java.util.List;
+
+import com.google.common.collect.ImmutableList;
+
+/**
+ * JSON Web Signature Algorithms
+ * <p/>
+ * We only support <a 
href="http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-36#section-3.1";>required
+ * or recommended algorithms</a>, with the exception of {@code none}, which is 
only supported in tests.
+ */
+public final class JWSAlgorithms {
+   /** This is a marker algorithm only supported in tests. */
+   public static final String NONE = "none";
+
+   private static final List<String> SUPPORTED_ALGS = 
ImmutableList.of("ES256", "RS256", "HS256", NONE);
+
+   /**
+    * Static mapping between the oauth algorithm name and the Crypto provider 
signature algorithm name and KeyFactory.
+    */
+   private static final List<List<String>> 
ALG_TO_SIGNATURE_ALG_AND_KEY_FACTORY = ImmutableList.<List<String>>of( //
+         ImmutableList.of(SUPPORTED_ALGS.get(0), "SHA256withECDSA", "EC"), // 
ECDSA using P-256 and SHA-256
+         ImmutableList.of(SUPPORTED_ALGS.get(1), "SHA256withRSA", "RSA"), // 
RSASSA-PKCS-v1_5 using SHA-256
+         ImmutableList.of(SUPPORTED_ALGS.get(2), "HmacSHA256", 
"DiffieHellman") // HMAC using SHA-256
+   );
+
+   /** Ordered list of supported algorithms by recommendation. */
+   public static List<String> supportedAlgs() {
+      return SUPPORTED_ALGS;
+   }
+
+   public static String macOrSignature(String jwsAlg) {
+      return ALG_TO_SIGNATURE_ALG_AND_KEY_FACTORY.get(indexOf(jwsAlg)).get(1);
+   }
+
+   public static KeyFactory keyFactory(String jwsAlg) {
+      String keyFactoryAlgorithm = 
ALG_TO_SIGNATURE_ALG_AND_KEY_FACTORY.get(indexOf(jwsAlg)).get(2);
+      try {
+         return KeyFactory.getInstance(keyFactoryAlgorithm);
+      } catch (NoSuchAlgorithmException e) {
+         throw new AssertionError("Invalid contents in JWSAlgorithms! " + 
e.getMessage());
+      }
+   }
+
+   private static int indexOf(String jwsAlg) {
+      int result = SUPPORTED_ALGS.indexOf(checkNotNull(jwsAlg, "jwsAlg"));
+      checkArgument(result != -1, "JSON Web Signature alg %s is not in the 
supported list %s", jwsAlg, SUPPORTED_ALGS);
+      return result;
+   }
+
+   private JWSAlgorithms() {
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/6c839f13/oauth/src/main/java/org/jclouds/oauth/v2/OAuthApi.java
----------------------------------------------------------------------
diff --git a/oauth/src/main/java/org/jclouds/oauth/v2/OAuthApi.java 
b/oauth/src/main/java/org/jclouds/oauth/v2/OAuthApi.java
index d3082fc..770e5e8 100644
--- a/oauth/src/main/java/org/jclouds/oauth/v2/OAuthApi.java
+++ b/oauth/src/main/java/org/jclouds/oauth/v2/OAuthApi.java
@@ -24,8 +24,8 @@ import javax.inject.Named;
 import javax.ws.rs.Consumes;
 import javax.ws.rs.POST;
 
-import org.jclouds.oauth.v2.binders.OAuthTokenBinder;
-import org.jclouds.oauth.v2.config.Authentication;
+import org.jclouds.oauth.v2.binders.TokenBinder;
+import org.jclouds.oauth.v2.config.OAuth;
 import org.jclouds.oauth.v2.domain.Token;
 import org.jclouds.oauth.v2.domain.TokenRequest;
 import org.jclouds.rest.AuthorizationException;
@@ -39,7 +39,7 @@ import org.jclouds.rest.annotations.Endpoint;
  * OAuthAuthenticator as a request filter, which in turn uses this class to
  * perform token requests.
  */
-@Endpoint(Authentication.class)
+@Endpoint(OAuth.class)
 public interface OAuthApi extends Closeable {
 
    /**
@@ -57,5 +57,5 @@ public interface OAuthApi extends Closeable {
    @Named("authenticate")
    @POST
    @Consumes(APPLICATION_JSON)
-   Token authenticate(@BinderParam(OAuthTokenBinder.class) TokenRequest 
tokenRequest) throws AuthorizationException;
+   Token authenticate(@BinderParam(TokenBinder.class) TokenRequest 
tokenRequest) throws AuthorizationException;
 }

http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/6c839f13/oauth/src/main/java/org/jclouds/oauth/v2/OAuthApiMetadata.java
----------------------------------------------------------------------
diff --git a/oauth/src/main/java/org/jclouds/oauth/v2/OAuthApiMetadata.java 
b/oauth/src/main/java/org/jclouds/oauth/v2/OAuthApiMetadata.java
index 58714e0..66f61bb 100644
--- a/oauth/src/main/java/org/jclouds/oauth/v2/OAuthApiMetadata.java
+++ b/oauth/src/main/java/org/jclouds/oauth/v2/OAuthApiMetadata.java
@@ -17,9 +17,9 @@
 package org.jclouds.oauth.v2;
 
 import static org.jclouds.Constants.PROPERTY_SESSION_INTERVAL;
-import static 
org.jclouds.oauth.v2.config.CredentialType.SERVICE_ACCOUNT_CREDENTIALS;
+import static 
org.jclouds.oauth.v2.config.CredentialType.P12_PRIVATE_KEY_CREDENTIALS;
 import static org.jclouds.oauth.v2.config.OAuthProperties.CREDENTIAL_TYPE;
-import static 
org.jclouds.oauth.v2.config.OAuthProperties.SIGNATURE_OR_MAC_ALGORITHM;
+import static org.jclouds.oauth.v2.config.OAuthProperties.JWS_ALG;
 
 import java.net.URI;
 import java.util.Properties;
@@ -51,8 +51,8 @@ public class OAuthApiMetadata extends 
BaseHttpApiMetadata<OAuthApi> {
 
    public static Properties defaultProperties() {
       Properties properties = BaseHttpApiMetadata.defaultProperties();
-      properties.put(SIGNATURE_OR_MAC_ALGORITHM, "RS256");
-      properties.put(CREDENTIAL_TYPE, SERVICE_ACCOUNT_CREDENTIALS);
+      properties.put(JWS_ALG, "RS256");
+      properties.put(CREDENTIAL_TYPE, P12_PRIVATE_KEY_CREDENTIALS);
       properties.put(PROPERTY_SESSION_INTERVAL, 3600);
       return properties;
    }

http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/6c839f13/oauth/src/main/java/org/jclouds/oauth/v2/OAuthConstants.java
----------------------------------------------------------------------
diff --git a/oauth/src/main/java/org/jclouds/oauth/v2/OAuthConstants.java 
b/oauth/src/main/java/org/jclouds/oauth/v2/OAuthConstants.java
deleted file mode 100644
index 9b140d4..0000000
--- a/oauth/src/main/java/org/jclouds/oauth/v2/OAuthConstants.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * 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.jclouds.oauth.v2;
-
-import com.google.common.collect.ImmutableMap;
-
-import java.util.Map;
-
-/**
- * The constants for OAuth \
- */
-public final class OAuthConstants {
-
-   /**
-    * Selected algorithm when a signature or mac isn't required.
-    */
-   public static final String NO_ALGORITHM = "none";
-
-   /**
-    * Static mapping between the oauth algorithm name and the Crypto provider 
signature algorithm name.
-    *
-    * @see <a 
href="http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-06#section-3.1";>doc</a>
-    * @see org.jclouds.oauth.v2.json.JWTTokenRequestFormat
-    */
-   public static final Map<String, String> 
OAUTH_ALGORITHM_NAMES_TO_SIGNATURE_ALGORITHM_NAMES = ImmutableMap
-           .<String, String>builder()
-           .put("RS256", "SHA256withRSA")
-           .put("RS384", "SHA384withRSA")
-           .put("RS512", "SHA512withRSA")
-           .put("HS256", "HmacSHA256")
-           .put("HS384", "HmacSHA384")
-           .put("HS512", "HmacSHA512")
-           .put("ES256", "SHA256withECDSA")
-           .put("ES384", "SHA384withECDSA")
-           .put("ES512", "SHA512withECDSA")
-           .put(NO_ALGORITHM, NO_ALGORITHM).build();
-
-   /**
-    * Static mapping between the oauth algorithm name and the Crypto provider 
KeyFactory algorithm name.
-    *
-    * @see <a 
href="http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-06#section-3.1";>doc</a>
-    */
-   public static final Map<String, String> 
OAUTH_ALGORITHM_NAMES_TO_KEYFACTORY_ALGORITHM_NAMES = ImmutableMap
-           .<String, String>builder()
-           .put("RS256", "RSA")
-           .put("RS384", "RSA")
-           .put("RS512", "RSA")
-           .put("HS256", "DiffieHellman")
-           .put("HS384", "DiffieHellman")
-           .put("HS512", "DiffieHellman")
-           .put("ES256", "EC")
-           .put("ES384", "EC")
-           .put("ES512", "EC")
-           .put(NO_ALGORITHM, NO_ALGORITHM).build();
-
-   /**
-    * The (optional) set of additional claims to use, provided in 
Map<String,String> form
-    */
-   public static final String ADDITIONAL_CLAIMS = 
"jclouds.oauth.additional-claims";
-
-   private OAuthConstants() {
-      throw new AssertionError("intentionally unimplemented");
-   }
-}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/6c839f13/oauth/src/main/java/org/jclouds/oauth/v2/binders/OAuthTokenBinder.java
----------------------------------------------------------------------
diff --git 
a/oauth/src/main/java/org/jclouds/oauth/v2/binders/OAuthTokenBinder.java 
b/oauth/src/main/java/org/jclouds/oauth/v2/binders/OAuthTokenBinder.java
deleted file mode 100644
index e62d9c7..0000000
--- a/oauth/src/main/java/org/jclouds/oauth/v2/binders/OAuthTokenBinder.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * 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.jclouds.oauth.v2.binders;
-
-import static com.google.common.base.Charsets.UTF_8;
-import static com.google.common.base.Joiner.on;
-import static com.google.common.io.BaseEncoding.base64Url;
-import static org.jclouds.io.Payloads.newUrlEncodedFormPayload;
-
-import javax.inject.Inject;
-
-import org.jclouds.http.HttpRequest;
-import org.jclouds.io.Payload;
-import org.jclouds.json.Json;
-import org.jclouds.oauth.v2.domain.TokenRequest;
-import org.jclouds.rest.Binder;
-
-import com.google.common.base.Function;
-import com.google.common.collect.ImmutableMultimap;
-
-/**
- * Formats a token request into JWT format namely:
- * <ol>
- * <li>Transforms the token request to json.</li>
- * <li>Creates the base64 header.claimset portions of the payload.</li>
- * <li>Uses the provided signer function to create a signature.</li>
- * <li>Creates the full url encoded payload as described in: <a 
href="https://developers.google.com/accounts/docs/OAuth2ServiceAccount";>OAuth2ServiceAccount</a></li>
- * </ol>
- */
-public final class OAuthTokenBinder implements Binder {
-   private static final String ASSERTION_FORM_PARAM = "assertion";
-   private static final String GRANT_TYPE_FORM_PARAM = "grant_type";
-   private static final String GRANT_TYPE_JWT_BEARER = 
"urn:ietf:params:oauth:grant-type:jwt-bearer";
-
-   private final Function<byte[], byte[]> signer;
-   private final Json json;
-
-   @Inject OAuthTokenBinder(Function<byte[], byte[]> signer, Json json) {
-      this.signer = signer;
-      this.json = json;
-   }
-
-   @Override public <R extends HttpRequest> R bindToRequest(R request, Object 
input) {
-      TokenRequest tokenRequest = (TokenRequest) input;
-      String encodedHeader = json.toJson(tokenRequest.header());
-      String encodedClaimSet = json.toJson(tokenRequest.claimSet());
-
-      encodedHeader = 
base64Url().omitPadding().encode(encodedHeader.getBytes(UTF_8));
-      encodedClaimSet = 
base64Url().omitPadding().encode(encodedClaimSet.getBytes(UTF_8));
-
-      byte[] signature = signer.apply(on(".").join(encodedHeader, 
encodedClaimSet).getBytes(UTF_8));
-      String encodedSignature = signature != null ?  
base64Url().omitPadding().encode(signature) : "";
-
-      // the final assertion in base 64 encoded 
{header}.{claimSet}.{signature} format
-      String assertion = on(".").join(encodedHeader, encodedClaimSet, 
encodedSignature);
-      Payload payload = newUrlEncodedFormPayload(ImmutableMultimap.<String, 
String> builder()
-            .put(GRANT_TYPE_FORM_PARAM, GRANT_TYPE_JWT_BEARER)
-            .put(ASSERTION_FORM_PARAM, assertion).build());
-
-      return (R) request.toBuilder().payload(payload).build();
-   }
-}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/6c839f13/oauth/src/main/java/org/jclouds/oauth/v2/binders/TokenBinder.java
----------------------------------------------------------------------
diff --git a/oauth/src/main/java/org/jclouds/oauth/v2/binders/TokenBinder.java 
b/oauth/src/main/java/org/jclouds/oauth/v2/binders/TokenBinder.java
new file mode 100644
index 0000000..0782000
--- /dev/null
+++ b/oauth/src/main/java/org/jclouds/oauth/v2/binders/TokenBinder.java
@@ -0,0 +1,77 @@
+/*
+ * 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.jclouds.oauth.v2.binders;
+
+import static com.google.common.base.Charsets.UTF_8;
+import static com.google.common.base.Joiner.on;
+import static com.google.common.io.BaseEncoding.base64Url;
+import static org.jclouds.io.Payloads.newUrlEncodedFormPayload;
+
+import javax.inject.Inject;
+
+import org.jclouds.http.HttpRequest;
+import org.jclouds.io.Payload;
+import org.jclouds.json.Json;
+import org.jclouds.oauth.v2.domain.TokenRequest;
+import org.jclouds.rest.Binder;
+
+import com.google.common.base.Function;
+import com.google.common.base.Supplier;
+import com.google.common.collect.ImmutableMultimap;
+
+/**
+ * Formats a token request into JWT format namely:
+ * <ol>
+ * <li>Transforms the token request to json.</li>
+ * <li>Creates the base64 header.claimset portions of the payload.</li>
+ * <li>Uses the provided signer function to create a signature.</li>
+ * <li>Creates the full url encoded payload as described in: <a 
href="https://developers.google.com/accounts/docs/OAuth2ServiceAccount";>OAuth2ServiceAccount</a></li>
+ * </ol>
+ */
+public final class TokenBinder implements Binder {
+   private static final String ASSERTION_FORM_PARAM = "assertion";
+   private static final String GRANT_TYPE_FORM_PARAM = "grant_type";
+   private static final String GRANT_TYPE_JWT_BEARER = 
"urn:ietf:params:oauth:grant-type:jwt-bearer";
+
+   private final Supplier<Function<byte[], byte[]>> signer;
+   private final Json json;
+
+   @Inject TokenBinder(Supplier<Function<byte[], byte[]>> signer, Json json) {
+      this.signer = signer;
+      this.json = json;
+   }
+
+   @Override public <R extends HttpRequest> R bindToRequest(R request, Object 
input) {
+      TokenRequest tokenRequest = (TokenRequest) input;
+      String encodedHeader = json.toJson(tokenRequest.header());
+      String encodedClaimSet = json.toJson(tokenRequest.claimSet());
+
+      encodedHeader = 
base64Url().omitPadding().encode(encodedHeader.getBytes(UTF_8));
+      encodedClaimSet = 
base64Url().omitPadding().encode(encodedClaimSet.getBytes(UTF_8));
+
+      byte[] signature = signer.get().apply(on(".").join(encodedHeader, 
encodedClaimSet).getBytes(UTF_8));
+      String encodedSignature = signature != null ?  
base64Url().omitPadding().encode(signature) : "";
+
+      // the final assertion in base 64 encoded 
{header}.{claimSet}.{signature} format
+      String assertion = on(".").join(encodedHeader, encodedClaimSet, 
encodedSignature);
+      Payload payload = newUrlEncodedFormPayload(ImmutableMultimap.<String, 
String> builder()
+            .put(GRANT_TYPE_FORM_PARAM, GRANT_TYPE_JWT_BEARER)
+            .put(ASSERTION_FORM_PARAM, assertion).build());
+
+      return (R) request.toBuilder().payload(payload).build();
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/6c839f13/oauth/src/main/java/org/jclouds/oauth/v2/config/Authentication.java
----------------------------------------------------------------------
diff --git 
a/oauth/src/main/java/org/jclouds/oauth/v2/config/Authentication.java 
b/oauth/src/main/java/org/jclouds/oauth/v2/config/Authentication.java
deleted file mode 100644
index 24f6851..0000000
--- a/oauth/src/main/java/org/jclouds/oauth/v2/config/Authentication.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * 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.jclouds.oauth.v2.config;
-
-
-import javax.inject.Qualifier;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Qualifies OAuth related resources, such as Endpoint.
- *
- * @see org.jclouds.oauth.v2.OAuthApi
- */
-@Retention(value = RetentionPolicy.RUNTIME)
-@Target(value = {ElementType.TYPE, ElementType.FIELD, ElementType.PARAMETER, 
ElementType.METHOD})
-@Qualifier
-public @interface Authentication {
-}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/6c839f13/oauth/src/main/java/org/jclouds/oauth/v2/config/CredentialType.java
----------------------------------------------------------------------
diff --git 
a/oauth/src/main/java/org/jclouds/oauth/v2/config/CredentialType.java 
b/oauth/src/main/java/org/jclouds/oauth/v2/config/CredentialType.java
index 24a658b..141564b 100644
--- a/oauth/src/main/java/org/jclouds/oauth/v2/config/CredentialType.java
+++ b/oauth/src/main/java/org/jclouds/oauth/v2/config/CredentialType.java
@@ -16,27 +16,23 @@
  */
 package org.jclouds.oauth.v2.config;
 
+import static com.google.common.base.CaseFormat.LOWER_CAMEL;
+import static com.google.common.base.CaseFormat.UPPER_UNDERSCORE;
 import static com.google.common.base.Preconditions.checkNotNull;
 
-import com.google.common.base.CaseFormat;
-
-/**
- * Decides what type of credentials createContext is supplied with.
- */
+/** Defines the contents of the credential field in {@link 
org.jclouds.ContextBuilder#credentials(String, String)}. */
 public enum CredentialType {
 
    BEARER_TOKEN_CREDENTIALS,
 
-   SERVICE_ACCOUNT_CREDENTIALS;
+   /** Contents are a PEM-encoded P12 Private Key. */
+   P12_PRIVATE_KEY_CREDENTIALS;
 
-   @Override
-   public String toString() {
-      return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, name());
+   @Override public String toString() {
+      return UPPER_UNDERSCORE.to(LOWER_CAMEL, name());
    }
 
    public static CredentialType fromValue(String credentialType) {
-      return valueOf(CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, 
checkNotNull(credentialType,
-            "credentialType")));
+      return valueOf(LOWER_CAMEL.to(UPPER_UNDERSCORE, 
checkNotNull(credentialType, "credentialType")));
    }
-
 }

http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/6c839f13/oauth/src/main/java/org/jclouds/oauth/v2/config/OAuth.java
----------------------------------------------------------------------
diff --git a/oauth/src/main/java/org/jclouds/oauth/v2/config/OAuth.java 
b/oauth/src/main/java/org/jclouds/oauth/v2/config/OAuth.java
new file mode 100644
index 0000000..6255e50
--- /dev/null
+++ b/oauth/src/main/java/org/jclouds/oauth/v2/config/OAuth.java
@@ -0,0 +1,35 @@
+/*
+ * 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.jclouds.oauth.v2.config;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import javax.inject.Qualifier;
+
+/**
+ * Qualifies OAuth related resources, such as Endpoint.
+ *
+ * @see org.jclouds.oauth.v2.OAuthApi
+ */
+@Retention(value = RetentionPolicy.RUNTIME)
+@Target(value = {ElementType.TYPE, ElementType.FIELD, ElementType.PARAMETER, 
ElementType.METHOD})
+@Qualifier
+public @interface OAuth {
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/6c839f13/oauth/src/main/java/org/jclouds/oauth/v2/config/OAuthAuthenticationModule.java
----------------------------------------------------------------------
diff --git 
a/oauth/src/main/java/org/jclouds/oauth/v2/config/OAuthAuthenticationModule.java
 
b/oauth/src/main/java/org/jclouds/oauth/v2/config/OAuthAuthenticationModule.java
index fb2d413..4d238f1 100644
--- 
a/oauth/src/main/java/org/jclouds/oauth/v2/config/OAuthAuthenticationModule.java
+++ 
b/oauth/src/main/java/org/jclouds/oauth/v2/config/OAuthAuthenticationModule.java
@@ -30,9 +30,6 @@ import com.google.common.base.Suppliers;
 import com.google.inject.AbstractModule;
 import com.google.inject.Provides;
 
-/**
- * An OAuth module to be used form other providers.
- */
 public class OAuthAuthenticationModule extends AbstractModule {
 
    @Override
@@ -40,13 +37,10 @@ public class OAuthAuthenticationModule extends 
AbstractModule {
       bindHttpApi(binder(), OAuthApi.class);
    }
 
-   /**
-    * When oauth is used as a module the oauth endpoint is a normal property
-    */
    @Provides
    @Singleton
-   @Authentication
-   protected Supplier<URI> 
provideAuthenticationEndpoint(@Named("oauth.endpoint") String endpoint) {
+   @OAuth
+   protected Supplier<URI> oauthEndpoint(@Named("oauth.endpoint") String 
endpoint) {
       return Suppliers.ofInstance(URI.create(endpoint));
    }
 }

http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/6c839f13/oauth/src/main/java/org/jclouds/oauth/v2/config/OAuthHttpApiModule.java
----------------------------------------------------------------------
diff --git 
a/oauth/src/main/java/org/jclouds/oauth/v2/config/OAuthHttpApiModule.java 
b/oauth/src/main/java/org/jclouds/oauth/v2/config/OAuthHttpApiModule.java
index 6b4fdf9..3bb7c1a 100644
--- a/oauth/src/main/java/org/jclouds/oauth/v2/config/OAuthHttpApiModule.java
+++ b/oauth/src/main/java/org/jclouds/oauth/v2/config/OAuthHttpApiModule.java
@@ -37,7 +37,7 @@ public class OAuthHttpApiModule extends 
HttpApiModule<OAuthApi> {
 
    @Provides
    @Singleton
-   @Authentication
+   @OAuth
    protected Supplier<URI> provideAuthenticationEndpoint(ProviderMetadata 
providerMetadata) {
       return Suppliers.ofInstance(URI.create(providerMetadata.getEndpoint()));
    }

http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/6c839f13/oauth/src/main/java/org/jclouds/oauth/v2/config/OAuthModule.java
----------------------------------------------------------------------
diff --git a/oauth/src/main/java/org/jclouds/oauth/v2/config/OAuthModule.java 
b/oauth/src/main/java/org/jclouds/oauth/v2/config/OAuthModule.java
index 788dac4..e831c0f 100644
--- a/oauth/src/main/java/org/jclouds/oauth/v2/config/OAuthModule.java
+++ b/oauth/src/main/java/org/jclouds/oauth/v2/config/OAuthModule.java
@@ -16,11 +16,14 @@
  */
 package org.jclouds.oauth.v2.config;
 
+import static java.util.concurrent.TimeUnit.SECONDS;
 import static org.jclouds.Constants.PROPERTY_SESSION_INTERVAL;
+import static org.jclouds.oauth.v2.JWSAlgorithms.NONE;
+import static org.jclouds.oauth.v2.config.OAuthProperties.JWS_ALG;
 
-import java.util.concurrent.TimeUnit;
+import java.security.PrivateKey;
 
-import org.jclouds.oauth.v2.domain.OAuthCredentials;
+import org.jclouds.http.HttpRequest;
 import org.jclouds.oauth.v2.domain.Token;
 import org.jclouds.oauth.v2.domain.TokenRequest;
 import org.jclouds.oauth.v2.filters.BearerTokenAuthenticator;
@@ -28,12 +31,12 @@ import 
org.jclouds.oauth.v2.filters.OAuthAuthenticationFilter;
 import org.jclouds.oauth.v2.filters.OAuthAuthenticator;
 import org.jclouds.oauth.v2.functions.BuildTokenRequest;
 import org.jclouds.oauth.v2.functions.FetchToken;
-import org.jclouds.oauth.v2.functions.OAuthCredentialsSupplier;
+import org.jclouds.oauth.v2.functions.PrivateKeySupplier;
 import org.jclouds.oauth.v2.functions.SignOrProduceMacForToken;
-import org.jclouds.rest.internal.GeneratedHttpRequest;
 
 import com.google.common.base.Function;
 import com.google.common.base.Supplier;
+import com.google.common.base.Suppliers;
 import com.google.common.cache.CacheBuilder;
 import com.google.common.cache.CacheLoader;
 import com.google.common.cache.LoadingCache;
@@ -48,11 +51,10 @@ import com.google.inject.name.Named;
 public class OAuthModule extends AbstractModule {
 
    @Override protected void configure() {
-      bind(new TypeLiteral<Function<byte[], byte[]>>() 
{}).to(SignOrProduceMacForToken.class);
       
bind(CredentialType.class).toProvider(CredentialTypeFromPropertyOrDefault.class);
-      bind(new TypeLiteral<Supplier<OAuthCredentials>>() 
{}).to(OAuthCredentialsSupplier.class);
-      bind(new TypeLiteral<Function<GeneratedHttpRequest, TokenRequest>>() 
{}).to(BuildTokenRequest.class);
+      bind(new TypeLiteral<Function<HttpRequest, TokenRequest>>() 
{}).to(BuildTokenRequest.class);
       bind(new TypeLiteral<Function<TokenRequest, Token>>() 
{}).to(FetchToken.class);
+      bind(new TypeLiteral<Supplier<PrivateKey>>() 
{}).annotatedWith(OAuth.class).to(PrivateKeySupplier.class);
    }
 
    /**
@@ -65,21 +67,34 @@ public class OAuthModule extends AbstractModule {
    @Provides
    @Singleton
    public LoadingCache<TokenRequest, Token> 
provideAccessCache(Function<TokenRequest, Token> getAccess,
-                                                               
@Named(PROPERTY_SESSION_INTERVAL) long
-                                                                       
sessionIntervalInSeconds) {
+                                                               
@Named(PROPERTY_SESSION_INTERVAL) long expirationSeconds) {
       // since the session interval is also the token expiration time 
requested to the server make the token expire a
       // bit before the deadline to make sure there aren't session expiration 
exceptions
-      sessionIntervalInSeconds = sessionIntervalInSeconds > 30 ? 
sessionIntervalInSeconds - 30 :
-              sessionIntervalInSeconds;
-      return 
CacheBuilder.newBuilder().expireAfterWrite(sessionIntervalInSeconds, 
TimeUnit.SECONDS).build(CacheLoader
-              .from(getAccess));
+      expirationSeconds = expirationSeconds > 30 ? expirationSeconds - 30 : 
expirationSeconds;
+      return CacheBuilder.newBuilder().expireAfterWrite(expirationSeconds, 
SECONDS).build(CacheLoader.from(getAccess));
+   }
+
+   /**
+    * Defers instantiation of {@linkplain SignOrProduceMacForToken} so as to 
avoid requiring private keys when the alg
+    * is set to {@linkplain org.jclouds.oauth.v2.JWSAlgorithms#NONE}.
+    */
+   @Provides @Singleton Supplier<Function<byte[], byte[]>> 
signOrProduceMacForToken(@Named(JWS_ALG) String jwsAlg,
+         Provider<SignOrProduceMacForToken> in) {
+      if (jwsAlg.equals(NONE)) { // Current implementation requires we return 
null on none.
+         return Suppliers.<Function<byte[], byte[]>>ofInstance(new 
Function<byte[], byte[]>() {
+            @Override public byte[] apply(byte[] input) {
+               return null;
+            }
+         });
+      }
+      return Suppliers.memoize(in.get());
    }
 
    @Singleton
    public static class CredentialTypeFromPropertyOrDefault implements 
Provider<CredentialType> {
       @Inject(optional = true)
       @Named(OAuthProperties.CREDENTIAL_TYPE)
-      String credentialType = 
CredentialType.SERVICE_ACCOUNT_CREDENTIALS.toString();
+      String credentialType = 
CredentialType.P12_PRIVATE_KEY_CREDENTIALS.toString();
 
       @Override
       public CredentialType get() {
@@ -93,7 +108,7 @@ public class OAuthModule extends AbstractModule {
                                                                              
OAuthAuthenticator serviceAccountAuth,
                                                                              
BearerTokenAuthenticator bearerTokenAuth) {
       switch (credentialType) {
-         case SERVICE_ACCOUNT_CREDENTIALS:
+         case P12_PRIVATE_KEY_CREDENTIALS:
             return serviceAccountAuth;
          case BEARER_TOKEN_CREDENTIALS:
             return bearerTokenAuth;

http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/6c839f13/oauth/src/main/java/org/jclouds/oauth/v2/config/OAuthProperties.java
----------------------------------------------------------------------
diff --git 
a/oauth/src/main/java/org/jclouds/oauth/v2/config/OAuthProperties.java 
b/oauth/src/main/java/org/jclouds/oauth/v2/config/OAuthProperties.java
index 9394cad..197bc31 100644
--- a/oauth/src/main/java/org/jclouds/oauth/v2/config/OAuthProperties.java
+++ b/oauth/src/main/java/org/jclouds/oauth/v2/config/OAuthProperties.java
@@ -16,17 +16,12 @@
  */
 package org.jclouds.oauth.v2.config;
 
-/**
- * Configurable properties for jclouds OAuth
- */
+import org.jclouds.oauth.v2.JWSAlgorithms;
+
 public class OAuthProperties {
 
-   /**
-    * The selected signature algorithm to use to sign the requests.
-    * <p/>
-    * This refers to the name the oauth provider expects, i.e., "RSA
-    */
-   public static final String SIGNATURE_OR_MAC_ALGORITHM = 
"jclouds.oauth.signature-or-mac-algorithm";
+   /** The JSON Web Signature alg, from the {@link 
JWSAlgorithms#supportedAlgs() supported list}. */
+   public static final String JWS_ALG = "jclouds.oauth.jws-alg";
 
    /**
     * The oauth audience, who this token is intended for. For instance in JWT 
and for
@@ -37,11 +32,6 @@ public class OAuthProperties {
    public static final String AUDIENCE = "jclouds.oauth.audience";
 
    /**
-    * Optional list of comma-separated scopes to use when no OAuthScopes 
annotation is present.
-    */
-   public static final String SCOPES = "jclouds.oauth.scopes";
-
-   /**
     * Specify if credentials are id + private key or if you are reusing an 
oauth2 token.
     *
     * @see org.jclouds.oauth.v2.config.CredentialType

http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/6c839f13/oauth/src/main/java/org/jclouds/oauth/v2/config/OAuthScopes.java
----------------------------------------------------------------------
diff --git a/oauth/src/main/java/org/jclouds/oauth/v2/config/OAuthScopes.java 
b/oauth/src/main/java/org/jclouds/oauth/v2/config/OAuthScopes.java
index 57ffd29..d4fe7d4 100644
--- a/oauth/src/main/java/org/jclouds/oauth/v2/config/OAuthScopes.java
+++ b/oauth/src/main/java/org/jclouds/oauth/v2/config/OAuthScopes.java
@@ -16,12 +16,13 @@
  */
 package org.jclouds.oauth.v2.config;
 
-import javax.inject.Qualifier;
 import java.lang.annotation.ElementType;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.lang.annotation.Target;
 
+import javax.inject.Qualifier;
+
 /**
  * Used to annotate REST methods/ifaces that use OAuthAuthentication.
  * <p/>

http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/6c839f13/oauth/src/main/java/org/jclouds/oauth/v2/domain/Header.java
----------------------------------------------------------------------
diff --git a/oauth/src/main/java/org/jclouds/oauth/v2/domain/Header.java 
b/oauth/src/main/java/org/jclouds/oauth/v2/domain/Header.java
index ea83a91..9cdd924 100644
--- a/oauth/src/main/java/org/jclouds/oauth/v2/domain/Header.java
+++ b/oauth/src/main/java/org/jclouds/oauth/v2/domain/Header.java
@@ -28,7 +28,7 @@ import com.google.auto.value.AutoValue;
 @AutoValue
 public abstract class Header {
 
-   /** The name of the algorithm used to compute the signature, e.g., {@code 
RS256}. */
+   /** The name of the algorithm used to compute the signature, e.g., {@code 
ES256}. */
    public abstract String signerAlgorithm();
 
    /** The type of the token, e.g., {@code JWT}. */

http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/6c839f13/oauth/src/main/java/org/jclouds/oauth/v2/domain/OAuthCredentials.java
----------------------------------------------------------------------
diff --git 
a/oauth/src/main/java/org/jclouds/oauth/v2/domain/OAuthCredentials.java 
b/oauth/src/main/java/org/jclouds/oauth/v2/domain/OAuthCredentials.java
deleted file mode 100644
index 78cb402..0000000
--- a/oauth/src/main/java/org/jclouds/oauth/v2/domain/OAuthCredentials.java
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * 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.jclouds.oauth.v2.domain;
-
-import com.google.common.base.Objects;
-import org.jclouds.domain.Credentials;
-
-import java.security.PrivateKey;
-
-import static com.google.common.base.Objects.equal;
-import static com.google.common.base.Objects.toStringHelper;
-import static com.google.common.base.Preconditions.checkNotNull;
-
-/**
- * Special kind credentials for oauth authentication that includes {@link 
java.security.PrivateKey} to sign
- * requests.
- */
-public class OAuthCredentials extends Credentials {
-
-   public static Builder builder() {
-      return new Builder();
-   }
-
-   public Builder toBuilder() {
-      return builder().fromOauthCredentials(this);
-   }
-
-   public static class Builder extends Credentials.Builder<OAuthCredentials> {
-
-      protected PrivateKey privateKey;
-
-      /**
-       * @see OAuthCredentials#privateKey
-       */
-      public Builder privateKey(PrivateKey privateKey) {
-         this.privateKey = checkNotNull(privateKey);
-         return this;
-      }
-
-      /**
-       * @see Credentials#identity
-       */
-      public Builder identity(String identity) {
-         this.identity = checkNotNull(identity);
-         return this;
-      }
-
-      /**
-       * @see Credentials#credential
-       */
-      public Builder credential(String credential) {
-         this.credential = credential;
-         return this;
-      }
-
-      public OAuthCredentials build() {
-         return new OAuthCredentials(checkNotNull(identity), credential, 
privateKey);
-      }
-
-      public Builder fromOauthCredentials(OAuthCredentials credentials) {
-         return new 
Builder().privateKey(credentials.privateKey).identity(credentials.identity)
-                 .credential(credentials.credential);
-      }
-   }
-
-   /**
-    * The private key associated with Credentials#identity.
-    * Used to sign token requests.
-    */
-   public final PrivateKey privateKey;
-
-   public OAuthCredentials(String identity, String credential, PrivateKey 
privateKey) {
-      super(identity, credential);
-      this.privateKey = privateKey;
-   }
-
-   /**
-    * {@inheritDoc}
-    */
-   @Override
-   public boolean equals(Object obj) {
-      if (this == obj)
-         return true;
-      if (obj == null)
-         return false;
-      if (getClass() != obj.getClass())
-         return false;
-      OAuthCredentials other = (OAuthCredentials) obj;
-      return equal(this.identity, other.identity) && equal(this.credential,
-              other.credential) && equal(this.privateKey,
-              other.privateKey);
-   }
-
-   /**
-    * {@inheritDoc}
-    */
-   @Override
-   public int hashCode() {
-      return Objects.hashCode(identity, credential, privateKey);
-   }
-
-   /**
-    * {@inheritDoc}
-    */
-   @Override
-   public String toString() {
-      return string().toString();
-   }
-
-   protected Objects.ToStringHelper string() {
-      return toStringHelper(this).omitNullValues().add("identity", identity)
-              .add("credential", credential != null ? credential.hashCode() : 
null).add("privateKey",
-                      privateKey.hashCode());
-   }
-}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/6c839f13/oauth/src/main/java/org/jclouds/oauth/v2/filters/BearerTokenAuthenticator.java
----------------------------------------------------------------------
diff --git 
a/oauth/src/main/java/org/jclouds/oauth/v2/filters/BearerTokenAuthenticator.java
 
b/oauth/src/main/java/org/jclouds/oauth/v2/filters/BearerTokenAuthenticator.java
index c5d944c..3d7d92d 100644
--- 
a/oauth/src/main/java/org/jclouds/oauth/v2/filters/BearerTokenAuthenticator.java
+++ 
b/oauth/src/main/java/org/jclouds/oauth/v2/filters/BearerTokenAuthenticator.java
@@ -20,16 +20,17 @@ import static java.lang.String.format;
 
 import javax.inject.Inject;
 
+import org.jclouds.domain.Credentials;
 import org.jclouds.http.HttpException;
 import org.jclouds.http.HttpRequest;
-import org.jclouds.oauth.v2.domain.OAuthCredentials;
+import org.jclouds.location.Provider;
 
 import com.google.common.base.Supplier;
 
 public final class BearerTokenAuthenticator implements 
OAuthAuthenticationFilter {
-   private final Supplier<OAuthCredentials> creds;
+   private final Supplier<Credentials> creds;
 
-   @Inject BearerTokenAuthenticator(Supplier<OAuthCredentials> creds) {
+   @Inject BearerTokenAuthenticator(@Provider Supplier<Credentials> creds) {
       this.creds = creds;
    }
 

http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/6c839f13/oauth/src/main/java/org/jclouds/oauth/v2/filters/OAuthAuthenticator.java
----------------------------------------------------------------------
diff --git 
a/oauth/src/main/java/org/jclouds/oauth/v2/filters/OAuthAuthenticator.java 
b/oauth/src/main/java/org/jclouds/oauth/v2/filters/OAuthAuthenticator.java
index 28a2c15..cb858b5 100644
--- a/oauth/src/main/java/org/jclouds/oauth/v2/filters/OAuthAuthenticator.java
+++ b/oauth/src/main/java/org/jclouds/oauth/v2/filters/OAuthAuthenticator.java
@@ -16,15 +16,12 @@
  */
 package org.jclouds.oauth.v2.filters;
 
-import static com.google.common.base.Preconditions.checkState;
-
 import javax.inject.Inject;
 
 import org.jclouds.http.HttpException;
 import org.jclouds.http.HttpRequest;
 import org.jclouds.oauth.v2.domain.Token;
 import org.jclouds.oauth.v2.domain.TokenRequest;
-import org.jclouds.rest.internal.GeneratedHttpRequest;
 
 import com.google.common.base.Function;
 import com.google.common.cache.LoadingCache;
@@ -36,21 +33,19 @@ import com.google.common.cache.LoadingCache;
  */
 public final class OAuthAuthenticator implements OAuthAuthenticationFilter {
 
-   private Function<GeneratedHttpRequest, TokenRequest> tokenRequestBuilder;
+   private Function<HttpRequest, TokenRequest> tokenRequestBuilder;
    private Function<TokenRequest, Token> tokenFetcher;
 
-   @Inject OAuthAuthenticator(Function<GeneratedHttpRequest, TokenRequest> 
tokenRequestBuilder,
+   @Inject OAuthAuthenticator(Function<HttpRequest, TokenRequest> 
tokenRequestBuilder,
          LoadingCache<TokenRequest, Token> tokenFetcher) {
       this.tokenRequestBuilder = tokenRequestBuilder;
       this.tokenFetcher = tokenFetcher;
    }
 
    @Override public HttpRequest filter(HttpRequest request) throws 
HttpException {
-      checkState(request instanceof GeneratedHttpRequest, "request must be an 
instance of GeneratedHttpRequest");
-      GeneratedHttpRequest generatedHttpRequest = 
GeneratedHttpRequest.class.cast(request);
-      TokenRequest tokenRequest = 
tokenRequestBuilder.apply(generatedHttpRequest);
+      TokenRequest tokenRequest = tokenRequestBuilder.apply(request);
       Token token = tokenFetcher.apply(tokenRequest);
-      return request.toBuilder().addHeader("Authorization", String.format("%s 
%s",
-              token.tokenType(), token.accessToken())).build();
+      String authorization = String.format("%s %s", token.tokenType(), 
token.accessToken());
+      return request.toBuilder().addHeader("Authorization", 
authorization).build();
    }
 }

http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/6c839f13/oauth/src/main/java/org/jclouds/oauth/v2/functions/BuildTokenRequest.java
----------------------------------------------------------------------
diff --git 
a/oauth/src/main/java/org/jclouds/oauth/v2/functions/BuildTokenRequest.java 
b/oauth/src/main/java/org/jclouds/oauth/v2/functions/BuildTokenRequest.java
index 7d94349..4a51954 100644
--- a/oauth/src/main/java/org/jclouds/oauth/v2/functions/BuildTokenRequest.java
+++ b/oauth/src/main/java/org/jclouds/oauth/v2/functions/BuildTokenRequest.java
@@ -17,21 +17,23 @@
 package org.jclouds.oauth.v2.functions;
 
 import static com.google.common.base.Preconditions.checkState;
-import static org.jclouds.oauth.v2.OAuthConstants.ADDITIONAL_CLAIMS;
+import static org.jclouds.Constants.PROPERTY_SESSION_INTERVAL;
 import static org.jclouds.oauth.v2.config.OAuthProperties.AUDIENCE;
-import static org.jclouds.oauth.v2.config.OAuthProperties.SCOPES;
-import static 
org.jclouds.oauth.v2.config.OAuthProperties.SIGNATURE_OR_MAC_ALGORITHM;
+import static org.jclouds.oauth.v2.config.OAuthProperties.JWS_ALG;
 import static org.jclouds.oauth.v2.domain.Claims.EXPIRATION_TIME;
 import static org.jclouds.oauth.v2.domain.Claims.ISSUED_AT;
 
-import java.util.Collections;
 import java.util.LinkedHashMap;
 import java.util.Map;
 
-import org.jclouds.Constants;
+import javax.inject.Inject;
+import javax.inject.Named;
+
+import org.jclouds.domain.Credentials;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.location.Provider;
 import org.jclouds.oauth.v2.config.OAuthScopes;
 import org.jclouds.oauth.v2.domain.Header;
-import org.jclouds.oauth.v2.domain.OAuthCredentials;
 import org.jclouds.oauth.v2.domain.TokenRequest;
 import org.jclouds.rest.internal.GeneratedHttpRequest;
 
@@ -39,83 +41,65 @@ import com.google.common.base.Function;
 import com.google.common.base.Joiner;
 import com.google.common.base.Supplier;
 import com.google.common.reflect.Invokable;
-import com.google.inject.Inject;
-import com.google.inject.name.Named;
-
-/**
- * The default authenticator.
- * <p/>
- * Builds the default token request with the following claims: 
iss,scope,aud,iat,exp.
- * <p/>
- * TODO scopes etc should come from the REST method and not from a global 
property
- */
-public final class BuildTokenRequest implements Function<GeneratedHttpRequest, 
TokenRequest> {
+
+/** Builds the default token request with the following claims: {@code 
iss,scope,aud,iat,exp}. */
+public class BuildTokenRequest implements Function<HttpRequest, TokenRequest> {
+   private static final Joiner ON_COMMA = Joiner.on(",");
+
    private final String assertionTargetDescription;
    private final String signatureAlgorithm;
-   private final Supplier<OAuthCredentials> credentialsSupplier;
+   private final Supplier<Credentials> credentialsSupplier;
    private final long tokenDuration;
 
-   @Inject(optional = true)
-   @Named(ADDITIONAL_CLAIMS)
-   private Map<String, String> additionalClaims = Collections.emptyMap();
-
-   @Inject(optional = true)
-   @Named(SCOPES)
-   private String globalScopes = null;
+   public static class TestBuildTokenRequest extends BuildTokenRequest {
+      @Inject TestBuildTokenRequest(@Named(AUDIENCE) String 
assertionTargetDescription,
+            @Named(JWS_ALG) String signatureAlgorithm, @Provider 
Supplier<Credentials> credentialsSupplier,
+            @Named(PROPERTY_SESSION_INTERVAL) long tokenDuration) {
+         super(assertionTargetDescription, signatureAlgorithm, 
credentialsSupplier, tokenDuration);
+      }
 
-   // injectable so expect tests can override with a predictable value
-   @Inject(optional = true)
-   private Supplier<Long> timeSourceMillisSinceEpoch = new Supplier<Long>() {
-      @Override
-      public Long get() {
-         return System.currentTimeMillis();
+      public long currentTimeSeconds() {
+         return 0;
       }
-   };
+   }
 
    @Inject BuildTokenRequest(@Named(AUDIENCE) String 
assertionTargetDescription,
-                            @Named(SIGNATURE_OR_MAC_ALGORITHM) String 
signatureAlgorithm,
-                            Supplier<OAuthCredentials> credentialsSupplier,
-                            @Named(Constants.PROPERTY_SESSION_INTERVAL) long 
tokenDuration) {
+         @Named(JWS_ALG) String signatureAlgorithm, @Provider 
Supplier<Credentials> credentialsSupplier,
+         @Named(PROPERTY_SESSION_INTERVAL) long tokenDuration) {
       this.assertionTargetDescription = assertionTargetDescription;
       this.signatureAlgorithm = signatureAlgorithm;
       this.credentialsSupplier = credentialsSupplier;
       this.tokenDuration = tokenDuration;
    }
 
-   @Override public TokenRequest apply(GeneratedHttpRequest request) {
-      long now = timeSourceMillisSinceEpoch.get() / 1000;
-
-      // fetch the token
+   @Override public TokenRequest apply(HttpRequest request) {
       Header header = Header.create(signatureAlgorithm, "JWT");
 
       Map<String, Object> claims = new LinkedHashMap<String, Object>();
       claims.put("iss", credentialsSupplier.get().identity);
-      claims.put("scope", getOAuthScopes(request));
+      claims.put("scope", getOAuthScopes((GeneratedHttpRequest) request));
       claims.put("aud", assertionTargetDescription);
+
+      long now = currentTimeSeconds();
       claims.put(EXPIRATION_TIME, now + tokenDuration);
       claims.put(ISSUED_AT, now);
-      claims.putAll(additionalClaims);
 
       return TokenRequest.create(header, claims);
    }
 
+   //TODO: Remove and switch to a request function.
    private String getOAuthScopes(GeneratedHttpRequest request) {
       Invokable<?, ?> invokable = request.getInvocation().getInvokable();
-      
       OAuthScopes classScopes = 
invokable.getOwnerType().getRawType().getAnnotation(OAuthScopes.class);
       OAuthScopes methodScopes = invokable.getAnnotation(OAuthScopes.class);
-
-      // if no annotations are present the rely on globally set scopes
-      if (classScopes == null && methodScopes == null) {
-         checkState(globalScopes != null, String.format("REST class or method 
should be annotated " +
-                 "with OAuthScopes specifying required permissions. 
Alternatively a global property " +
-                 "\"oauth.scopes\" may be set to define scopes globally. REST 
Class: %s, Method: %s",
-                 invokable.getOwnerType(),
-                 invokable.getName()));
-         return globalScopes;
-      }
-
+      checkState(classScopes != null || methodScopes != null, "Api interface 
or method should be annotated " //
+                  + "with OAuthScopes specifying required permissions. Api 
interface: %s, Method: %s", //
+            invokable.getOwnerType(), invokable.getName());
       OAuthScopes scopes = methodScopes != null ? methodScopes : classScopes;
-      return Joiner.on(",").join(scopes.value());
+      return ON_COMMA.join(scopes.value());
+   }
+
+   long currentTimeSeconds() {
+      return System.currentTimeMillis() / 1000;
    }
 }

http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/6c839f13/oauth/src/main/java/org/jclouds/oauth/v2/functions/OAuthCredentialsSupplier.java
----------------------------------------------------------------------
diff --git 
a/oauth/src/main/java/org/jclouds/oauth/v2/functions/OAuthCredentialsSupplier.java
 
b/oauth/src/main/java/org/jclouds/oauth/v2/functions/OAuthCredentialsSupplier.java
deleted file mode 100644
index 3ec907e..0000000
--- 
a/oauth/src/main/java/org/jclouds/oauth/v2/functions/OAuthCredentialsSupplier.java
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * 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.jclouds.oauth.v2.functions;
-
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.base.Throwables.propagate;
-import static java.lang.String.format;
-import static org.jclouds.crypto.Pems.privateKeySpec;
-import static org.jclouds.oauth.v2.OAuthConstants.NO_ALGORITHM;
-import static 
org.jclouds.oauth.v2.OAuthConstants.OAUTH_ALGORITHM_NAMES_TO_KEYFACTORY_ALGORITHM_NAMES;
-import static 
org.jclouds.oauth.v2.config.OAuthProperties.SIGNATURE_OR_MAC_ALGORITHM;
-import static org.jclouds.util.Throwables2.getFirstThrowableOfType;
-
-import java.io.IOException;
-import java.security.GeneralSecurityException;
-import java.security.KeyFactory;
-import java.security.PrivateKey;
-import javax.inject.Inject;
-import javax.inject.Named;
-import javax.inject.Singleton;
-
-import org.jclouds.domain.Credentials;
-import org.jclouds.location.Provider;
-import org.jclouds.oauth.v2.config.CredentialType;
-import org.jclouds.oauth.v2.domain.OAuthCredentials;
-import org.jclouds.rest.AuthorizationException;
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Charsets;
-import com.google.common.base.Supplier;
-import com.google.common.cache.CacheBuilder;
-import com.google.common.cache.CacheLoader;
-import com.google.common.cache.LoadingCache;
-import com.google.common.io.ByteSource;
-import com.google.common.util.concurrent.UncheckedExecutionException;
-
-/**
- * Loads {@link OAuthCredentials} from a pem private key using the KeyFactory 
obtained from the JWT Algorithm
- * Name<->KeyFactory name mapping in OAuthConstants. The pem pk algorithm must 
match the KeyFactory algorithm.
- *
- * @see 
org.jclouds.oauth.v2.OAuthConstants#OAUTH_ALGORITHM_NAMES_TO_KEYFACTORY_ALGORITHM_NAMES
- */
-@Singleton // due to cache
-public final class OAuthCredentialsSupplier implements 
Supplier<OAuthCredentials> {
-
-   private final Supplier<Credentials> creds;
-   private final LoadingCache<Credentials, OAuthCredentials> keyCache;
-
-   @Inject OAuthCredentialsSupplier(@Provider Supplier<Credentials> creds, 
OAuthCredentialsForCredentials loader,
-                                   @Named(SIGNATURE_OR_MAC_ALGORITHM) String 
signatureOrMacAlgorithm) {
-      this.creds = creds;
-      
checkArgument(OAUTH_ALGORITHM_NAMES_TO_KEYFACTORY_ALGORITHM_NAMES.containsKey(signatureOrMacAlgorithm),
-              format("No mapping for key factory for algorithm: %s", 
signatureOrMacAlgorithm));
-      // throw out the private key related to old credentials
-      this.keyCache = 
CacheBuilder.newBuilder().maximumSize(2).build(checkNotNull(loader, "loader"));
-   }
-
-   /**
-    * it is relatively expensive to extract a private key from a PEM. cache 
the relationship between current credentials
-    * so that the private key is only recalculated once.
-    */
-   @VisibleForTesting
-   static final class OAuthCredentialsForCredentials extends 
CacheLoader<Credentials, OAuthCredentials> {
-      private final String keyFactoryAlgorithm;
-      private final CredentialType credentialType;
-
-      @Inject 
OAuthCredentialsForCredentials(@Named(SIGNATURE_OR_MAC_ALGORITHM) String 
signatureOrMacAlgorithm,
-            CredentialType credentialType) {
-         this.keyFactoryAlgorithm = 
OAUTH_ALGORITHM_NAMES_TO_KEYFACTORY_ALGORITHM_NAMES.get(checkNotNull(
-                 signatureOrMacAlgorithm, "signatureOrMacAlgorithm"));
-         this.credentialType = credentialType;
-      }
-
-      @Override public OAuthCredentials load(Credentials in) {
-         try {
-            String identity = in.identity;
-            String privateKeyInPemFormat = in.credential;
-
-            // If passing Bearer tokens, simply create and pass it along
-            if (credentialType == CredentialType.BEARER_TOKEN_CREDENTIALS) {
-               return new 
OAuthCredentials.Builder().identity(identity).credential(in.credential).build();
-            }
-
-            if (keyFactoryAlgorithm.equals(NO_ALGORITHM)) {
-               return new 
OAuthCredentials.Builder().identity(identity).credential(privateKeyInPemFormat).build();
-            }
-            KeyFactory keyFactory = 
KeyFactory.getInstance(keyFactoryAlgorithm);
-            PrivateKey privateKey = 
keyFactory.generatePrivate(privateKeySpec(ByteSource.wrap(
-               privateKeyInPemFormat.getBytes(Charsets.UTF_8))));
-            return new 
OAuthCredentials.Builder().identity(identity).credential(privateKeyInPemFormat)
-                    .privateKey(privateKey).build();
-         } catch (IOException e) {
-            throw propagate(e);
-            // catch security exceptions InvalidKeySpecException and 
NoSuchAlgorithmException as GSE
-         } catch (GeneralSecurityException e) {
-            throw new AuthorizationException("security exception loading 
credentials. " + e.getMessage(), e);
-            // catch IAE that is thrown when parsing the pk fails
-         } catch (IllegalArgumentException e) {
-            throw new AuthorizationException("cannot parse pk. " + 
e.getMessage(), e);
-         }
-      }
-   }
-
-   @Override public OAuthCredentials get() {
-      try {
-         // loader always throws UncheckedExecutionException so no point in 
using get()
-         return keyCache.getUnchecked(checkNotNull(creds.get(), "credential 
supplier returned null"));
-      } catch (UncheckedExecutionException e) {
-         AuthorizationException authorizationException = 
getFirstThrowableOfType(e, AuthorizationException.class);
-         if (authorizationException != null) {
-            throw authorizationException;
-         }
-         throw e;
-      }
-   }
-}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/6c839f13/oauth/src/main/java/org/jclouds/oauth/v2/functions/PrivateKeySupplier.java
----------------------------------------------------------------------
diff --git 
a/oauth/src/main/java/org/jclouds/oauth/v2/functions/PrivateKeySupplier.java 
b/oauth/src/main/java/org/jclouds/oauth/v2/functions/PrivateKeySupplier.java
new file mode 100644
index 0000000..cbdad5e
--- /dev/null
+++ b/oauth/src/main/java/org/jclouds/oauth/v2/functions/PrivateKeySupplier.java
@@ -0,0 +1,105 @@
+/*
+ * 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.jclouds.oauth.v2.functions;
+
+import static com.google.common.base.Charsets.UTF_8;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Throwables.propagate;
+import static org.jclouds.crypto.Pems.privateKeySpec;
+import static org.jclouds.oauth.v2.config.OAuthProperties.JWS_ALG;
+import static org.jclouds.util.Throwables2.getFirstThrowableOfType;
+
+import java.io.IOException;
+import java.security.KeyFactory;
+import java.security.PrivateKey;
+import java.security.spec.InvalidKeySpecException;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+import org.jclouds.domain.Credentials;
+import org.jclouds.location.Provider;
+import org.jclouds.oauth.v2.JWSAlgorithms;
+import org.jclouds.rest.AuthorizationException;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Supplier;
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.CacheLoader;
+import com.google.common.cache.LoadingCache;
+import com.google.common.io.ByteSource;
+import com.google.common.util.concurrent.UncheckedExecutionException;
+
+/**
+ * Loads {@link PrivateKey} from a pem private key using the KeyFactory 
obtained vi {@link
+ * JWSAlgorithms#keyFactory(String)}. The pem pk algorithm must match the 
KeyFactory algorithm.
+ */
+@Singleton // due to cache
+public final class PrivateKeySupplier implements Supplier<PrivateKey> {
+
+   private final Supplier<Credentials> creds;
+   private final LoadingCache<Credentials, PrivateKey> keyCache;
+
+   @Inject PrivateKeySupplier(@Provider Supplier<Credentials> creds, 
PrivateKeyForCredentials loader) {
+      this.creds = creds;
+      // throw out the private key related to old credentials
+      this.keyCache = 
CacheBuilder.newBuilder().maximumSize(2).build(checkNotNull(loader, "loader"));
+   }
+
+   /**
+    * it is relatively expensive to extract a private key from a PEM. cache 
the relationship between current
+    * credentials
+    * so that the private key is only recalculated once.
+    */
+   @VisibleForTesting
+   static final class PrivateKeyForCredentials extends 
CacheLoader<Credentials, PrivateKey> {
+      private final String jwsAlg;
+
+      @Inject PrivateKeyForCredentials(@Named(JWS_ALG) String jwsAlg) {
+         this.jwsAlg = jwsAlg;
+      }
+
+      @Override public PrivateKey load(Credentials in) {
+         try {
+            String privateKeyInPemFormat = in.credential;
+            KeyFactory keyFactory = JWSAlgorithms.keyFactory(jwsAlg);
+            return 
keyFactory.generatePrivate(privateKeySpec(ByteSource.wrap(privateKeyInPemFormat.getBytes(UTF_8))));
+         } catch (IOException e) {
+            throw propagate(e);
+         } catch (InvalidKeySpecException e) {
+            throw new AuthorizationException("security exception loading 
credentials. " + e.getMessage(), e);
+            // catch IAE that is thrown when parsing the pk fails
+         } catch (IllegalArgumentException e) {
+            throw new AuthorizationException("cannot parse pk. " + 
e.getMessage(), e);
+         }
+      }
+   }
+
+   @Override public PrivateKey get() {
+      try {
+         // loader always throws UncheckedExecutionException so no point in 
using get()
+         return keyCache.getUnchecked(checkNotNull(creds.get(), "credential 
supplier returned null"));
+      } catch (UncheckedExecutionException e) {
+         AuthorizationException authorizationException = 
getFirstThrowableOfType(e, AuthorizationException.class);
+         if (authorizationException != null) {
+            throw authorizationException;
+         }
+         throw e;
+      }
+   }
+}

Reply via email to