You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@stratos.apache.org by ni...@apache.org on 2014/10/19 17:58:15 UTC
[09/17] Initial GCE commit
http://git-wip-us.apache.org/repos/asf/stratos/blob/4203d59b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/OAuthApi.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/OAuthApi.java b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/OAuthApi.java
new file mode 100644
index 0000000..12e8fcb
--- /dev/null
+++ b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/OAuthApi.java
@@ -0,0 +1,63 @@
+/*
+ * 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 java.io.Closeable;
+
+import javax.inject.Named;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.POST;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.oauth.v2.config.Authentication;
+import org.jclouds.oauth.v2.domain.Token;
+import org.jclouds.oauth.v2.domain.TokenRequest;
+import org.jclouds.oauth.v2.handlers.OAuthTokenBinder;
+import org.jclouds.rest.AuthorizationException;
+import org.jclouds.rest.annotations.BinderParam;
+import org.jclouds.rest.annotations.Endpoint;
+
+/**
+ * Provides access to OAuth via REST api.
+ * <p/>
+ * Usually this is not directly used by a client, which instead specifies
+ * OAuthAuthenticator as a request filter, which in turn uses this class to
+ * perform token requests.
+ *
+ * @see OAuthAsyncApi
+ */
+@Endpoint(Authentication.class)
+public interface OAuthApi extends Closeable {
+
+ /**
+ * Authenticates/Authorizes access to a resource defined in TokenRequest
+ * against an OAuth v2 authentication/authorization server.
+ *
+ * @param tokenRequest
+ * specified the principal and the required permissions
+ * @return a Token object with the token required to access the resource
+ * along with its expiration time
+ * @throws AuthorizationException
+ * if the principal cannot be authenticated or has no permissions
+ * for the specifed resources.
+ */
+ @Named("authenticate")
+ @POST
+ @Consumes(MediaType.APPLICATION_JSON)
+ Token authenticate(@BinderParam(OAuthTokenBinder.class) TokenRequest tokenRequest) throws AuthorizationException;
+
+}
http://git-wip-us.apache.org/repos/asf/stratos/blob/4203d59b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/OAuthApiMetadata.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/OAuthApiMetadata.java b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/OAuthApiMetadata.java
new file mode 100644
index 0000000..3ef26e6
--- /dev/null
+++ b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/OAuthApiMetadata.java
@@ -0,0 +1,80 @@
+/*
+ * 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 org.jclouds.Constants.PROPERTY_SESSION_INTERVAL;
+import static org.jclouds.oauth.v2.config.OAuthProperties.SIGNATURE_OR_MAC_ALGORITHM;
+
+import java.net.URI;
+import java.util.Properties;
+
+import org.jclouds.oauth.v2.config.OAuthHttpApiModule;
+import org.jclouds.oauth.v2.config.OAuthModule;
+import org.jclouds.rest.internal.BaseHttpApiMetadata;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.inject.Module;
+
+/**
+ * Implementation of {@link ApiMetadata} for OAuth 2 API
+ */
+public class OAuthApiMetadata extends BaseHttpApiMetadata<OAuthApi> {
+
+ @Override
+ public Builder toBuilder() {
+ return new Builder().fromApiMetadata(this);
+ }
+
+ public OAuthApiMetadata() {
+ this(new Builder());
+ }
+
+ protected OAuthApiMetadata(Builder builder) {
+ super(builder);
+ }
+
+ public static Properties defaultProperties() {
+ Properties properties = BaseHttpApiMetadata.defaultProperties();
+ properties.put(SIGNATURE_OR_MAC_ALGORITHM, "RS256");
+ properties.put(PROPERTY_SESSION_INTERVAL, 3600);
+ return properties;
+ }
+
+ public static class Builder extends BaseHttpApiMetadata.Builder<OAuthApi, Builder> {
+
+ protected Builder() {
+ id("oauth")
+ .name("OAuth API")
+ .identityName("service_account")
+ .credentialName("service_key")
+ .documentation(URI.create("TODO"))
+ .version("2")
+ .defaultProperties(OAuthApiMetadata.defaultProperties())
+ .defaultModules(ImmutableSet.<Class<? extends Module>>of(OAuthModule.class, OAuthHttpApiModule.class));
+ }
+
+ @Override
+ public OAuthApiMetadata build() {
+ return new OAuthApiMetadata(this);
+ }
+
+ @Override
+ protected Builder self() {
+ return this;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/stratos/blob/4203d59b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/OAuthConstants.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/OAuthConstants.java b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/OAuthConstants.java
new file mode 100644
index 0000000..9b140d4
--- /dev/null
+++ b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/OAuthConstants.java
@@ -0,0 +1,78 @@
+/*
+ * 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/stratos/blob/4203d59b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/config/Authentication.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/config/Authentication.java b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/config/Authentication.java
new file mode 100644
index 0000000..4f1107a
--- /dev/null
+++ b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/config/Authentication.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 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.OAuthAsyncApi
+ */
+@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/stratos/blob/4203d59b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/config/OAuthAuthenticationModule.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/config/OAuthAuthenticationModule.java b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/config/OAuthAuthenticationModule.java
new file mode 100644
index 0000000..fb2d413
--- /dev/null
+++ b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/config/OAuthAuthenticationModule.java
@@ -0,0 +1,52 @@
+/*
+ * 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 static org.jclouds.rest.config.BinderUtils.bindHttpApi;
+
+import java.net.URI;
+
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+import org.jclouds.oauth.v2.OAuthApi;
+
+import com.google.common.base.Supplier;
+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
+ protected void configure() {
+ 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) {
+ return Suppliers.ofInstance(URI.create(endpoint));
+ }
+}
http://git-wip-us.apache.org/repos/asf/stratos/blob/4203d59b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/config/OAuthHttpApiModule.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/config/OAuthHttpApiModule.java b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/config/OAuthHttpApiModule.java
new file mode 100644
index 0000000..6b4fdf9
--- /dev/null
+++ b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/config/OAuthHttpApiModule.java
@@ -0,0 +1,45 @@
+/*
+ * 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.net.URI;
+
+import javax.inject.Singleton;
+
+import org.jclouds.oauth.v2.OAuthApi;
+import org.jclouds.providers.ProviderMetadata;
+import org.jclouds.rest.ConfiguresHttpApi;
+import org.jclouds.rest.config.HttpApiModule;
+
+import com.google.common.base.Supplier;
+import com.google.common.base.Suppliers;
+import com.google.inject.Provides;
+
+/**
+ * OAuth module to when accessing OAuth stand-alone.
+ */
+@ConfiguresHttpApi
+public class OAuthHttpApiModule extends HttpApiModule<OAuthApi> {
+
+ @Provides
+ @Singleton
+ @Authentication
+ protected Supplier<URI> provideAuthenticationEndpoint(ProviderMetadata providerMetadata) {
+ return Suppliers.ofInstance(URI.create(providerMetadata.getEndpoint()));
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/stratos/blob/4203d59b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/config/OAuthModule.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/config/OAuthModule.java b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/config/OAuthModule.java
new file mode 100644
index 0000000..11fca2f
--- /dev/null
+++ b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/config/OAuthModule.java
@@ -0,0 +1,86 @@
+/*
+ * 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 com.google.common.base.Function;
+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.collect.ImmutableMap;
+import com.google.inject.AbstractModule;
+import com.google.inject.Provides;
+import com.google.inject.TypeLiteral;
+import org.jclouds.oauth.v2.domain.ClaimSet;
+import org.jclouds.oauth.v2.domain.Header;
+import org.jclouds.oauth.v2.domain.OAuthCredentials;
+import org.jclouds.oauth.v2.domain.Token;
+import org.jclouds.oauth.v2.domain.TokenRequest;
+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.SignOrProduceMacForToken;
+import org.jclouds.oauth.v2.json.ClaimSetTypeAdapter;
+import org.jclouds.oauth.v2.json.HeaderTypeAdapter;
+import org.jclouds.rest.internal.GeneratedHttpRequest;
+
+import javax.inject.Named;
+import javax.inject.Singleton;
+import java.lang.reflect.Type;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+import static org.jclouds.Constants.PROPERTY_SESSION_INTERVAL;
+
+/**
+ * Base OAuth module
+ */
+public class OAuthModule extends AbstractModule {
+
+
+ @Override
+ protected void configure() {
+ bind(new TypeLiteral<Function<byte[], byte[]>>() {}).to(SignOrProduceMacForToken.class);
+ bind(new TypeLiteral<Map<Type, Object>>() {}).toInstance(ImmutableMap.<Type, Object>of(
+ Header.class, new HeaderTypeAdapter(),
+ ClaimSet.class, new ClaimSetTypeAdapter()));
+ bind(new TypeLiteral<Supplier<OAuthCredentials>>() {}).to(OAuthCredentialsSupplier.class);
+ bind(new TypeLiteral<Function<GeneratedHttpRequest, TokenRequest>>() {}).to(BuildTokenRequest.class);
+ bind(new TypeLiteral<Function<TokenRequest, Token>>() {}).to(FetchToken.class);
+ }
+
+ /**
+ * Provides a cache for tokens. Cache is time based and by default expires after 59 minutes
+ * (the maximum time a token is valid is 60 minutes).
+ * This cache and expiry period is system-wide and does not attend to per-instance expiry time
+ * (e.g. "expires_in" from Google Compute -- which is set to the standard 3600 seconds).
+ */
+ // NB: If per-instance expiry time is required, significant refactoring will be needed.
+ @Provides
+ @Singleton
+ public LoadingCache<TokenRequest, Token> provideAccessCache(Function<TokenRequest, Token> getAccess,
+ @Named(PROPERTY_SESSION_INTERVAL) long
+ sessionIntervalInSeconds) {
+ // 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));
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/stratos/blob/4203d59b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/config/OAuthProperties.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/config/OAuthProperties.java b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/config/OAuthProperties.java
new file mode 100644
index 0000000..7b1bf17
--- /dev/null
+++ b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/config/OAuthProperties.java
@@ -0,0 +1,43 @@
+/*
+ * 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;
+
+/**
+ * Configurable properties for jclouds OAuth
+ */
+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 oauth audience, who this token is intended for. For instance in JWT and for
+ * google API's this property maps to: {"aud","https://accounts.google.com/o/oauth2/token"}
+ *
+ * @see <a href="http://tools.ietf.org/html/draft-jones-json-web-token-04">doc</a>
+ */
+ 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";
+}
http://git-wip-us.apache.org/repos/asf/stratos/blob/4203d59b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/config/OAuthScopes.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/config/OAuthScopes.java b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/config/OAuthScopes.java
new file mode 100644
index 0000000..57ffd29
--- /dev/null
+++ b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/config/OAuthScopes.java
@@ -0,0 +1,40 @@
+/*
+ * 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;
+
+/**
+ * Used to annotate REST methods/ifaces that use OAuthAuthentication.
+ * <p/>
+ * Sets the scopes for the token request for that particular method.
+ */
+@Retention(value = RetentionPolicy.RUNTIME)
+@Target(value = {ElementType.TYPE, ElementType.METHOD})
+@Qualifier
+public @interface OAuthScopes {
+
+ /**
+ * @return the OAuth scopes required to access the resource.
+ */
+ String[] value();
+
+}
http://git-wip-us.apache.org/repos/asf/stratos/blob/4203d59b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/domain/ClaimSet.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/domain/ClaimSet.java b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/domain/ClaimSet.java
new file mode 100644
index 0000000..5c0b348
--- /dev/null
+++ b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/domain/ClaimSet.java
@@ -0,0 +1,191 @@
+/*
+ * 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 com.google.common.base.Splitter;
+import com.google.common.collect.ForwardingMap;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Sets;
+
+import java.util.Map;
+import java.util.Set;
+
+import static com.google.common.base.Objects.ToStringHelper;
+import static com.google.common.base.Objects.equal;
+import static com.google.common.base.Objects.toStringHelper;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+
+/**
+ * The claimset for the token.
+ *
+ * @see <a
+ * href="https://developers.google.com/accounts/docs/OAuth2ServiceAccount"
+ * >doc</a>
+ */
+public class ClaimSet extends ForwardingMap<String, String> {
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public Builder toBuilder() {
+ return builder().fromClaimSet(this);
+ }
+
+ public static class Builder {
+
+ private Set<String> requiredClaims;
+ private ImmutableMap.Builder<String, String> claims = new ImmutableMap.Builder<String, String>();
+ private long emissionTime;
+ private long expirationTime;
+
+ public Builder() {
+ this(ImmutableSet.<String>of());
+ }
+
+ /**
+ * Constructor that allows to predefine a mandatory set of claims as a comma-separated string, e.g, "iss,iat".
+ */
+ public Builder(String commaSeparatedRequiredClaims) {
+ this(ImmutableSet.copyOf(Splitter.on(",").split(checkNotNull(commaSeparatedRequiredClaims))));
+ }
+
+ /**
+ * Constructor that allows to predefine a mandatory set of claims as a set of strings.
+ */
+ public Builder(Set<String> requiredClaims) {
+ this.requiredClaims = ImmutableSet.copyOf(checkNotNull(requiredClaims));
+ }
+
+ /**
+ * Adds a Claim, i.e. key/value pair, e.g., "scope":"all_permissions".
+ */
+ public Builder addClaim(String name, String value) {
+ claims.put(checkNotNull(name), checkNotNull(value, "value of %s", name));
+ return this;
+ }
+
+ /**
+ * @see ClaimSet#getEmissionTime()
+ */
+ public Builder emissionTime(long emmissionTime) {
+ this.emissionTime = emmissionTime;
+ return this;
+ }
+
+ /**
+ * @see ClaimSet#getExpirationTime()
+ */
+ public Builder expirationTime(long expirationTime) {
+ this.expirationTime = expirationTime;
+ return this;
+ }
+
+ /**
+ * Adds a map containing multiple claims
+ */
+ public Builder addAllClaims(Map<String, String> claims) {
+ this.claims.putAll(checkNotNull(claims));
+ return this;
+ }
+
+ public ClaimSet build() {
+ Map<String, String> claimsMap = claims.build();
+ checkState(Sets.intersection(claimsMap.keySet(), requiredClaims).size() == requiredClaims.size(),
+ "not all required claims were present");
+ if (expirationTime == 0) {
+ expirationTime = emissionTime + 3600;
+ }
+ return new ClaimSet(claimsMap, emissionTime, expirationTime);
+ }
+
+ public Builder fromClaimSet(ClaimSet claimSet) {
+ return new Builder().addAllClaims(claimSet.claims).expirationTime(expirationTime).emissionTime(emissionTime);
+ }
+ }
+
+ private final Map<String, String> claims;
+ private final long emissionTime;
+ private final long expirationTime;
+
+ private ClaimSet(Map<String, String> claims, long emissionTime, long expirationTime) {
+ this.claims = claims;
+ this.emissionTime = emissionTime;
+ this.expirationTime = expirationTime;
+ }
+
+ /**
+ * The emission time, in seconds since the epoch.
+ */
+ public long getEmissionTime() {
+ return emissionTime;
+ }
+
+ /**
+ * The expiration time, in seconds since the emission time.
+ */
+ public long getExpirationTime() {
+ return expirationTime;
+ }
+
+ /**
+ * @returns the claims.
+ */
+ @Override
+ protected Map<String, String> delegate() {
+ return claims;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(claims);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ ClaimSet other = (ClaimSet) obj;
+ return equal(claims, other.claims);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String toString() {
+ return string().toString();
+ }
+
+ protected ToStringHelper string() {
+ return toStringHelper(this).omitNullValues().add("claims", claims)
+ .add("emissionTime", emissionTime).add("expirationTIme", expirationTime);
+ }
+}
http://git-wip-us.apache.org/repos/asf/stratos/blob/4203d59b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/domain/Header.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/domain/Header.java b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/domain/Header.java
new file mode 100644
index 0000000..c230e1d
--- /dev/null
+++ b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/domain/Header.java
@@ -0,0 +1,128 @@
+/*
+ * 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 static com.google.common.base.Objects.equal;
+import static com.google.common.base.Objects.toStringHelper;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * The header for the OAuth token, contains the signer algorithm's name and the type of the token
+ *
+ * @see <a href="https://developers.google.com/accounts/docs/OAuth2ServiceAccount">doc</a>
+ */
+public class Header {
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public Builder toBuilder() {
+ return builder().fromHeader(this);
+ }
+
+ public static class Builder {
+
+ private String signerAlgorithm;
+ private String type;
+
+ /**
+ * @see Header#getSignerAlgorithm()
+ */
+ public Builder signerAlgorithm(String signerAlgorithm) {
+ this.signerAlgorithm = checkNotNull(signerAlgorithm);
+ return this;
+ }
+
+ /**
+ * @see Header#getType()
+ */
+ public Builder type(String type) {
+ this.type = checkNotNull(type);
+ return this;
+ }
+
+ public Header build() {
+ return new Header(signerAlgorithm, type);
+ }
+
+ public Builder fromHeader(Header header) {
+ return new Builder().signerAlgorithm(header.signerAlgorithm).type(header.type);
+ }
+ }
+
+ private final String signerAlgorithm;
+ private final String type;
+
+ protected Header(String signerAlgorithm, String type) {
+ this.signerAlgorithm = checkNotNull(signerAlgorithm);
+ this.type = checkNotNull(type);
+ }
+
+ /**
+ * The name of the algorithm used to compute the signature, e.g., "RS256"
+ */
+ public String getSignerAlgorithm() {
+ return signerAlgorithm;
+ }
+
+ /**
+ * The type of the token, e.g., "JWT"
+ */
+ public String getType() {
+ return type;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ Header other = (Header) obj;
+ return equal(this.signerAlgorithm, other.signerAlgorithm) && equal(this.type,
+ other.type);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(signerAlgorithm, type);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String toString() {
+ return string().toString();
+ }
+
+ protected Objects.ToStringHelper string() {
+ return toStringHelper(this).omitNullValues().add("signerAlgorithm", signerAlgorithm)
+ .add("type", type);
+ }
+}
http://git-wip-us.apache.org/repos/asf/stratos/blob/4203d59b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/domain/OAuthCredentials.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/domain/OAuthCredentials.java b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/domain/OAuthCredentials.java
new file mode 100644
index 0000000..78cb402
--- /dev/null
+++ b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/domain/OAuthCredentials.java
@@ -0,0 +1,129 @@
+/*
+ * 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/stratos/blob/4203d59b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/domain/Token.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/domain/Token.java b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/domain/Token.java
new file mode 100644
index 0000000..a18a7eb
--- /dev/null
+++ b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/domain/Token.java
@@ -0,0 +1,149 @@
+/*
+ * 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 java.beans.ConstructorProperties;
+
+import static com.google.common.base.Objects.equal;
+import static com.google.common.base.Objects.toStringHelper;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * The oauth token, obtained upon a successful token request and ready to embed in requests.
+ */
+public class Token {
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public Builder toBuilder() {
+ return builder().fromToken(this);
+ }
+
+ public static class Builder {
+
+ private String accessToken;
+ private String tokenType;
+ private long expiresIn;
+
+ /**
+ * @see Token#getAccessToken()
+ */
+ public Builder accessToken(String accessToken) {
+ this.accessToken = checkNotNull(accessToken);
+ return this;
+ }
+
+ /**
+ * @see Token#getTokenType()
+ */
+ public Builder tokenType(String tokenType) {
+ this.tokenType = checkNotNull(tokenType);
+ return this;
+ }
+
+ /**
+ * @see Token#getExpiresIn()
+ */
+ public Builder expiresIn(long expiresIn) {
+ this.expiresIn = expiresIn;
+ return this;
+ }
+
+ public Token build() {
+ return new Token(accessToken, tokenType, expiresIn);
+ }
+
+ public Builder fromToken(Token token) {
+ return new Builder().accessToken(token.accessToken).tokenType(token.tokenType).expiresIn(token.expiresIn);
+ }
+ }
+
+ private final String accessToken;
+ private final String tokenType;
+ private final long expiresIn;
+
+ @ConstructorProperties({"access_token", "token_type", "expires_in"})
+ protected Token(String accessToken, String tokenType, long expiresIn) {
+ this.accessToken = accessToken;
+ this.tokenType = tokenType;
+ this.expiresIn = expiresIn;
+ }
+
+ /**
+ * The access token obtained from the OAuth server.
+ */
+ public String getAccessToken() {
+ return accessToken;
+ }
+
+ /**
+ * The type of the token, e.g., "Bearer"
+ */
+ public String getTokenType() {
+ return tokenType;
+ }
+
+ /**
+ * In how many seconds this token expires.
+ */
+ public long getExpiresIn() {
+ return expiresIn;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ Token other = (Token) obj;
+ return equal(this.accessToken, other.accessToken) && equal(this.tokenType,
+ other.tokenType) && equal(this.expiresIn,
+ other.expiresIn);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(accessToken, tokenType, expiresIn);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String toString() {
+ return string().toString();
+ }
+
+ protected Objects.ToStringHelper string() {
+ return toStringHelper(this).omitNullValues().add("accessToken", accessToken)
+ .add("tokenType", tokenType).add("expiresIn", expiresIn);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/stratos/blob/4203d59b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/domain/TokenRequest.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/domain/TokenRequest.java b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/domain/TokenRequest.java
new file mode 100644
index 0000000..7d1a6a4
--- /dev/null
+++ b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/domain/TokenRequest.java
@@ -0,0 +1,131 @@
+/*
+ * 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 static com.google.common.base.Objects.equal;
+import static com.google.common.base.Objects.toStringHelper;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * A complete token request.
+ */
+public class TokenRequest {
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public Builder toBuilder() {
+ return builder().fromTokenRequest(this);
+ }
+
+ public static class Builder {
+ private Header header;
+ private ClaimSet claimSet;
+
+ /**
+ * @see TokenRequest#getClaimSet()
+ */
+ public Builder header(Header header) {
+ this.header = header;
+ return this;
+ }
+
+ /**
+ * @see TokenRequest#getHeader()
+ */
+ public Builder claimSet(ClaimSet claimSet) {
+ this.claimSet = claimSet;
+ return this;
+ }
+
+ public TokenRequest build() {
+ return new TokenRequest(header, claimSet);
+ }
+
+ public Builder fromTokenRequest(TokenRequest tokeRequest) {
+ return new Builder().header(tokeRequest.header).claimSet(tokeRequest.claimSet);
+ }
+ }
+
+ private final Header header;
+ private final ClaimSet claimSet;
+
+ public TokenRequest(Header header, ClaimSet claimSet) {
+ this.header = checkNotNull(header);
+ this.claimSet = checkNotNull(claimSet);
+ }
+
+ /**
+ * The header of this token request.
+ *
+ * @see Header
+ */
+ public Header getHeader() {
+ return header;
+ }
+
+ /**
+ * The claim set of this token request.
+ *
+ * @see ClaimSet
+ */
+ public ClaimSet getClaimSet() {
+ return claimSet;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ TokenRequest other = (TokenRequest) obj;
+ return equal(this.header, other.header) && equal(this.claimSet,
+ other.claimSet);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(header, claimSet);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String toString() {
+ return string().toString();
+ }
+
+ protected Objects.ToStringHelper string() {
+ return toStringHelper(this).omitNullValues().add("header", header)
+ .add("claimSet", claimSet);
+ }
+
+
+}
http://git-wip-us.apache.org/repos/asf/stratos/blob/4203d59b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/domain/TokenRequestFormat.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/domain/TokenRequestFormat.java b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/domain/TokenRequestFormat.java
new file mode 100644
index 0000000..f4b80c1
--- /dev/null
+++ b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/domain/TokenRequestFormat.java
@@ -0,0 +1,45 @@
+/*
+ * 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.inject.ImplementedBy;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.oauth.v2.json.JWTTokenRequestFormat;
+
+import java.util.Set;
+
+/**
+ * Transforms a TokenRequest into a specific format (e.g. JWT token)
+ */
+@ImplementedBy(JWTTokenRequestFormat.class)
+public interface TokenRequestFormat {
+
+ /**
+ * Transforms the provided HttpRequest into a particular token request with a specific format.
+ */
+ <R extends HttpRequest> R formatRequest(R httpRequest, TokenRequest tokenRequest);
+
+ /**
+ * The name of the type of the token request, e.g., "JWT"
+ */
+ String getTypeName();
+
+ /**
+ * The claims that must be present in the token request for it to be valid.
+ */
+ Set<String> requiredClaims();
+}
http://git-wip-us.apache.org/repos/asf/stratos/blob/4203d59b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/filters/OAuthAuthenticator.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/filters/OAuthAuthenticator.java b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/filters/OAuthAuthenticator.java
new file mode 100644
index 0000000..e25bc20
--- /dev/null
+++ b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/filters/OAuthAuthenticator.java
@@ -0,0 +1,63 @@
+/*
+ * 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.filters;
+
+import com.google.common.base.Function;
+import com.google.common.cache.LoadingCache;
+import org.jclouds.http.HttpException;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.HttpRequestFilter;
+import org.jclouds.oauth.v2.domain.Token;
+import org.jclouds.oauth.v2.domain.TokenRequest;
+import org.jclouds.rest.internal.GeneratedHttpRequest;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import static com.google.common.base.Preconditions.checkState;
+
+/**
+ * To be used by client applications to embed an OAuth authentication in their REST requests.
+ * <p/>
+ * TODO when we're able to use the OAuthAuthentication an this should be used automatically
+ */
+@Singleton
+public class OAuthAuthenticator implements HttpRequestFilter {
+
+ private Function<GeneratedHttpRequest, TokenRequest> tokenRequestBuilder;
+ private Function<TokenRequest, Token> tokenFetcher;
+
+ @Inject
+ OAuthAuthenticator(Function<GeneratedHttpRequest, 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);
+ Token token = tokenFetcher.apply(tokenRequest);
+ return request.toBuilder().addHeader("Authorization", String.format("%s %s",
+ token.getTokenType(), token.getAccessToken())).build();
+
+ }
+
+
+}
http://git-wip-us.apache.org/repos/asf/stratos/blob/4203d59b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/functions/BuildTokenRequest.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/functions/BuildTokenRequest.java b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/functions/BuildTokenRequest.java
new file mode 100644
index 0000000..7b869dc
--- /dev/null
+++ b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/functions/BuildTokenRequest.java
@@ -0,0 +1,135 @@
+/*
+ * 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.checkState;
+import static org.jclouds.oauth.v2.OAuthConstants.ADDITIONAL_CLAIMS;
+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 java.util.Map;
+
+import javax.inject.Singleton;
+
+import org.jclouds.Constants;
+import org.jclouds.oauth.v2.config.OAuthScopes;
+import org.jclouds.oauth.v2.domain.ClaimSet;
+import org.jclouds.oauth.v2.domain.Header;
+import org.jclouds.oauth.v2.domain.OAuthCredentials;
+import org.jclouds.oauth.v2.domain.TokenRequest;
+import org.jclouds.oauth.v2.domain.TokenRequestFormat;
+import org.jclouds.rest.internal.GeneratedHttpRequest;
+
+import com.google.common.base.Function;
+import com.google.common.base.Joiner;
+import com.google.common.base.Supplier;
+import com.google.common.collect.ImmutableMap;
+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
+ */
+@Singleton
+public class BuildTokenRequest implements Function<GeneratedHttpRequest, TokenRequest> {
+
+ private final String assertionTargetDescription;
+ private final String signatureAlgorithm;
+ private final TokenRequestFormat tokenRequestFormat;
+ private final Supplier<OAuthCredentials> credentialsSupplier;
+ private final long tokenDuration;
+
+ @Inject(optional = true)
+ @Named(ADDITIONAL_CLAIMS)
+ protected Map<String, String> additionalClaims = ImmutableMap.of();
+
+ @Inject(optional = true)
+ @Named(SCOPES)
+ protected String globalScopes = null;
+
+ // injectable so expect tests can override with a predictable value
+ @Inject(optional = true)
+ protected Supplier<Long> timeSourceMillisSinceEpoch = new Supplier<Long>() {
+ @Override
+ public Long get() {
+ return System.currentTimeMillis();
+ }
+ };
+
+ @Inject
+ public BuildTokenRequest(@Named(AUDIENCE) String assertionTargetDescription,
+ @Named(SIGNATURE_OR_MAC_ALGORITHM) String signatureAlgorithm,
+ TokenRequestFormat tokenRequestFormat, Supplier<OAuthCredentials> credentialsSupplier,
+ @Named(Constants.PROPERTY_SESSION_INTERVAL) long tokenDuration) {
+ this.assertionTargetDescription = assertionTargetDescription;
+ this.signatureAlgorithm = signatureAlgorithm;
+ this.tokenRequestFormat = tokenRequestFormat;
+ this.credentialsSupplier = credentialsSupplier;
+ this.tokenDuration = tokenDuration;
+ }
+
+ @Override
+ public TokenRequest apply(GeneratedHttpRequest request) {
+ long now = timeSourceMillisSinceEpoch.get() / 1000;
+
+ // fetch the token
+ Header header = new Header.Builder()
+ .signerAlgorithm(signatureAlgorithm)
+ .type(tokenRequestFormat.getTypeName())
+ .build();
+
+ ClaimSet claimSet = new ClaimSet.Builder(this.tokenRequestFormat.requiredClaims())
+ .addClaim("iss", credentialsSupplier.get().identity)
+ .addClaim("scope", getOAuthScopes(request))
+ .addClaim("aud", assertionTargetDescription)
+ .emissionTime(now)
+ .expirationTime(now + tokenDuration)
+ .addAllClaims(additionalClaims)
+ .build();
+
+ return new TokenRequest.Builder()
+ .header(header)
+ .claimSet(claimSet)
+ .build();
+ }
+
+ protected 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;
+ }
+
+ OAuthScopes scopes = methodScopes != null ? methodScopes : classScopes;
+ return Joiner.on(",").join(scopes.value());
+ }
+}
http://git-wip-us.apache.org/repos/asf/stratos/blob/4203d59b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/functions/FetchToken.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/functions/FetchToken.java b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/functions/FetchToken.java
new file mode 100644
index 0000000..593c885
--- /dev/null
+++ b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/functions/FetchToken.java
@@ -0,0 +1,41 @@
+/*
+ * 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 com.google.common.base.Function;
+import org.jclouds.oauth.v2.OAuthApi;
+import org.jclouds.oauth.v2.domain.Token;
+import org.jclouds.oauth.v2.domain.TokenRequest;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+@Singleton
+public class FetchToken implements Function<TokenRequest, Token> {
+
+ private OAuthApi oAuthApi;
+
+ @Inject
+ public FetchToken(OAuthApi oAuthApi) {
+ this.oAuthApi = oAuthApi;
+ }
+
+ @Override
+ public Token apply(TokenRequest input) {
+ return this.oAuthApi.authenticate(input);
+ }
+}
http://git-wip-us.apache.org/repos/asf/stratos/blob/4203d59b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/functions/OAuthCredentialsSupplier.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/functions/OAuthCredentialsSupplier.java b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/functions/OAuthCredentialsSupplier.java
new file mode 100644
index 0000000..45620c0
--- /dev/null
+++ b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/functions/OAuthCredentialsSupplier.java
@@ -0,0 +1,125 @@
+/*
+ * 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 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;
+import org.jclouds.domain.Credentials;
+import org.jclouds.location.Provider;
+import org.jclouds.oauth.v2.domain.OAuthCredentials;
+import org.jclouds.rest.AuthorizationException;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Singleton;
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+import java.security.KeyFactory;
+import java.security.PrivateKey;
+
+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;
+
+/**
+ * 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
+public class OAuthCredentialsSupplier implements Supplier<OAuthCredentials> {
+
+ private final Supplier<Credentials> creds;
+ private final LoadingCache<Credentials, OAuthCredentials> keyCache;
+
+ @Inject
+ public 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 class OAuthCredentialsForCredentials extends CacheLoader<Credentials, OAuthCredentials> {
+ private final String keyFactoryAlgorithm;
+
+ @Inject
+ public OAuthCredentialsForCredentials(@Named(SIGNATURE_OR_MAC_ALGORITHM) String signatureOrMacAlgorithm) {
+ this.keyFactoryAlgorithm = OAUTH_ALGORITHM_NAMES_TO_KEYFACTORY_ALGORITHM_NAMES.get(checkNotNull(
+ signatureOrMacAlgorithm, "signatureOrMacAlgorithm"));
+ }
+
+ @Override
+ public OAuthCredentials load(Credentials in) {
+ try {
+ String identity = in.identity;
+ String privateKeyInPemFormat = in.credential;
+ 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) {
+ Throwable authorizationException = getFirstThrowableOfType(e, AuthorizationException.class);
+ if (authorizationException != null) {
+ throw (AuthorizationException) authorizationException;
+ }
+ throw propagate(e);
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/stratos/blob/4203d59b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/functions/SignOrProduceMacForToken.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/functions/SignOrProduceMacForToken.java b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/functions/SignOrProduceMacForToken.java
new file mode 100644
index 0000000..471812a
--- /dev/null
+++ b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/functions/SignOrProduceMacForToken.java
@@ -0,0 +1,119 @@
+/*
+ * 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 com.google.common.base.Function;
+import com.google.common.base.Supplier;
+import com.google.common.base.Throwables;
+import org.jclouds.oauth.v2.domain.OAuthCredentials;
+
+import javax.annotation.PostConstruct;
+import javax.crypto.Mac;
+import javax.inject.Inject;
+import javax.inject.Named;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.Signature;
+import java.security.SignatureException;
+
+import static com.google.common.base.Preconditions.checkState;
+import static java.lang.String.format;
+import static org.jclouds.oauth.v2.OAuthConstants.NO_ALGORITHM;
+import static org.jclouds.oauth.v2.OAuthConstants.OAUTH_ALGORITHM_NAMES_TO_SIGNATURE_ALGORITHM_NAMES;
+import static org.jclouds.oauth.v2.config.OAuthProperties.SIGNATURE_OR_MAC_ALGORITHM;
+
+/**
+ * Function that signs/produces mac's for OAuth tokens, provided a {@link Signature} or a {@link Mac} algorithm and
+ * {@link PrivateKey}
+ */
+public class SignOrProduceMacForToken implements Function<byte[], byte[]> {
+
+ private final Supplier<OAuthCredentials> credentials;
+ private final String signatureOrMacAlgorithm;
+ private Function<byte[], byte[]> signatureOrMacFunction;
+
+
+ @Inject
+ public SignOrProduceMacForToken(@Named(SIGNATURE_OR_MAC_ALGORITHM) String signatureOrMacAlgorithm,
+ Supplier<OAuthCredentials> credentials) {
+ checkState(OAUTH_ALGORITHM_NAMES_TO_SIGNATURE_ALGORITHM_NAMES.containsKey(signatureOrMacAlgorithm),
+ format("the signature algorithm %s is not supported", signatureOrMacAlgorithm));
+ this.signatureOrMacAlgorithm = OAUTH_ALGORITHM_NAMES_TO_SIGNATURE_ALGORITHM_NAMES.get(signatureOrMacAlgorithm);
+ this.credentials = credentials;
+ }
+
+ @PostConstruct
+ public void loadSignatureOrMacOrNone() throws InvalidKeyException, NoSuchAlgorithmException {
+ if (signatureOrMacAlgorithm.equals(NO_ALGORITHM)) {
+ this.signatureOrMacFunction = new Function<byte[], byte[]>() {
+ @Override
+ public byte[] apply(byte[] input) {
+ return null;
+ }
+ };
+ } else if (signatureOrMacAlgorithm.startsWith("SHA")) {
+ this.signatureOrMacFunction = new SignatureGenerator(signatureOrMacAlgorithm, credentials.get().privateKey);
+ } else {
+ this.signatureOrMacFunction = new MessageAuthenticationCodeGenerator(signatureOrMacAlgorithm,
+ credentials.get().privateKey);
+ }
+ }
+
+ @Override
+ public byte[] apply(byte[] input) {
+ return signatureOrMacFunction.apply(input);
+ }
+
+ private static class MessageAuthenticationCodeGenerator implements Function<byte[], byte[]> {
+
+ private Mac mac;
+
+ private MessageAuthenticationCodeGenerator(String macAlgorithm, PrivateKey privateKey) throws
+ NoSuchAlgorithmException, InvalidKeyException {
+ this.mac = Mac.getInstance(macAlgorithm);
+ this.mac.init(privateKey);
+ }
+
+ @Override
+ public byte[] apply(byte[] input) {
+ this.mac.update(input);
+ return this.mac.doFinal();
+ }
+ }
+
+ private static class SignatureGenerator implements Function<byte[], byte[]> {
+
+ private Signature signature;
+
+ private SignatureGenerator(String signatureAlgorithm, PrivateKey privateKey) throws NoSuchAlgorithmException,
+ InvalidKeyException {
+ this.signature = Signature.getInstance(signatureAlgorithm);
+ this.signature.initSign(privateKey);
+ }
+
+ @Override
+ public byte[] apply(byte[] input) {
+ try {
+ signature.update(input);
+ return signature.sign();
+ } catch (SignatureException e) {
+ throw Throwables.propagate(e);
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/stratos/blob/4203d59b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/handlers/OAuthErrorHandler.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/handlers/OAuthErrorHandler.java b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/handlers/OAuthErrorHandler.java
new file mode 100644
index 0000000..78d7844
--- /dev/null
+++ b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/handlers/OAuthErrorHandler.java
@@ -0,0 +1,64 @@
+/*
+ * 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.handlers;
+
+import org.jclouds.http.HttpCommand;
+import org.jclouds.http.HttpErrorHandler;
+import org.jclouds.http.HttpResponse;
+import org.jclouds.http.HttpResponseException;
+import org.jclouds.rest.AuthorizationException;
+import org.jclouds.rest.ResourceNotFoundException;
+
+import javax.inject.Singleton;
+
+import static javax.ws.rs.core.Response.Status;
+import static org.jclouds.http.HttpUtils.closeClientButKeepContentStream;
+
+/**
+ * This will parse and set an appropriate exception on the command object.
+ */
+@Singleton
+public class OAuthErrorHandler implements HttpErrorHandler {
+ public void handleError(HttpCommand command, HttpResponse response) {
+ // it is important to always read fully and close streams
+ byte[] data = closeClientButKeepContentStream(response);
+ String message = data != null ? new String(data) : null;
+
+ Exception exception = message != null ? new HttpResponseException(command, response, message)
+ : new HttpResponseException(command, response);
+ message = message != null ? message : String.format("%s -> %s", command.getCurrentRequest().getRequestLine(),
+ response.getStatusLine());
+ Status status = Status.fromStatusCode(response.getStatusCode());
+ switch (status) {
+ case BAD_REQUEST:
+ break;
+ case UNAUTHORIZED:
+ case FORBIDDEN:
+ exception = new AuthorizationException(message, exception);
+ break;
+ case NOT_FOUND:
+ if (!command.getCurrentRequest().getMethod().equals("DELETE")) {
+ exception = new ResourceNotFoundException(message, exception);
+ }
+ break;
+ case CONFLICT:
+ exception = new IllegalStateException(message, exception);
+ break;
+ }
+ command.setException(exception);
+ }
+}
http://git-wip-us.apache.org/repos/asf/stratos/blob/4203d59b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/handlers/OAuthTokenBinder.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/handlers/OAuthTokenBinder.java b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/handlers/OAuthTokenBinder.java
new file mode 100644
index 0000000..1030804
--- /dev/null
+++ b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/handlers/OAuthTokenBinder.java
@@ -0,0 +1,45 @@
+/*
+ * 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.handlers;
+
+import org.jclouds.http.HttpRequest;
+import org.jclouds.oauth.v2.domain.TokenRequest;
+import org.jclouds.oauth.v2.domain.TokenRequestFormat;
+import org.jclouds.rest.Binder;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+/**
+ * Generic implementation of a token binder. Uses a provided {@link TokenRequestFormat} to actually bind tokens to
+ * requests.
+ */
+@Singleton
+public class OAuthTokenBinder implements Binder {
+
+ private final TokenRequestFormat tokenRequestFormat;
+
+ @Inject
+ OAuthTokenBinder(TokenRequestFormat tokenRequestFormat) {
+ this.tokenRequestFormat = tokenRequestFormat;
+ }
+
+ @Override
+ public <R extends HttpRequest> R bindToRequest(R request, Object input) {
+ return tokenRequestFormat.formatRequest(request, (TokenRequest) input);
+ }
+}
http://git-wip-us.apache.org/repos/asf/stratos/blob/4203d59b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/json/ClaimSetTypeAdapter.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/json/ClaimSetTypeAdapter.java b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/json/ClaimSetTypeAdapter.java
new file mode 100644
index 0000000..62b3a26
--- /dev/null
+++ b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/json/ClaimSetTypeAdapter.java
@@ -0,0 +1,59 @@
+/*
+ * 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.json;
+
+import com.google.gson.TypeAdapter;
+import com.google.gson.stream.JsonReader;
+import com.google.gson.stream.JsonWriter;
+import org.jclouds.oauth.v2.domain.ClaimSet;
+
+import java.io.IOException;
+import java.util.Map;
+
+/**
+ * JSON TypeAdapter for the ClaimSet type. Pull the claims maps to the root level and adds two properties for the
+ * expiration time and issuing time.
+ */
+public class ClaimSetTypeAdapter extends TypeAdapter<ClaimSet> {
+
+ @Override
+ public void write(JsonWriter out, ClaimSet value) throws IOException {
+ out.beginObject();
+ for (Map.Entry<String, String> entry : value.entrySet()) {
+ out.name(entry.getKey());
+ out.value(entry.getValue());
+ }
+ out.name("exp");
+ out.value(value.getExpirationTime());
+ out.name("iat");
+ out.value(value.getEmissionTime());
+ out.endObject();
+ }
+
+ @Override
+ public ClaimSet read(JsonReader in) throws IOException {
+ ClaimSet.Builder builder = new ClaimSet.Builder();
+ in.beginObject();
+ while (in.hasNext()) {
+ String claimName = in.nextName();
+ String claimValue = in.nextString();
+ builder.addClaim(claimName, claimValue);
+ }
+ in.endObject();
+ return builder.build();
+ }
+}
http://git-wip-us.apache.org/repos/asf/stratos/blob/4203d59b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/json/HeaderTypeAdapter.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/json/HeaderTypeAdapter.java b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/json/HeaderTypeAdapter.java
new file mode 100644
index 0000000..f911a54
--- /dev/null
+++ b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/oauth/v2/json/HeaderTypeAdapter.java
@@ -0,0 +1,52 @@
+/*
+ * 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.json;
+
+import com.google.gson.TypeAdapter;
+import com.google.gson.stream.JsonReader;
+import com.google.gson.stream.JsonWriter;
+import org.jclouds.oauth.v2.domain.Header;
+
+import java.io.IOException;
+
+/**
+ * JSON TypeAdapter for the Header type. Simply transforms the field names.
+ */
+public class HeaderTypeAdapter extends TypeAdapter<Header> {
+
+ @Override
+ public void write(JsonWriter out, Header value) throws IOException {
+ out.beginObject();
+ out.name("alg");
+ out.value(value.getSignerAlgorithm());
+ out.name("typ");
+ out.value(value.getType());
+ out.endObject();
+ }
+
+ @Override
+ public Header read(JsonReader in) throws IOException {
+ Header.Builder builder = new Header.Builder();
+ in.beginObject();
+ in.nextName();
+ builder.signerAlgorithm(in.nextString());
+ in.nextName();
+ builder.type(in.nextString());
+ in.endObject();
+ return builder.build();
+ }
+}