JCLOUDS-750 At the cost of fiddling with type hierarchy adapters, remove lots of junk with google auto.

This commit is contained in:
Adrian Cole 2014-10-25 15:23:30 -07:00 committed by Adrian Cole
parent f94d0caf3b
commit 07d7a5a749
26 changed files with 459 additions and 856 deletions

View File

@ -48,6 +48,12 @@
<artifactId>jclouds-core</artifactId>
<version>${jclouds.version}</version>
</dependency>
<dependency>
<groupId>com.google.auto.value</groupId>
<artifactId>auto-value</artifactId>
<version>1.0-rc2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.jclouds</groupId>
<artifactId>jclouds-core</artifactId>
@ -61,6 +67,11 @@
<version>${jclouds.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.squareup.okhttp</groupId>
<artifactId>mockwebserver</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>

View File

@ -57,5 +57,4 @@ public interface OAuthApi extends Closeable {
@POST
@Consumes(MediaType.APPLICATION_JSON)
Token authenticate(@BinderParam(OAuthTokenBinder.class) TokenRequest tokenRequest) throws AuthorizationException;
}

View File

@ -22,16 +22,17 @@ import static org.jclouds.oauth.v2.config.OAuthProperties.SIGNATURE_OR_MAC_ALGOR
import java.net.URI;
import java.util.Properties;
import org.jclouds.apis.ApiMetadata;
import org.jclouds.oauth.v2.config.OAuthHttpApiModule;
import org.jclouds.oauth.v2.config.OAuthModule;
import org.jclouds.oauth.v2.config.OAuthParserModule;
import org.jclouds.rest.internal.BaseHttpApiMetadata;
import com.google.auto.service.AutoService;
import com.google.common.collect.ImmutableSet;
import com.google.inject.Module;
/**
* Implementation of {@link ApiMetadata} for OAuth 2 API
*/
@AutoService(ApiMetadata.class)
public class OAuthApiMetadata extends BaseHttpApiMetadata<OAuthApi> {
@Override
@ -64,7 +65,8 @@ public class OAuthApiMetadata extends BaseHttpApiMetadata<OAuthApi> {
.documentation(URI.create("TODO"))
.version("2")
.defaultProperties(OAuthApiMetadata.defaultProperties())
.defaultModules(ImmutableSet.<Class<? extends Module>>of(OAuthModule.class, OAuthHttpApiModule.class));
.defaultModules(ImmutableSet
.<Class<? extends Module>>of(OAuthModule.class, OAuthParserModule.class, OAuthHttpApiModule.class));
}
@Override

View File

@ -16,21 +16,10 @@
*/
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.Inject;
import com.google.inject.Provider;
import com.google.inject.Provides;
import com.google.inject.Singleton;
import com.google.inject.TypeLiteral;
import com.google.inject.name.Named;
import org.jclouds.oauth.v2.domain.ClaimSet;
import org.jclouds.oauth.v2.domain.Header;
import static org.jclouds.Constants.PROPERTY_SESSION_INTERVAL;
import java.util.concurrent.TimeUnit;
import org.jclouds.oauth.v2.domain.OAuthCredentials;
import org.jclouds.oauth.v2.domain.Token;
import org.jclouds.oauth.v2.domain.TokenRequest;
@ -41,28 +30,25 @@ 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 java.lang.reflect.Type;
import java.util.Map;
import java.util.concurrent.TimeUnit;
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.inject.AbstractModule;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Provides;
import com.google.inject.Singleton;
import com.google.inject.TypeLiteral;
import com.google.inject.name.Named;
import static org.jclouds.Constants.PROPERTY_SESSION_INTERVAL;
/**
* Base OAuth module
*/
public class OAuthModule extends AbstractModule {
@Override
protected void configure() {
@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(CredentialType.class).toProvider(CredentialTypeFromPropertyOrDefault.class);
bind(new TypeLiteral<Supplier<OAuthCredentials>>() {}).to(OAuthCredentialsSupplier.class);
bind(new TypeLiteral<Function<GeneratedHttpRequest, TokenRequest>>() {}).to(BuildTokenRequest.class);

View File

@ -0,0 +1,159 @@
/*
* 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.io.IOException;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import javax.inject.Singleton;
import org.jclouds.oauth.v2.domain.ClaimSet;
import org.jclouds.oauth.v2.domain.Header;
import org.jclouds.oauth.v2.domain.Token;
import com.google.common.collect.ImmutableSet;
import com.google.gson.Gson;
import com.google.gson.TypeAdapter;
import com.google.gson.TypeAdapterFactory;
import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;
import com.google.inject.AbstractModule;
import com.google.inject.Provides;
/** Configures type adapter factories for {@link Header}, {@link ClaimSet}, and {@link Token}. */
public final class OAuthParserModule extends AbstractModule {
@Override protected void configure() {
}
// TODO: change jclouds core to use collaborative set bindings
@Provides @Singleton public Set<TypeAdapterFactory> typeAdapterFactories() {
return ImmutableSet
.<TypeAdapterFactory>of(new HeaderTypeAdapter(), new ClaimSetTypeAdapter(), new TokenAdapter());
}
private static final class HeaderTypeAdapter extends SubtypeAdapterFactory<Header> {
HeaderTypeAdapter() {
super(Header.class);
}
@Override public void write(JsonWriter out, Header value) throws IOException {
out.beginObject();
out.name("alg");
out.value(value.signerAlgorithm());
out.name("typ");
out.value(value.type());
out.endObject();
}
@Override public Header read(JsonReader in) throws IOException {
in.beginObject();
in.nextName();
String signerAlgorithm = in.nextString();
in.nextName();
String type = in.nextString();
in.endObject();
return Header.create(signerAlgorithm, type);
}
}
private static final class ClaimSetTypeAdapter extends SubtypeAdapterFactory<ClaimSet> {
ClaimSetTypeAdapter() {
super(ClaimSet.class);
}
@Override public void write(JsonWriter out, ClaimSet value) throws IOException {
out.beginObject();
for (Map.Entry<String, String> entry : value.claims().entrySet()) {
out.name(entry.getKey());
out.value(entry.getValue());
}
out.name("exp");
out.value(value.expirationTime());
out.name("iat");
out.value(value.emissionTime());
out.endObject();
}
@Override public ClaimSet read(JsonReader in) throws IOException {
Map<String, String> claims = new LinkedHashMap<String, String>();
in.beginObject();
while (in.hasNext()) {
claims.put(in.nextName(), in.nextString());
}
in.endObject();
return ClaimSet.create(0, 0, Collections.unmodifiableMap(claims));
}
}
/** OAuth is used in apis that may not default to snake case. Explicity control case format. */
private static final class TokenAdapter extends SubtypeAdapterFactory<Token> {
TokenAdapter() {
super(Token.class);
}
@Override public void write(JsonWriter out, Token value) throws IOException {
out.beginObject();
out.name("access_token");
out.value(value.accessToken());
out.name("token_type");
out.value(value.tokenType());
out.name("expires_in");
out.value(value.expiresIn());
out.endObject();
}
@Override public Token read(JsonReader in) throws IOException {
String accessToken = null;
String tokenType = null;
int expiresIn = 0;
in.beginObject();
while (in.hasNext()) {
String name = in.nextName();
if (name.equals("access_token")) {
accessToken = in.nextString();
} else if (name.equals("token_type")) {
tokenType = in.nextString();
} else if (name.equals("expires_in")) {
expiresIn = in.nextInt();
} else {
in.skipValue();
}
}
in.endObject();
return Token.create(accessToken, tokenType, expiresIn);
}
}
private abstract static class SubtypeAdapterFactory<T> extends TypeAdapter<T> implements TypeAdapterFactory {
private final Class<T> baseClass;
private SubtypeAdapterFactory(Class<T> baseClass) {
this.baseClass = baseClass;
}
@Override public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) {
if (!(baseClass.isAssignableFrom(typeToken.getRawType()))) {
return null;
}
return (TypeAdapter<T>) this;
}
}
}

View File

@ -16,176 +16,27 @@
*/
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;
import com.google.auto.value.AutoValue;
/**
* The claimset for the token.
* The claimset for the {@linkplain Token}.
*
* @see <a
* href="https://developers.google.com/accounts/docs/OAuth2ServiceAccount"
* >doc</a>
* @see <a href="https://developers.google.com/accounts/docs/OAuth2ServiceAccount">doc</a>
*/
public class ClaimSet extends ForwardingMap<String, String> {
@AutoValue
public abstract class ClaimSet {
public static Builder builder() {
return new Builder();
}
/** The emission time, in seconds since the epoch. */
public abstract long emissionTime();
public Builder toBuilder() {
return builder().fromClaimSet(this);
}
/** The expiration time, in seconds since the emission time. */
public abstract long expirationTime();
public static class Builder {
public abstract Map<String, String> claims();
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);
public static ClaimSet create(long emissionTime, long expirationTime, Map<String, String> claims) {
return new AutoValue_ClaimSet(emissionTime, expirationTime, claims);
}
}

View File

@ -16,113 +16,23 @@
*/
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;
import com.google.auto.value.AutoValue;
/**
* 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 {
@AutoValue
public abstract class Header {
public static Builder builder() {
return new Builder();
}
/** The name of the algorithm used to compute the signature, e.g., {@code RS256}. */
public abstract String signerAlgorithm();
public Builder toBuilder() {
return builder().fromHeader(this);
}
/** The type of the token, e.g., {@code JWT}. */
public abstract String type();
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);
public static Header create(String signerAlgorithm, String type){
return new AutoValue_Header(signerAlgorithm, type);
}
}

View File

@ -16,134 +16,24 @@
*/
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;
import com.google.auto.value.AutoValue;
/**
* The oauth token, obtained upon a successful token request and ready to embed in requests.
*/
public class Token {
@AutoValue
public abstract class Token {
/** The access token obtained from the OAuth server. */
public abstract String accessToken();
public static Builder builder() {
return new Builder();
/** The type of the token, e.g., {@code Bearer}. */
public abstract String tokenType();
/** In how many seconds this token expires. */
public abstract long expiresIn();
public static Token
create(String accessToken, String tokenType, long expiresIn) {
return new AutoValue_Token(accessToken, tokenType, expiresIn);
}
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);
}
}

View File

@ -16,116 +16,14 @@
*/
package org.jclouds.oauth.v2.domain;
import com.google.common.base.Objects;
import com.google.auto.value.AutoValue;
import static com.google.common.base.Objects.equal;
import static com.google.common.base.Objects.toStringHelper;
import static com.google.common.base.Preconditions.checkNotNull;
@AutoValue
public abstract class TokenRequest {
public abstract Header header();
public abstract ClaimSet claimSet();
/**
* A complete token request.
*/
public class TokenRequest {
public static Builder builder() {
return new Builder();
public static TokenRequest create(Header header, ClaimSet claimSet) {
return new AutoValue_TokenRequest(header, claimSet);
}
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);
}
}

View File

@ -36,7 +36,7 @@ public interface TokenRequestFormat {
/**
* The name of the type of the token request, e.g., "JWT"
*/
String getTypeName();
String type();
/**
* The claims that must be present in the token request for it to be valid.

View File

@ -54,7 +54,7 @@ public class OAuthAuthenticator implements OAuthAuthenticationFilter {
TokenRequest tokenRequest = tokenRequestBuilder.apply(generatedHttpRequest);
Token token = tokenFetcher.apply(tokenRequest);
return request.toBuilder().addHeader("Authorization", String.format("%s %s",
token.getTokenType(), token.getAccessToken())).build();
token.tokenType(), token.accessToken())).build();
}

View File

@ -22,6 +22,8 @@ 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.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import javax.inject.Singleton;
@ -38,7 +40,6 @@ 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;
@ -61,7 +62,7 @@ public class BuildTokenRequest implements Function<GeneratedHttpRequest, TokenRe
@Inject(optional = true)
@Named(ADDITIONAL_CLAIMS)
protected Map<String, String> additionalClaims = ImmutableMap.of();
protected Map<String, String> additionalClaims = Collections.emptyMap();
@Inject(optional = true)
@Named(SCOPES)
@ -93,24 +94,20 @@ public class BuildTokenRequest implements Function<GeneratedHttpRequest, TokenRe
long now = timeSourceMillisSinceEpoch.get() / 1000;
// fetch the token
Header header = new Header.Builder()
.signerAlgorithm(signatureAlgorithm)
.type(tokenRequestFormat.getTypeName())
.build();
Header header = Header.create(signatureAlgorithm, tokenRequestFormat.type());
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();
Map<String, String> claims = new LinkedHashMap<String, String>();
claims.put("iss", credentialsSupplier.get().identity);
claims.put("scope", getOAuthScopes(request));
claims.put("aud", assertionTargetDescription);
claims.putAll(additionalClaims);
return new TokenRequest.Builder()
.header(header)
.claimSet(claimSet)
.build();
checkState(claims.keySet().containsAll(tokenRequestFormat.requiredClaims()),
"not all required claims were present");
ClaimSet claimSet = ClaimSet.create(now, now + tokenDuration, Collections.unmodifiableMap(claims));
return TokenRequest.create(header, claimSet);
}
protected String getOAuthScopes(GeneratedHttpRequest request) {

View File

@ -0,0 +1,42 @@
/*
* 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.internal;
import com.google.gson.Gson;
import com.google.gson.TypeAdapter;
import com.google.gson.TypeAdapterFactory;
import com.google.gson.reflect.TypeToken;
/**
* Type adapter used to serialize all subtypes of a value. This can be used to force serialization for an {@link
* com.google.auto.value.AutoValue} generated class.
*/
public abstract class SubtypeAdapterFactory<T> extends TypeAdapter<T> implements TypeAdapterFactory {
private final Class<T> baseClass;
protected SubtypeAdapterFactory(Class<T> baseClass) {
this.baseClass = baseClass;
}
/** Accepts duty for any subtype. When using AutoValue properly, this will be the generated form. */
@Override public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) {
if (!(baseClass.isAssignableFrom(typeToken.getRawType()))) {
return null;
}
return (TypeAdapter<T>) this;
}
}

View File

@ -1,59 +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.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();
}
}

View File

@ -1,52 +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.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();
}
}

View File

@ -24,7 +24,6 @@ import static org.jclouds.io.Payloads.newUrlEncodedFormPayload;
import java.util.Set;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.http.HttpRequest;
import org.jclouds.io.Payload;
@ -45,7 +44,6 @@ import com.google.common.collect.ImmutableSet;
* https://developers.google.com/accounts/docs/OAuth2ServiceAccount
* <p/>
*/
@Singleton
public class JWTTokenRequestFormat implements TokenRequestFormat {
private static final String ASSERTION_FORM_PARAM = "assertion";
@ -55,18 +53,15 @@ public class JWTTokenRequestFormat implements TokenRequestFormat {
private final Function<byte[], byte[]> signer;
private final Json json;
@Inject
public JWTTokenRequestFormat(Function<byte[], byte[]> signer, Json json) {
@Inject JWTTokenRequestFormat(Function<byte[], byte[]> signer, Json json) {
this.signer = signer;
this.json = json;
}
@SuppressWarnings("unchecked")
@Override
public <R extends HttpRequest> R formatRequest(R request, TokenRequest tokenRequest) {
@Override public <R extends HttpRequest> R formatRequest(R request, TokenRequest tokenRequest) {
String encodedHeader = json.toJson(tokenRequest.getHeader());
String encodedClaimSet = json.toJson(tokenRequest.getClaimSet());
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));
@ -83,13 +78,11 @@ public class JWTTokenRequestFormat implements TokenRequestFormat {
return (R) request.toBuilder().payload(payload).build();
}
@Override
public String getTypeName() {
@Override public String type() {
return "JWT";
}
@Override
public Set<String> requiredClaims() {
@Override public Set<String> requiredClaims() {
// exp and ist (expiration and emission times) are assumed mandatory already
return ImmutableSet.of("iss", "scope", "aud");
}

View File

@ -1,18 +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.
#
org.jclouds.oauth.v2.OAuthApiMetadata

View File

@ -16,35 +16,33 @@
*/
package org.jclouds.oauth.v2;
import com.google.common.base.Charsets;
import com.google.common.base.Throwables;
import com.google.common.io.Files;
import org.jclouds.oauth.v2.config.CredentialType;
import org.jclouds.oauth.v2.config.OAuthProperties;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Throwables.propagate;
import static org.jclouds.oauth.v2.config.OAuthProperties.AUDIENCE;
import static org.jclouds.util.Strings2.toStringAndClose;
import java.io.File;
import java.io.IOException;
import java.util.Properties;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.oauth.v2.config.OAuthProperties.AUDIENCE;
import org.jclouds.oauth.v2.config.CredentialType;
import org.jclouds.oauth.v2.config.OAuthProperties;
import com.google.common.base.Charsets;
import com.google.common.io.Files;
/**
* Utils for OAuth tests.
*/
public class OAuthTestUtils {
public static Properties defaultProperties(Properties properties) {
try {
properties = properties == null ? new Properties() : properties;
properties.put("oauth.identity", "foo");
properties.put("oauth.credential",
Files.asCharSource(new File("src/test/resources/testpk.pem"), Charsets.UTF_8).read());
properties.put("oauth.credential", toStringAndClose(OAuthTestUtils.class.getResourceAsStream("/testpk.pem")));
properties.put("oauth.endpoint", "http://localhost:5000/o/oauth2/token");
properties.put(AUDIENCE, "https://accounts.google.com/o/oauth2/token");
return properties;
} catch (IOException e) {
throw Throwables.propagate(e);
throw propagate(e);
}
}
@ -75,7 +73,7 @@ public class OAuthTestUtils {
try {
credentialFromFile = Files.toString(new File(val), Charsets.UTF_8);
} catch (IOException e) {
throw Throwables.propagate(e);
throw propagate(e);
}
overrides.setProperty(key, credentialFromFile);
return credentialFromFile;

View File

@ -1,99 +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.features;
import static com.google.common.base.Charsets.UTF_8;
import static com.google.common.io.BaseEncoding.base64Url;
import static org.testng.Assert.assertEquals;
import java.net.URI;
import java.util.Properties;
import javax.ws.rs.core.MediaType;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.jclouds.oauth.v2.OAuthApi;
import org.jclouds.oauth.v2.OAuthTestUtils;
import org.jclouds.oauth.v2.domain.ClaimSet;
import org.jclouds.oauth.v2.domain.Header;
import org.jclouds.oauth.v2.domain.Token;
import org.jclouds.oauth.v2.domain.TokenRequest;
import org.jclouds.oauth.v2.internal.BaseOAuthApiExpectTest;
import org.testng.annotations.Test;
/**
* Tests that a token requess is well formed.
*/
@Test(groups = "unit")
public class OAuthApiExpectTest extends BaseOAuthApiExpectTest {
private static final String header = "{\"alg\":\"RS256\",\"typ\":\"JWT\"}";
private static final String claims = "{\"iss\":\"761326798069-r5mljlln1rd4lrbhg75efgigp36m78j5@developer" +
".gserviceaccount.com\"," +
"\"scope\":\"https://www.googleapis.com/auth/prediction\",\"aud\":\"https://accounts.google" +
".com/o/oauth2/token\",\"exp\":1328573381,\"iat\":1328569781}";
private static final Token TOKEN = new Token.Builder().accessToken
("1/8xbJqaOZXSUZbHLl5EOtu1pxz3fmmetKx9W8CV4t79M").tokenType("Bearer").expiresIn(3600).build();
private static final ClaimSet CLAIM_SET = new ClaimSet.Builder().addClaim("iss",
"761326798069-r5mljlln1rd4lrbhg75efgigp36m78j5@developer" +
".gserviceaccount.com")
.addClaim("scope", "https://www.googleapis.com/auth/prediction")
.addClaim("aud", "https://accounts.google.com/o/oauth2/token")
.expirationTime(1328573381)
.emissionTime(1328569781).build();
private static final Header HEADER = new Header.Builder().signerAlgorithm("RS256").type("JWT").build();
private static final String URL_ENCODED_TOKEN_REQUEST =
"grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&" +
// Base64 Encoded Header
"assertion=" + base64Url().omitPadding().encode(header.getBytes(UTF_8)) + "." +
// Base64 Encoded Claims
base64Url().omitPadding().encode(claims.getBytes(UTF_8)) + "." +
// Base64 encoded {header}.{claims} signature (using SHA256)
"W2Lesr_98AzVYiMbzxFqmwcOjpIWlwqkC6pNn1fXND9oSDNNnFhy-AAR6DKH-x9ZmxbY80" +
"R5fH-OCeWumXlVgceKN8Z2SmgQsu8ElTpypQA54j_5j8vUImJ5hsOUYPeyF1U2BUzZ3L5g" +
"03PXBA0YWwRU9E1ChH28dQBYuGiUmYw";
private static final HttpRequest TOKEN_REQUEST = HttpRequest.builder()
.method("POST")
.endpoint(URI.create("http://localhost:5000/o/oauth2/token"))
.addHeader("Accept", MediaType.APPLICATION_JSON)
.payload(payloadFromStringWithContentType(URL_ENCODED_TOKEN_REQUEST, "application/x-www-form-urlencoded"))
.build();
private static final HttpResponse TOKEN_RESPONSE = HttpResponse.builder().statusCode(200).payload(
payloadFromString("{\n" +
" \"access_token\" : \"1/8xbJqaOZXSUZbHLl5EOtu1pxz3fmmetKx9W8CV4t79M\",\n" +
" \"token_type\" : \"Bearer\",\n" +
" \"expires_in\" : 3600\n" +
"}")).build();
@Override
protected Properties setupProperties() {
return OAuthTestUtils.defaultProperties(super.setupProperties());
}
public void testGenerateJWTRequest() {
OAuthApi api = requestSendsResponse(TOKEN_REQUEST, TOKEN_RESPONSE);
assertEquals(api.authenticate(new TokenRequest(HEADER, CLAIM_SET)), TOKEN);
}
}

View File

@ -34,6 +34,8 @@ import org.jclouds.oauth.v2.domain.TokenRequest;
import org.jclouds.oauth.v2.internal.BaseOAuthApiLiveTest;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableMap;
/**
* A live test for authentication. Requires the following properties to be set:
* - test.oauth.endpoint
@ -62,17 +64,17 @@ public class OAuthApiLiveTest extends BaseOAuthApiLiveTest {
checkState(OAuthConstants.OAUTH_ALGORITHM_NAMES_TO_SIGNATURE_ALGORITHM_NAMES.containsKey(signatureAlgorithm)
, String.format("Algorithm not supported: " + signatureAlgorithm));
Header header = Header.builder().signerAlgorithm(signatureAlgorithm).type("JWT").build();
Header header = Header.create(signatureAlgorithm, "JWT");
String scopes = getMandatoryProperty(properties, SCOPES);
String audience = getMandatoryProperty(properties, AUDIENCE);
long now = nowInSeconds();
ClaimSet claimSet = ClaimSet.builder().addClaim("aud", audience).addClaim("scope", scopes).addClaim("iss",
identity).emissionTime(now).expirationTime(now + 3600).build();
ClaimSet claimSet = ClaimSet.create(now, now + 3600,
ImmutableMap.of("aud", audience, "scope", scopes, "iss", identity));
TokenRequest tokenRequest = TokenRequest.builder().header(header).claimSet(claimSet).build();
TokenRequest tokenRequest = TokenRequest.create(header, claimSet);
Token token = api.authenticate(tokenRequest);
assertNotNull(token, "no token when authenticating " + tokenRequest);

View File

@ -0,0 +1,114 @@
/*
* 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.features;
import static com.google.common.base.Charsets.UTF_8;
import static com.google.common.io.BaseEncoding.base64Url;
import static com.google.common.util.concurrent.MoreExecutors.sameThreadExecutor;
import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
import static org.jclouds.Constants.PROPERTY_MAX_RETRIES;
import static org.jclouds.oauth.v2.config.OAuthProperties.AUDIENCE;
import static org.jclouds.util.Strings2.toStringAndClose;
import static org.testng.Assert.assertEquals;
import java.io.IOException;
import java.net.URL;
import java.util.Properties;
import org.jclouds.ContextBuilder;
import org.jclouds.concurrent.config.ExecutorServiceModule;
import org.jclouds.oauth.v2.OAuthApi;
import org.jclouds.oauth.v2.OAuthApiMetadata;
import org.jclouds.oauth.v2.OAuthTestUtils;
import org.jclouds.oauth.v2.domain.ClaimSet;
import org.jclouds.oauth.v2.domain.Header;
import org.jclouds.oauth.v2.domain.Token;
import org.jclouds.oauth.v2.domain.TokenRequest;
import org.testng.annotations.Test;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.io.BaseEncoding;
import com.google.inject.Module;
import com.squareup.okhttp.mockwebserver.MockResponse;
import com.squareup.okhttp.mockwebserver.MockWebServer;
import com.squareup.okhttp.mockwebserver.RecordedRequest;
@Test(groups = "unit", testName = "OAuthApiMockTest")
public class OAuthApiMockTest {
private static final String header = "{\"alg\":\"RS256\",\"typ\":\"JWT\"}";
private static final String claims = "{\"iss\":\"761326798069-r5mljlln1rd4lrbhg75efgigp36m78j5@developer" +
".gserviceaccount.com\"," +
"\"scope\":\"https://www.googleapis.com/auth/prediction\",\"aud\":\"https://accounts.google" +
".com/o/oauth2/token\",\"exp\":1328573381,\"iat\":1328569781}";
private static final Token TOKEN = Token.create("1/8xbJqaOZXSUZbHLl5EOtu1pxz3fmmetKx9W8CV4t79M", "Bearer", 3600);
private static final ClaimSet CLAIM_SET = ClaimSet.create(1328569781, 1328573381, ImmutableMap
.of("iss", "761326798069-r5mljlln1rd4lrbhg75efgigp36m78j5@developer.gserviceaccount.com", "scope",
"https://www.googleapis.com/auth/prediction", "aud", "https://accounts.google.com/o/oauth2/token"));
private static final Header HEADER = Header.create("RS256", "JWT");
public void testGenerateJWTRequest() throws Exception {
MockWebServer server = new MockWebServer();
server.enqueue(new MockResponse().setBody("{\n" +
" \"access_token\" : \"1/8xbJqaOZXSUZbHLl5EOtu1pxz3fmmetKx9W8CV4t79M\",\n" +
" \"token_type\" : \"Bearer\",\n" +
" \"expires_in\" : 3600\n" +
"}"));
server.play();
OAuthApi api = api(server.getUrl("/"));
assertEquals(api.authenticate(TokenRequest.create(HEADER, CLAIM_SET)), TOKEN);
RecordedRequest request = server.takeRequest();
assertEquals(request.getMethod(), "POST");
assertEquals(request.getHeader("Accept"), APPLICATION_JSON);
assertEquals(request.getHeader("Content-Type"), "application/x-www-form-urlencoded");
assertEquals(new String(request.getBody(), UTF_8), //
"grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&" +
// Base64 Encoded Header
"assertion=" +
Joiner.on('.').join(encoding.encode(header.getBytes(UTF_8)), encoding.encode(claims.getBytes(UTF_8)),
// Base64 encoded {header}.{claims} signature (using SHA256)
"W2Lesr_98AzVYiMbzxFqmwcOjpIWlwqkC6pNn1fXND9oSDNNnFhy-AAR6DKH-x9ZmxbY80" +
"R5fH-OCeWumXlVgceKN8Z2SmgQsu8ElTpypQA54j_5j8vUImJ5hsOUYPeyF1U2BUzZ3L5g" +
"03PXBA0YWwRU9E1ChH28dQBYuGiUmYw"));
}
private final BaseEncoding encoding = base64Url().omitPadding();
private OAuthApi api(URL url) throws IOException {
Properties overrides = new Properties();
overrides.put(AUDIENCE, "https://accounts.google.com/o/oauth2/token");
overrides.put(PROPERTY_MAX_RETRIES, "1");
return ContextBuilder.newBuilder(new OAuthApiMetadata())
.credentials("foo", toStringAndClose(OAuthTestUtils.class.getResourceAsStream("/testpk.pem")))
.endpoint(url.toString())
.overrides(overrides)
.modules(ImmutableSet.<Module>of(new ExecutorServiceModule(sameThreadExecutor())))
.buildApi(OAuthApi.class);
}
}

View File

@ -1,23 +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.internal;
import org.jclouds.oauth.v2.OAuthApi;
public class BaseOAuthApiExpectTest extends BaseOAuthExpectTest<OAuthApi> {
}

View File

@ -37,6 +37,7 @@ import org.jclouds.oauth.v2.domain.TokenRequest;
import org.testng.annotations.Test;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableMap;
import com.google.common.reflect.TypeToken;
import com.google.inject.Injector;
import com.google.inject.Key;
@ -75,18 +76,14 @@ public abstract class BaseOAuthAuthenticatedApiLiveTest<A extends Closeable> ext
// obtain the scopes from the subclass
String scopes = getScopes();
Header header = Header.builder().signerAlgorithm(signatureAlgorithm).type("JWT").build();
Header header = Header.create(signatureAlgorithm, "JWT");
long now = SECONDS.convert(System.currentTimeMillis(), MILLISECONDS);
ClaimSet claimSet = ClaimSet.builder()
.addClaim("aud", audience)
.addClaim("scope", scopes)
.addClaim("iss", identity)
.emissionTime(now)
.expirationTime(now + 3600).build();
ClaimSet claimSet = ClaimSet.create(now, now + 3600,
ImmutableMap.of("aud", audience, "scope", scopes, "iss", identity));
TokenRequest tokenRequest = TokenRequest.builder().header(header).claimSet(claimSet).build();
TokenRequest tokenRequest = TokenRequest.create(header, claimSet);
Token token = oauthApi.authenticate(tokenRequest);

View File

@ -16,11 +16,15 @@
*/
package org.jclouds.oauth.v2.internal;
import org.jclouds.rest.internal.BaseRestApiExpectTest;
import org.jclouds.json.BaseItemParserTest;
import org.jclouds.json.config.GsonModule;
import org.jclouds.oauth.v2.config.OAuthParserModule;
public class BaseOAuthExpectTest<T> extends BaseRestApiExpectTest<T> {
import com.google.inject.Guice;
import com.google.inject.Injector;
public BaseOAuthExpectTest() {
provider = "oauth";
public abstract class BaseOAuthParseTest<T> extends BaseItemParserTest<T> {
@Override protected Injector injector() {
return Guice.createInjector(new GsonModule(), new OAuthParserModule());
}
}

View File

@ -34,6 +34,7 @@ import org.jclouds.util.Strings2;
import org.testng.annotations.Test;
import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
@Test(groups = "unit")
@ -47,10 +48,10 @@ public class JWTTokenRequestFormatTest {
TokenRequestFormat tokenRequestFormat = ContextBuilder.newBuilder(new OAuthApiMetadata()).overrides
(OAuthTestUtils.defaultProperties(null)).build().utils()
.injector().getInstance(TokenRequestFormat.class);
Header header = new Header.Builder().signerAlgorithm("a").type("b").build();
ClaimSet claimSet = new ClaimSet.Builder().addClaim("ist", STRING_THAT_GENERATES_URL_UNSAFE_BASE64_ENCODING)
.build();
TokenRequest tokenRequest = new TokenRequest.Builder().claimSet(claimSet).header(header).build();
Header header = Header.create("a", "b");
ClaimSet claimSet = ClaimSet.create(0, 0,
ImmutableMap.of("ist", STRING_THAT_GENERATES_URL_UNSAFE_BASE64_ENCODING));
TokenRequest tokenRequest = TokenRequest.create(header, claimSet);
HttpRequest request = tokenRequestFormat.formatRequest(HttpRequest.builder().method("GET").endpoint
("http://localhost").build(), tokenRequest);

View File

@ -16,15 +16,16 @@
*/
package org.jclouds.oauth.v2.parse;
import org.jclouds.json.BaseItemParserTest;
import org.jclouds.oauth.v2.domain.Token;
import org.testng.annotations.Test;
import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
import javax.ws.rs.Consumes;
import javax.ws.rs.core.MediaType;
@Test(groups = "unit")
public class ParseTokenTest extends BaseItemParserTest<Token> {
import org.jclouds.oauth.v2.domain.Token;
import org.jclouds.oauth.v2.internal.BaseOAuthParseTest;
import org.testng.annotations.Test;
@Test(groups = "unit", testName = "ParseTokenTest")
public class ParseTokenTest extends BaseOAuthParseTest<Token> {
@Override
public String resource() {
@ -32,9 +33,8 @@ public class ParseTokenTest extends BaseItemParserTest<Token> {
}
@Override
@Consumes(MediaType.APPLICATION_JSON)
@Consumes(APPLICATION_JSON)
public Token expected() {
return Token.builder().expiresIn(3600).tokenType("Bearer").accessToken
("1/8xbJqaOZXSUZbHLl5EOtu1pxz3fmmetKx9W8CV4t79M").build();
return Token.create("1/8xbJqaOZXSUZbHLl5EOtu1pxz3fmmetKx9W8CV4t79M", "Bearer", 3600);
}
}