You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@shindig.apache.org by wo...@apache.org on 2011/10/12 22:10:42 UTC
svn commit: r1182565 [4/9] - in /shindig/trunk: config/
content/samplecontainer/examples/commoncontainer/
content/samplecontainer/examples/oauth2/
features/src/main/javascript/features/core.io/
features/src/main/javascript/features/shindig.xhrwrapper/ ...
Added: shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/handler/CodeGrantTypeHandler.java
URL: http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/handler/CodeGrantTypeHandler.java?rev=1182565&view=auto
==============================================================================
--- shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/handler/CodeGrantTypeHandler.java (added)
+++ shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/handler/CodeGrantTypeHandler.java Wed Oct 12 20:10:39 2011
@@ -0,0 +1,105 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.apache.shindig.gadgets.oauth2.handler;
+
+import java.util.Map;
+
+import org.apache.shindig.gadgets.http.HttpRequest;
+import org.apache.shindig.gadgets.oauth2.OAuth2Accessor;
+import org.apache.shindig.gadgets.oauth2.OAuth2Error;
+import org.apache.shindig.gadgets.oauth2.OAuth2Message;
+import org.apache.shindig.gadgets.oauth2.OAuth2RequestException;
+import org.apache.shindig.gadgets.oauth2.OAuth2Utils;
+
+import com.google.common.collect.Maps;
+import com.google.inject.Inject;
+
+/**
+ *
+ * See {@link GrantRequestHandler}
+ *
+ * Handles the "authorization_code" flow
+ */
+public class CodeGrantTypeHandler implements GrantRequestHandler {
+ private static final OAuth2Error ERROR = OAuth2Error.CODE_GRANT_PROBLEM;
+
+ @Inject
+ public CodeGrantTypeHandler() {
+ }
+
+ public HttpRequest getAuthorizationRequest(final OAuth2Accessor accessor,
+ final String completeAuthorizationUrl) throws OAuth2RequestException {
+ throw new OAuth2RequestException(CodeGrantTypeHandler.ERROR,
+ "inappropriate call to CodeGrantTypeHandler.getAuthorizationRequest()", null);
+ }
+
+ public String getCompleteUrl(final OAuth2Accessor accessor) throws OAuth2RequestException {
+ if (accessor == null) {
+ throw new OAuth2RequestException(CodeGrantTypeHandler.ERROR, "accessor is null", null);
+ }
+
+ if (!accessor.isValid() || accessor.isErrorResponse() || accessor.isRedirecting()) {
+ throw new OAuth2RequestException(CodeGrantTypeHandler.ERROR, "accessor is invalid", null);
+ }
+
+ if (!accessor.getGrantType().equalsIgnoreCase(OAuth2Message.AUTHORIZATION)) {
+ throw new OAuth2RequestException(CodeGrantTypeHandler.ERROR, "grant type is not code", null);
+ }
+
+ final Map<String, String> queryParams = Maps.newHashMapWithExpectedSize(4);
+ queryParams.put(OAuth2Message.RESPONSE_TYPE, this.getGrantType());
+ queryParams.put(OAuth2Message.CLIENT_ID, accessor.getClientId());
+ final String redirectUri = accessor.getRedirectUri();
+ if ((redirectUri != null) && (redirectUri.length() > 0)) {
+ queryParams.put(OAuth2Message.REDIRECT_URI, redirectUri);
+ }
+
+ final String state = accessor.getState();
+ if ((state != null) && (state.length() > 0)) {
+ queryParams.put(OAuth2Message.STATE, state);
+ }
+
+ final String scope = accessor.getScope();
+ if ((scope != null) && (scope.length() > 0)) {
+ queryParams.put(OAuth2Message.SCOPE, scope);
+ }
+
+ final String ret = OAuth2Utils.buildUrl(accessor.getAuthorizationUrl(), queryParams, null);
+
+ return ret;
+ }
+
+ public String getGrantType() {
+ return OAuth2Message.AUTHORIZATION;
+ }
+
+ public static String getResponseType() {
+ return OAuth2Message.AUTHORIZATION_CODE;
+ }
+
+ public boolean isAuthorizationEndpointResponse() {
+ return true;
+ }
+
+ public boolean isRedirectRequired() {
+ return true;
+ }
+
+ public boolean isTokenEndpointResponse() {
+ return false;
+ }
+}
\ No newline at end of file
Added: shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/handler/GrantRequestHandler.java
URL: http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/handler/GrantRequestHandler.java?rev=1182565&view=auto
==============================================================================
--- shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/handler/GrantRequestHandler.java (added)
+++ shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/handler/GrantRequestHandler.java Wed Oct 12 20:10:39 2011
@@ -0,0 +1,82 @@
+/*
+ * 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.apache.shindig.gadgets.oauth2.handler;
+
+import org.apache.shindig.gadgets.http.HttpRequest;
+import org.apache.shindig.gadgets.oauth2.OAuth2Accessor;
+import org.apache.shindig.gadgets.oauth2.OAuth2RequestException;
+
+/**
+ * Enables injection of new Grant Type schemes into the system.
+ *
+ * If a {@link GrantRequestHandler#getGrantType()} matches a
+ * {@link OAuth2Accessor#getGrantType()} it will be invoked to initiate the
+ * grant request.
+ *
+ * By default "code" and "client_credentials" are supported.
+ *
+ * Only one GrantRequestHandler will be executed (first to match.)
+ *
+ */
+public interface GrantRequestHandler {
+ /**
+ * If {@link #isRedirectRequired()} is false the system will executes this
+ * request.
+ *
+ * @param accessor
+ * @param completeAuthorizationUrl
+ * @return HttpRequest
+ * @throws OAuth2RequestException
+ */
+ public HttpRequest getAuthorizationRequest(OAuth2Accessor accessor,
+ String completeAuthorizationUrl) throws OAuth2RequestException;
+
+ /**
+ * Url to send redirects to.
+ *
+ * @param accessor
+ * @return String complete url
+ * @throws OAuth2RequestException
+ */
+ public String getCompleteUrl(OAuth2Accessor accessor) throws OAuth2RequestException;
+
+ /**
+ *
+ * @return the grant_type this handler initiates
+ */
+ public String getGrantType();
+
+ /**
+ *
+ * @return true if the response is from the authorization endpoint, i.e. code
+ */
+ public boolean isAuthorizationEndpointResponse();
+
+ /**
+ *
+ * @return true to redirect the client to the
+ * {@link #getCompleteUrl(OAuth2Accessor)}
+ */
+ public boolean isRedirectRequired();
+
+ /**
+ *
+ * @return true if the response is from the token endpoint i.e.
+ * client_credentials
+ */
+ public boolean isTokenEndpointResponse();
+}
Added: shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/handler/MacTokenHandler.java
URL: http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/handler/MacTokenHandler.java?rev=1182565&view=auto
==============================================================================
--- shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/handler/MacTokenHandler.java (added)
+++ shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/handler/MacTokenHandler.java Wed Oct 12 20:10:39 2011
@@ -0,0 +1,266 @@
+/*
+ * 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.apache.shindig.gadgets.oauth2.handler;
+
+import java.io.UnsupportedEncodingException;
+import java.security.GeneralSecurityException;
+
+import org.apache.commons.codec.binary.Base64;
+import org.apache.shindig.common.crypto.Crypto;
+import org.apache.shindig.common.uri.Uri;
+import org.apache.shindig.gadgets.http.HttpRequest;
+import org.apache.shindig.gadgets.oauth2.OAuth2Accessor;
+import org.apache.shindig.gadgets.oauth2.OAuth2Error;
+import org.apache.shindig.gadgets.oauth2.OAuth2Message;
+import org.apache.shindig.gadgets.oauth2.OAuth2Token;
+
+/**
+ *
+ * See {@link ResourceRequestHandler}
+ *
+ * Handles the mac token type
+ */
+public class MacTokenHandler implements ResourceRequestHandler {
+ public static final String TOKEN_TYPE = OAuth2Message.MAC_TOKEN_TYPE;
+ private static final OAuth2Error ERROR = OAuth2Error.MAC_TOKEN_PROBLEM;
+
+ public MacTokenHandler() {
+ }
+
+ public OAuth2HandlerError addOAuth2Params(final OAuth2Accessor accessor, final HttpRequest request) {
+ try {
+ final OAuth2HandlerError handlerError = MacTokenHandler.validateOAuth2Params(accessor, request);
+ if (handlerError != null) {
+ return handlerError;
+ }
+
+ final OAuth2Token accessToken = accessor.getAccessToken();
+
+ String ext = accessToken.getMacExt();
+ if ((ext == null) || (ext.length() == 0)) {
+ ext = "";
+ }
+
+ // REQUIRED. The MAC key identifier.
+ final String id = new String(accessToken.getSecret(), "UTF-8");
+
+ // REQUIRED. A unique string generated by the client to allow the
+ // server to verify that a request has never been made before and
+ // helps prevent replay attacks when requests are made over an
+ // insecure channel. The nonce value MUST be unique across all
+ // requests with the same MAC key identifier.
+ // The nonce value MUST consist of the age of the MAC credentials
+ // expressed as the number of seconds since the credentials were
+ // issued to the client, a colon character (%x25), and a unique
+ // string (typically random). The age value MUST be a positive
+ // integer and MUST NOT include leading zeros (e.g.
+ // "000137131200"). For example: "273156:di3hvdf8".
+ // To avoid the need to retain an infinite number of nonce values
+ // for future checks, the server MAY choose to restrict the time
+ // period after which a request with an old age is rejected. If
+ // such a restriction is enforced, the server SHOULD allow for a
+ // sufficiently large window to accommodate network delays which
+ // will affect the credentials issue time used by the client to
+ // calculate the credentials' age.
+ final long currentTime = System.currentTimeMillis() / 1000;
+ final String nonce = Long.toString(currentTime - accessToken.getIssuedAt()) + ':'
+ + String.valueOf(Math.abs(Crypto.RAND.nextLong()));
+
+ // OPTIONAL. The HTTP request payload body hash as described in
+ // Section 3.2.
+
+ String bodyHash = MacTokenHandler.getBodyHash(request, accessToken.getMacSecret(),
+ accessToken.getMacAlgorithm());
+ if (bodyHash == null) {
+ bodyHash = "";
+ }
+
+ // mac
+ // REQUIRED. The HTTP request MAC as described in Section 3.3.
+ final Uri uri = request.getUri();
+
+ String uriString = uri.getPath();
+ if (uri.getQuery() != null) {
+ uriString = uriString + '?' + uri.getQuery();
+ }
+
+ String host = uri.getAuthority();
+ String port = "80";
+ final int index = host.indexOf(':');
+ if (index > 0) {
+ port = host.substring(index + 1);
+ host = host.substring(0, index);
+ } else {
+ final String scheme = uri.getScheme();
+ if ("https".equals(scheme)) {
+ port = "443";
+ }
+ }
+
+ final String mac = MacTokenHandler.getMac(nonce, request.getMethod(), uriString, host, port,
+ bodyHash, ext, accessToken.getMacSecret(), accessToken.getMacAlgorithm());
+
+ final String headerString = buildHeaderString(id, nonce, bodyHash, ext, mac);
+
+ request.setHeader(OAuth2Message.AUTHORIZATION_HEADER, headerString);
+ return null;
+ } catch (final Exception e) {
+ return MacTokenHandler.getError("Exception occurred " + e.getMessage(), e);
+ }
+ }
+
+ private static String buildHeaderString(String id, String nonce, String bodyHash, String ext, String mac) {
+ final StringBuilder headerString = new StringBuilder();
+
+ headerString.append(OAuth2Message.MAC_HEADER);
+ headerString.append(" id = \"");
+ headerString.append(id);
+ headerString.append("\",");
+ headerString.append(OAuth2Message.NONCE);
+ headerString.append("=\"");
+ headerString.append(nonce);
+ if (bodyHash.length() > 0) {
+ headerString.append("\",");
+ headerString.append(OAuth2Message.BODYHASH);
+ headerString.append("=\"");
+ headerString.append(bodyHash);
+ }
+ if (ext.length() > 0) {
+ headerString.append("\",");
+ headerString.append(OAuth2Message.MAC_EXT);
+ headerString.append("=\"");
+ headerString.append(ext);
+ }
+ headerString.append("\",");
+ headerString.append(OAuth2Message.MAC);
+ headerString.append("=\"");
+ headerString.append(mac);
+ headerString.append('\"');
+ return headerString.toString();
+ }
+
+ private static OAuth2HandlerError validateOAuth2Params(OAuth2Accessor accessor, HttpRequest request) {
+ if ((accessor == null) || (!accessor.isValid()) || (accessor.isErrorResponse())) {
+ return MacTokenHandler.getError("accessor is invalid " + accessor);
+ }
+
+ if (request == null) {
+ return MacTokenHandler.getError("request is null");
+ }
+
+ final OAuth2Token accessToken = accessor.getAccessToken();
+
+ if ((accessToken == null) || (accessToken.getTokenType().length() == 0)) {
+ return MacTokenHandler.getError("accessToken is invalid " + accessToken);
+ }
+
+ if (!MacTokenHandler.TOKEN_TYPE.equalsIgnoreCase(accessToken.getTokenType())) {
+ return MacTokenHandler.getError("token type mismatch expected " + MacTokenHandler.TOKEN_TYPE
+ + " but got " + accessToken.getTokenType());
+ }
+
+ final String algorithm = accessToken.getMacAlgorithm();
+ if ((algorithm == null) || (algorithm.length() == 0)) {
+ return MacTokenHandler.getError("invalid mac algorithm " + algorithm);
+ }
+
+ if (!OAuth2Message.HMAC_SHA_1.equalsIgnoreCase(algorithm)) {
+ return MacTokenHandler.getError("unsupported algorithm " + algorithm);
+ }
+
+ final byte[] macSecret = accessToken.getMacSecret();
+ if (macSecret == null) {
+ return MacTokenHandler.getError("mac secret is null");
+ }
+
+ if (macSecret.length == 0) {
+ return MacTokenHandler.getError("invalid mac secret");
+ }
+
+ return null;
+ }
+
+ public String getTokenType() {
+ return MacTokenHandler.TOKEN_TYPE;
+ }
+
+ private static String getBodyHash(final HttpRequest request, final byte[] key,
+ final String algorithm) throws UnsupportedEncodingException, GeneralSecurityException {
+ if (request.getPostBodyLength() > 0) {
+ final byte[] text = MacTokenHandler.getBody(request);
+ final byte[] hashed = MacTokenHandler.hash(text, key, algorithm);
+ return new String(hashed, "UTF-8");
+ }
+
+ return "";
+ }
+
+ private static byte[] getBody(final HttpRequest request) throws UnsupportedEncodingException {
+ return request.getPostBodyAsString().getBytes("UTF-8");
+ }
+
+ private static String getMac(final String nonce, final String method, final String uri,
+ final String host, final String port, final String bodyHash, final String ext,
+ final byte[] key, final String algorithm) throws UnsupportedEncodingException,
+ GeneralSecurityException {
+ final StringBuilder normalizedRequestString = MacTokenHandler.getNormalizedRequestString(nonce,
+ method, uri, host, port, bodyHash, ext);
+ final byte[] normalizedRequestBytes = normalizedRequestString.toString().getBytes("UTF-8");
+ final byte[] mac = MacTokenHandler.hash(normalizedRequestBytes, key, algorithm);
+ final byte[] encodedBytes = Base64.encodeBase64(mac);
+ return new String(encodedBytes, "UTF-8");
+ }
+
+ private static byte[] hash(final byte[] text, byte[] key, final String algorithm)
+ throws GeneralSecurityException {
+ if (OAuth2Message.HMAC_SHA_1.equalsIgnoreCase(algorithm)) {
+ return Crypto.hmacSha1(key, text);
+ }
+
+ return new byte[] {};
+ }
+
+ private static StringBuilder getNormalizedRequestString(final String nonce, final String method,
+ final String uri, final String host, final String port, final String bodyHash,
+ final String ext) {
+ final StringBuilder ret = new StringBuilder();
+ ret.append(nonce);
+ ret.append('\n');
+ ret.append(method);
+ ret.append('\n');
+ ret.append(uri);
+ ret.append('\n');
+ ret.append(host);
+ ret.append('\n');
+ ret.append(port);
+ ret.append('\n');
+ ret.append(bodyHash);
+ ret.append('\n');
+ ret.append(ext);
+ ret.append('\n');
+
+ return ret;
+ }
+
+ private static OAuth2HandlerError getError(final String contextMessage) {
+ return MacTokenHandler.getError(contextMessage, null);
+ }
+
+ private static OAuth2HandlerError getError(final String contextMessage, final Exception e) {
+ return new OAuth2HandlerError(MacTokenHandler.ERROR, contextMessage, e);
+ }
+}
Added: shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/handler/OAuth2HandlerError.java
URL: http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/handler/OAuth2HandlerError.java?rev=1182565&view=auto
==============================================================================
--- shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/handler/OAuth2HandlerError.java (added)
+++ shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/handler/OAuth2HandlerError.java Wed Oct 12 20:10:39 2011
@@ -0,0 +1,72 @@
+/*
+ * 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.apache.shindig.gadgets.oauth2.handler;
+
+import java.io.Serializable;
+
+import org.apache.shindig.gadgets.oauth2.OAuth2Error;
+
+/**
+ * Stores an error in the handler layer.
+ *
+ *
+ */
+public class OAuth2HandlerError implements Serializable {
+ private static final long serialVersionUID = 6533884367169476207L;
+
+ private final OAuth2Error error;
+ private final Exception cause;
+ private final String contextMessage;
+
+ public OAuth2HandlerError(final OAuth2Error error, final String contextMessage,
+ final Exception cause) {
+ this.error = error;
+ this.contextMessage = contextMessage;
+ this.cause = cause;
+ }
+
+ /**
+ *
+ * @return the {@link OAuth2Error} associated with this error
+ */
+ public OAuth2Error getError() {
+ return this.error;
+ }
+
+ /**
+ *
+ * @return underlying exception that caused is error or <code>null</code>
+ */
+ public Exception getCause() {
+ return this.cause;
+ }
+
+ /**
+ *
+ * @return non-translated message about the context of this error for
+ * debugging purposes
+ */
+ public String getContextMessage() {
+ return this.contextMessage;
+ }
+
+ @Override
+ public String toString() {
+ return OAuth2HandlerError.class.getName() + " : " + this.error + " : "
+ + this.getContextMessage() + " : " + this.cause;
+ }
+}
Added: shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/handler/OAuth2HandlerModule.java
URL: http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/handler/OAuth2HandlerModule.java?rev=1182565&view=auto
==============================================================================
--- shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/handler/OAuth2HandlerModule.java (added)
+++ shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/handler/OAuth2HandlerModule.java Wed Oct 12 20:10:39 2011
@@ -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.apache.shindig.gadgets.oauth2.handler;
+
+import java.util.List;
+
+import org.apache.shindig.gadgets.oauth2.logger.FilteredLogger;
+
+import com.google.common.collect.ImmutableList;
+import com.google.inject.AbstractModule;
+import com.google.inject.Provides;
+import com.google.inject.Singleton;
+
+/**
+ * Injects the default handlers.
+ *
+ */
+public class OAuth2HandlerModule extends AbstractModule {
+ private static final FilteredLogger LOG = FilteredLogger
+ .getFilteredLogger(OAuth2HandlerModule.class.getName());
+
+ @Override
+ protected void configure() {
+ if (OAuth2HandlerModule.LOG.isLoggable()) {
+ OAuth2HandlerModule.LOG.entering(OAuth2HandlerModule.class.getName(), "configure");
+ }
+ }
+
+ @Provides
+ @Singleton
+ static List<AuthorizationEndpointResponseHandler> provideAuthorizationEndpointResponseHandlers(
+ final CodeAuthorizationResponseHandler codeAuthorizationResponseHandler) {
+ return ImmutableList
+ .of((AuthorizationEndpointResponseHandler) codeAuthorizationResponseHandler);
+ }
+
+ @Provides
+ @Singleton
+ static List<ClientAuthenticationHandler> provideClientAuthenticationHandlers(
+ final BasicAuthenticationHandler basicAuthenticationHandler,
+ final StandardAuthenticationHandler standardAuthenticationHandler) {
+ return ImmutableList.of(basicAuthenticationHandler, standardAuthenticationHandler);
+ }
+
+ @Provides
+ @Singleton
+ static List<GrantRequestHandler> provideGrantRequestHandlers(
+ final ClientCredentialsGrantTypeHandler clientCredentialsGrantTypeHandler,
+ final CodeGrantTypeHandler codeGrantTypeHandler) {
+ return ImmutableList.of(clientCredentialsGrantTypeHandler, codeGrantTypeHandler);
+ }
+
+ @Provides
+ @Singleton
+ static List<TokenEndpointResponseHandler> provideTokenEndpointResponseHandlers(
+ final TokenAuthorizationResponseHandler tokenAuthorizationResponseHandler) {
+ return ImmutableList.of((TokenEndpointResponseHandler) tokenAuthorizationResponseHandler);
+ }
+
+ @Provides
+ @Singleton
+ static List<ResourceRequestHandler> provideTokenHandlers(
+ final BearerTokenHandler bearerTokenHandler, final MacTokenHandler macTokenHandler) {
+ return ImmutableList.of(bearerTokenHandler, macTokenHandler);
+ }
+}
\ No newline at end of file
Added: shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/handler/ResourceRequestHandler.java
URL: http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/handler/ResourceRequestHandler.java?rev=1182565&view=auto
==============================================================================
--- shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/handler/ResourceRequestHandler.java (added)
+++ shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/handler/ResourceRequestHandler.java Wed Oct 12 20:10:39 2011
@@ -0,0 +1,50 @@
+/*
+ * 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.apache.shindig.gadgets.oauth2.handler;
+
+import org.apache.shindig.gadgets.http.HttpRequest;
+import org.apache.shindig.gadgets.oauth2.OAuth2Accessor;
+import org.apache.shindig.gadgets.oauth2.OAuth2Token;
+
+/**
+ *
+ * Enables inject of token type handlers to add OAuth2 auth data to resource
+ * requests.
+ *
+ * By default shindig supports "Bearer" token types.
+ *
+ * Matches on {@link OAuth2Token#getTokenType()}
+ *
+ * All matching handlers are executed.
+ *
+ */
+public interface ResourceRequestHandler {
+ /**
+ * Do the handler magic for the token type.
+ *
+ * @param accessor
+ * @param request
+ * @return {@link OAuth2HandlerError} if one occurs
+ */
+ public OAuth2HandlerError addOAuth2Params(final OAuth2Accessor accessor, final HttpRequest request);
+
+ /**
+ *
+ * @return the token type this handler handles
+ */
+ public String getTokenType();
+}
Added: shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/handler/StandardAuthenticationHandler.java
URL: http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/handler/StandardAuthenticationHandler.java?rev=1182565&view=auto
==============================================================================
--- shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/handler/StandardAuthenticationHandler.java (added)
+++ shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/handler/StandardAuthenticationHandler.java Wed Oct 12 20:10:39 2011
@@ -0,0 +1,88 @@
+/*
+ * 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.apache.shindig.gadgets.oauth2.handler;
+
+import org.apache.shindig.gadgets.http.HttpRequest;
+import org.apache.shindig.gadgets.oauth2.OAuth2Accessor;
+import org.apache.shindig.gadgets.oauth2.OAuth2Error;
+import org.apache.shindig.gadgets.oauth2.OAuth2Message;
+
+/**
+ *
+ * See {@link ClientAuthenticationHandler}
+ *
+ * Handler for Basic Authentication
+ *
+ */
+public class StandardAuthenticationHandler implements ClientAuthenticationHandler {
+ private static final OAuth2Error ERROR = OAuth2Error.AUTHENTICATION_PROBLEM;
+
+ public StandardAuthenticationHandler() {
+ }
+
+ public OAuth2HandlerError addOAuth2Authentication(final HttpRequest request,
+ final OAuth2Accessor accessor) {
+ try {
+ if (request == null) {
+ return StandardAuthenticationHandler.getError("request is null");
+ }
+
+ if (accessor == null) {
+ return StandardAuthenticationHandler.getError("accessor is null");
+ }
+
+ if (!accessor.isValid() || accessor.isErrorResponse()) {
+ return StandardAuthenticationHandler.getError("accessor is invalid");
+ }
+
+ final String clientId = accessor.getClientId();
+
+ if (clientId == null) {
+ return StandardAuthenticationHandler.getError("client_id is null");
+ }
+
+ final byte[] secretBytes = accessor.getClientSecret();
+
+ if (secretBytes == null) {
+ return StandardAuthenticationHandler.getError("client_secret is secret");
+ }
+
+ final String secret = new String(secretBytes, "UTF-8");
+
+ request.setHeader(OAuth2Message.CLIENT_ID, clientId);
+ request.setParam(OAuth2Message.CLIENT_ID, clientId);
+ request.setHeader(OAuth2Message.CLIENT_SECRET, secret);
+ request.setParam(OAuth2Message.CLIENT_SECRET, secret);
+
+ return null;
+ } catch (final Exception e) {
+ return StandardAuthenticationHandler.getError("Exception adding standard auth headers", e);
+ }
+ }
+
+ public String geClientAuthenticationType() {
+ return OAuth2Message.STANDARD_AUTH_TYPE;
+ }
+
+ private static OAuth2HandlerError getError(final String contextMessage) {
+ return StandardAuthenticationHandler.getError(contextMessage, null);
+ }
+
+ private static OAuth2HandlerError getError(final String contextMessage, final Exception e) {
+ return new OAuth2HandlerError(StandardAuthenticationHandler.ERROR, contextMessage, e);
+ }
+}
\ No newline at end of file
Added: shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/handler/TokenAuthorizationResponseHandler.java
URL: http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/handler/TokenAuthorizationResponseHandler.java?rev=1182565&view=auto
==============================================================================
--- shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/handler/TokenAuthorizationResponseHandler.java (added)
+++ shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/handler/TokenAuthorizationResponseHandler.java Wed Oct 12 20:10:39 2011
@@ -0,0 +1,211 @@
+/*
+ * 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.apache.shindig.gadgets.oauth2.handler;
+
+import java.util.Map;
+
+import org.apache.shindig.gadgets.http.HttpResponse;
+import org.apache.shindig.gadgets.oauth2.OAuth2Accessor;
+import org.apache.shindig.gadgets.oauth2.OAuth2Error;
+import org.apache.shindig.gadgets.oauth2.OAuth2Message;
+import org.apache.shindig.gadgets.oauth2.OAuth2Store;
+import org.apache.shindig.gadgets.oauth2.OAuth2Token;
+import org.apache.shindig.gadgets.oauth2.logger.FilteredLogger;
+import org.json.JSONObject;
+
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+
+/**
+ *
+ * See {@link TokenEndpointResponseHandler}
+ *
+ * Handles the "client_credentials" flow
+ */
+public class TokenAuthorizationResponseHandler implements TokenEndpointResponseHandler {
+ private final static String LOG_CLASS = CodeAuthorizationResponseHandler.class.getName();
+ private static final FilteredLogger LOG = FilteredLogger
+ .getFilteredLogger(TokenAuthorizationResponseHandler.LOG_CLASS);
+
+ private static final OAuth2Error ERROR = OAuth2Error.TOKEN_RESPONSE_PROBLEM;
+
+ private final Provider<OAuth2Message> oauth2MessageProvider;
+ private final OAuth2Store store;
+
+ @Inject
+ public TokenAuthorizationResponseHandler(final Provider<OAuth2Message> oauth2MessageProvider,
+ final OAuth2Store store) {
+ this.oauth2MessageProvider = oauth2MessageProvider;
+ this.store = store;
+
+ if (TokenAuthorizationResponseHandler.LOG.isLoggable()) {
+ TokenAuthorizationResponseHandler.LOG.log("this.oauth2MessageProvider = {0}",
+ this.oauth2MessageProvider);
+ TokenAuthorizationResponseHandler.LOG.log("this.store = {0}", this.store);
+ }
+ }
+
+ public OAuth2HandlerError handleResponse(final OAuth2Accessor accessor,
+ final HttpResponse response) {
+ final boolean isLogging = TokenAuthorizationResponseHandler.LOG.isLoggable();
+
+ if (isLogging) {
+ if (response != null) {
+ TokenAuthorizationResponseHandler.LOG.entering(TokenAuthorizationResponseHandler.LOG_CLASS,
+ "getAuthorizationBody", new Object[] { accessor, "non-null response" });
+ } else {
+ TokenAuthorizationResponseHandler.LOG.entering(TokenAuthorizationResponseHandler.LOG_CLASS,
+ "getAuthorizationBody", new Object[] { accessor, null });
+ }
+ }
+
+ OAuth2HandlerError ret = null;
+
+ try {
+ if (response == null) {
+ ret = TokenAuthorizationResponseHandler.getError("response is null");
+ }
+
+ if ((ret == null)
+ && ((accessor == null) || (!accessor.isValid()) || (accessor.isErrorResponse()))) {
+ ret = TokenAuthorizationResponseHandler.getError("accessor is invalid " + accessor);
+ }
+
+ if ((ret == null) && (response != null)) {
+ final int responseCode = response.getHttpStatusCode();
+ if (responseCode != HttpResponse.SC_OK) {
+ ret = TokenAuthorizationResponseHandler.getError("can't handle error response code "
+ + responseCode);
+ }
+
+ if (ret == null) {
+ final long issuedAt = System.currentTimeMillis() / 1000;
+
+ final String contentType = response.getHeader("Content-Type");
+ final String responseString = response.getResponseAsString();
+ final OAuth2Message msg = this.oauth2MessageProvider.get();
+
+ if (contentType.startsWith("text/plain")) {
+ // Facebook does this
+ msg.parseQuery("?" + responseString);
+ } else if (contentType.startsWith("application/json")) {
+ // Google does this
+ final JSONObject responseJson = new JSONObject(responseString);
+ msg.parseJSON(responseJson.toString());
+ } else {
+ if (isLogging) {
+ TokenAuthorizationResponseHandler.LOG.log("Unhandled Content-Type {0}", contentType);
+ TokenAuthorizationResponseHandler.LOG.exiting(
+ TokenAuthorizationResponseHandler.LOG_CLASS, "handleResponse", null);
+ }
+ ret = TokenAuthorizationResponseHandler.getError("Unhandled Content-Type "
+ + contentType);
+ }
+
+ final OAuth2Error error = msg.getError();
+ if ((error == null) && (accessor != null)) {
+ final String accessToken = msg.getAccessToken();
+ final String refreshToken = msg.getRefreshToken();
+ final String expiresIn = msg.getExpiresIn();
+ final String tokenType = msg.getTokenType();
+ final String providerName = accessor.getServiceName();
+ final String gadgetUri = accessor.getGadgetUri();
+ final String scope = accessor.getScope();
+ final String user = accessor.getUser();
+ final String macAlgorithm = msg.getMacAlgorithm();
+ final String macSecret = msg.getMacSecret();
+ final Map<String, String> unparsedProperties = msg.getUnparsedProperties();
+
+ if (accessToken != null) {
+ final OAuth2Token storedAccessToken = this.store.createToken();
+ storedAccessToken.setIssuedAt(issuedAt);
+ if (expiresIn != null) {
+ storedAccessToken.setExpiresAt(issuedAt + Long.decode(expiresIn));
+ } else {
+ storedAccessToken.setExpiresAt(0);
+ }
+ storedAccessToken.setGadgetUri(gadgetUri);
+ storedAccessToken.setServiceName(providerName);
+ storedAccessToken.setScope(scope);
+ storedAccessToken.setSecret(accessToken.getBytes("UTF-8"));
+ storedAccessToken.setTokenType(tokenType);
+ storedAccessToken.setType(OAuth2Token.Type.ACCESS);
+ storedAccessToken.setUser(user);
+ if (macAlgorithm != null) {
+ storedAccessToken.setMacAlgorithm(macAlgorithm);
+ }
+ if (macSecret != null) {
+ storedAccessToken.setMacSecret(macSecret.getBytes("UTF-8"));
+ }
+ storedAccessToken.setProperties(unparsedProperties);
+ this.store.setToken(storedAccessToken);
+ accessor.setAccessToken(storedAccessToken);
+ }
+
+ if (refreshToken != null) {
+ final OAuth2Token storedRefreshToken = this.store.createToken();
+ storedRefreshToken.setExpiresAt(0);
+ storedRefreshToken.setGadgetUri(gadgetUri);
+ storedRefreshToken.setServiceName(providerName);
+ storedRefreshToken.setScope(scope);
+ storedRefreshToken.setSecret(refreshToken.getBytes("UTF-8"));
+ storedRefreshToken.setTokenType(tokenType);
+ storedRefreshToken.setType(OAuth2Token.Type.REFRESH);
+ storedRefreshToken.setUser(user);
+ this.store.setToken(storedRefreshToken);
+ accessor.setRefreshToken(storedRefreshToken);
+ }
+ }
+ }
+ }
+ } catch (final Exception e) {
+ if (isLogging) {
+ TokenAuthorizationResponseHandler.LOG.log(
+ "exception thrown handling authorization response", e);
+ }
+ return TokenAuthorizationResponseHandler.getError(
+ "exception thrown handling authorization response", e);
+ }
+
+ if (isLogging) {
+ TokenAuthorizationResponseHandler.LOG.exiting(TokenAuthorizationResponseHandler.LOG_CLASS,
+ "handleResponse", ret);
+ }
+
+ return ret;
+ }
+
+ public boolean handlesResponse(final OAuth2Accessor accessor, final HttpResponse response) {
+ if ((accessor == null) || (!accessor.isValid()) || (accessor.isErrorResponse())) {
+ return false;
+ }
+
+ if (response == null) {
+ return false;
+ }
+
+ return true;
+ }
+
+ private static OAuth2HandlerError getError(final String contextMessage) {
+ return TokenAuthorizationResponseHandler.getError(contextMessage, null);
+ }
+
+ private static OAuth2HandlerError getError(final String contextMessage, final Exception e) {
+ return new OAuth2HandlerError(TokenAuthorizationResponseHandler.ERROR, contextMessage, e);
+ }
+}
Added: shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/handler/TokenEndpointResponseHandler.java
URL: http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/handler/TokenEndpointResponseHandler.java?rev=1182565&view=auto
==============================================================================
--- shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/handler/TokenEndpointResponseHandler.java (added)
+++ shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/handler/TokenEndpointResponseHandler.java Wed Oct 12 20:10:39 2011
@@ -0,0 +1,60 @@
+/*
+ * 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.apache.shindig.gadgets.oauth2.handler;
+
+import org.apache.shindig.gadgets.http.HttpResponse;
+import org.apache.shindig.gadgets.oauth2.OAuth2Accessor;
+
+/**
+ * When an TokenEndpointResponseHandler is injected into the system it will be
+ * called on every response from the token server that it claims to handle.
+ *
+ * See {@link http://tools.ietf.org/html/draft-ietf-oauth-v2-21#section-4}
+ *
+ * By default shindig has handlers for the Authorization Code and Client
+ * Credential flows.
+ *
+ */
+public interface TokenEndpointResponseHandler {
+ /**
+ * Let the handler do it's magic including any accessor/store updates.
+ *
+ * If the handler is executed and encountered an error that should stop the
+ * authorization process it should return the appropriate
+ * {@link OAuth2HandlerError}.
+ *
+ *
+ * Applies in particular to the client_credentials flow.
+ *
+ * See {@link http://tools.ietf.org/html/draft-ietf-oauth-v2-21#section-4.4.1}
+ *
+ * @param accessor
+ * @param response
+ * @return see above
+ */
+ public OAuth2HandlerError handleResponse(OAuth2Accessor accessor, HttpResponse response);
+
+ /**
+ * Does the handler support this {@link OAuth2Accessor} / {@link HttpResponse}
+ * response?
+ *
+ * @param accessor
+ * @param request
+ * @return <code>true</code> if handleRequest() should be invoked
+ */
+ public boolean handlesResponse(OAuth2Accessor accessor, HttpResponse response);
+}
Added: shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/logger/FilteredLogger.java
URL: http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/logger/FilteredLogger.java?rev=1182565&view=auto
==============================================================================
--- shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/logger/FilteredLogger.java (added)
+++ shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/logger/FilteredLogger.java Wed Oct 12 20:10:39 2011
@@ -0,0 +1,150 @@
+/*
+ * 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.apache.shindig.gadgets.oauth2.logger;
+
+import java.util.ResourceBundle;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.shindig.gadgets.oauth2.OAuth2Error;
+
+/**
+ * Wraps a {@link Logger} with functions to remove OAuth2 secrets so they don't
+ * show up in trace logs.
+ *
+ */
+public class FilteredLogger {
+ private static final Level DEFAULT_LOG_LEVEL = Level.FINEST;
+
+ private static final Pattern REMOVE_SECRETS1 = Pattern.compile("(?<=access_token=)[^=& \t\r\n]*");
+ private static final Pattern REMOVE_SECRETS2 = Pattern.compile("(Authorization:)[^\t\r\n]*");
+
+ private static String filteredMsg(final String msg) {
+ return FilteredLogger.filterSecrets(msg);
+ }
+
+ private static String filteredParam(final Object param) {
+ final String _param;
+ if (param != null) {
+ _param = FilteredLogger.filterSecrets(param.toString());
+ } else {
+ _param = "";
+ }
+
+ return _param;
+ }
+
+ private static String[] filteredParams(final Object[] params) {
+ final String[] _params;
+ if (params != null) {
+ _params = new String[params.length];
+ int i = 0;
+ for (final Object param : params) {
+ if (param != null) {
+ _params[i] = FilteredLogger.filteredMsg(param.toString());
+ } else {
+ _params[i] = "";
+ }
+ i++;
+ }
+ } else {
+ _params = new String[] {};
+ }
+
+ return _params;
+ }
+
+ public static String filterSecrets(String in) {
+ if ((in != null) && (in.length() > 0)) {
+ Matcher m = FilteredLogger.REMOVE_SECRETS1.matcher(in);
+ final String ret = m.replaceAll("REMOVED");
+ m = FilteredLogger.REMOVE_SECRETS2.matcher(ret);
+ return m.replaceAll("REMOVED");
+ }
+
+ return "";
+ }
+
+ public static FilteredLogger getFilteredLogger(final String className) {
+ return new FilteredLogger(className);
+ }
+
+ private final Logger logger;
+
+ protected FilteredLogger(final String className) {
+ this.logger = java.util.logging.Logger.getLogger(className, OAuth2Error.MESSAGES);
+ }
+
+ public void entering(String sourceClass, String sourceMethod) {
+ this.logger.entering(sourceClass, sourceMethod);
+ }
+
+ public void entering(String sourceClass, String sourceMethod, Object param) {
+ this.logger.entering(sourceClass, sourceMethod, FilteredLogger.filteredParam(param));
+ }
+
+ public void entering(String sourceClass, String sourceMethod, Object[] params) {
+ this.logger.entering(sourceClass, sourceMethod, FilteredLogger.filteredParams(params));
+ }
+
+ public ResourceBundle getResourceBundle() {
+ return this.logger.getResourceBundle();
+ }
+
+ public boolean isLoggable() {
+ return this.isLoggable(FilteredLogger.DEFAULT_LOG_LEVEL);
+ }
+
+ public boolean isLoggable(final Level logLevel) {
+ return this.logger.isLoggable(logLevel);
+ }
+
+ public void log(Level logLevel, String msg, Object param) {
+ this.logger.log(logLevel, FilteredLogger.filteredMsg(msg), FilteredLogger.filteredParam(param));
+ }
+
+ public void log(Level logLevel, String msg, Object[] params) {
+ this.logger.log(logLevel, FilteredLogger.filteredMsg(msg),
+ FilteredLogger.filteredParams(params));
+ }
+
+ public void log(Level logLevel, String msg, Throwable thrown) {
+ this.logger.log(logLevel, FilteredLogger.filterSecrets(msg), thrown);
+ }
+
+ public void log(String msg, Object param) {
+ this.log(FilteredLogger.DEFAULT_LOG_LEVEL, msg, param);
+ }
+
+ public void log(String msg, Object[] params) {
+ this.log(FilteredLogger.DEFAULT_LOG_LEVEL, msg, params);
+ }
+
+ public void log(String msg, Throwable thrown) {
+ this.logger.log(FilteredLogger.DEFAULT_LOG_LEVEL, msg, thrown);
+ }
+
+ public void exiting(String sourceClass, String sourceMethod) {
+ this.logger.exiting(sourceClass, sourceMethod);
+ }
+
+ public void exiting(String sourceClass, String sourceMethod, Object result) {
+ this.logger.exiting(sourceClass, sourceMethod, FilteredLogger.filteredParam(result));
+ }
+}
\ No newline at end of file
Added: shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/persistence/OAuth2Cache.java
URL: http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/persistence/OAuth2Cache.java?rev=1182565&view=auto
==============================================================================
--- shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/persistence/OAuth2Cache.java (added)
+++ shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/persistence/OAuth2Cache.java Wed Oct 12 20:10:39 2011
@@ -0,0 +1,175 @@
+/*
+ * 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.apache.shindig.gadgets.oauth2.persistence;
+
+import java.util.Collection;
+
+import org.apache.shindig.gadgets.oauth2.OAuth2Accessor;
+import org.apache.shindig.gadgets.oauth2.OAuth2Store;
+import org.apache.shindig.gadgets.oauth2.OAuth2Token;
+
+/**
+ * Used by {@link OAuth2Store} to cache OAuth2 data.
+ *
+ * Default implementation is in-memory HashMaps for shindig.
+ *
+ */
+public interface OAuth2Cache {
+ /**
+ * Clears all cached {@link OAuth2Client}s.
+ *
+ * @throws OAuth2CacheException
+ */
+ void clearClients() throws OAuth2CacheException;
+
+ /**
+ * Clears all cached {@link OAuth2Token}s.
+ *
+ * @throws OAuth2CacheException
+ */
+ void clearTokens() throws OAuth2CacheException;
+
+ /**
+ * Find an {@link OAuth2Client} by {@link Integer} index.
+ *
+ * @param index
+ * @return OAuth2Client
+ */
+ OAuth2Client getClient(Integer index);
+
+ /**
+ * Generate an {@link OAuth2Client} index for the given mapping.
+ *
+ * @param gadgetUri
+ * @param serviceName
+ * @return client index
+ */
+ Integer getClientIndex(String gadgetUri, String serviceName);
+
+ /**
+ * Find an {@link OAuth2Accessor} by index.
+ *
+ * @param index
+ * @return OAuth2Accessor
+ */
+ OAuth2Accessor getOAuth2Accessor(Integer index);
+
+ /**
+ * Generate in index for an {@link OAuth2Accessor} by the given parameters.
+ *
+ * @param gadgetUri
+ * @param serviceName
+ * @param user
+ * @param scope
+ * @return index for the OAuth2Accessor
+ */
+ Integer getOAuth2AccessorIndex(String gadgetUri, String serviceName, String user, String scope);
+
+ /**
+ * Find an {@link OAuth2Token} based on index
+ *
+ * @param index
+ * @return an OAuth2Token
+ */
+ OAuth2Token getToken(Integer index);
+
+ /**
+ * Returns the {@link Integer} index for the given {@link OAuth2Token}.
+ *
+ * @param token
+ * @return index of the OAuth2Token
+ */
+ Integer getTokenIndex(OAuth2Token token);
+
+ /**
+ * Generate index for {@link OAuth2Token} based on parameters
+ *
+ * @param gadgetUri
+ * @param serviceName
+ * @param user
+ * @param scope
+ * @param type
+ * @return index of OAuth2Token
+ */
+ Integer getTokenIndex(String gadgetUri, String serviceName, String user, String scope,
+ OAuth2Token.Type type);
+
+ /**
+ * Removes the {@link OAuth2Client} from the cache.
+ *
+ * @param index
+ * @return the removed client, or <code>null</code> if none was found
+ * @throws OAuth2CacheException
+ */
+ OAuth2Client removeClient(Integer index) throws OAuth2CacheException;
+
+ /**
+ * Removes the given {@link OAuth2Accessor} from the cache.
+ *
+ * @param index
+ * @return the removed {@link OAuth2Accessor} or <code>null</code> if none was
+ * found
+ */
+ OAuth2Accessor removeOAuth2Accessor(Integer index);
+
+ /**
+ * Removes the given {@link OAuth2Token} from the cache.
+ *
+ * @param index
+ * @return the removed {@link OAuth2Token} or <code>null</code> if none was
+ * found
+ * @throws OAuth2CacheException
+ */
+ OAuth2Token removeToken(Integer index) throws OAuth2CacheException;
+
+ /**
+ * Stores the given client.
+ *
+ * @param index
+ * @param client
+ * @throws OAuth2CacheException
+ */
+ Integer storeClient(OAuth2Client client) throws OAuth2CacheException;
+
+ /**
+ * Store all clients in the collection.
+ *
+ * @param clients
+ * @throws OAuth2CacheException
+ */
+ void storeClients(Collection<OAuth2Client> clients) throws OAuth2CacheException;
+
+ /**
+ * Stores the given accessor.
+ *
+ * @param accessor
+ */
+ Integer storeOAuth2Accessor(OAuth2Accessor accessor);
+
+ /**
+ * Stores the given token and returns it's index.
+ */
+ Integer storeToken(OAuth2Token token) throws OAuth2CacheException;
+
+ /**
+ * Stores all tokens in the collection.
+ *
+ * @param tokens
+ * @throws OAuth2CacheException
+ */
+ void storeTokens(Collection<OAuth2Token> tokens) throws OAuth2CacheException;
+}
Added: shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/persistence/OAuth2CacheException.java
URL: http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/persistence/OAuth2CacheException.java?rev=1182565&view=auto
==============================================================================
--- shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/persistence/OAuth2CacheException.java (added)
+++ shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/persistence/OAuth2CacheException.java Wed Oct 12 20:10:39 2011
@@ -0,0 +1,29 @@
+/*
+ * 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.apache.shindig.gadgets.oauth2.persistence;
+
+/**
+ * Subclass of {@link OAuth2PersistenceException} for caching issues.
+ *
+ */
+public class OAuth2CacheException extends OAuth2PersistenceException {
+ private static final long serialVersionUID = -7722454386821962603L;
+
+ public OAuth2CacheException(final Exception cause) {
+ super(cause);
+ }
+}
Added: shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/persistence/OAuth2Client.java
URL: http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/persistence/OAuth2Client.java?rev=1182565&view=auto
==============================================================================
--- shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/persistence/OAuth2Client.java (added)
+++ shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/persistence/OAuth2Client.java Wed Oct 12 20:10:39 2011
@@ -0,0 +1,244 @@
+/*
+ * 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.apache.shindig.gadgets.oauth2.persistence;
+
+import java.io.Serializable;
+
+import org.apache.shindig.gadgets.oauth2.OAuth2Accessor;
+import org.apache.shindig.gadgets.oauth2.OAuth2Message;
+
+import com.google.inject.Inject;
+
+/**
+ * Data class for client data stored in persistence.
+ *
+ * Uses the injected {@link OAuth2Encrypter} protect the client_secret in the
+ * persistence store.
+ *
+ */
+public class OAuth2Client implements Serializable {
+ private static final long serialVersionUID = -6090033505867216220L;
+
+ private boolean allowModuleOverride;
+ private boolean authorizationHeader;
+ private String authorizationUrl;
+ private String clientAuthenticationType;
+ private String clientId;
+ private byte[] clientSecret;
+ private byte[] encryptedSecret;
+ private transient final OAuth2Encrypter encrypter;
+ private String gadgetUri;
+ private String grantType = OAuth2Message.NO_GRANT_TYPE;
+ private String redirectUri;
+ private String serviceName;
+ private String tokenUrl;
+ private OAuth2Accessor.Type type = OAuth2Accessor.Type.UNKNOWN;
+ private boolean urlParameter;
+
+ @Inject
+ public OAuth2Client(final OAuth2Encrypter encrypter) {
+ this.encrypter = encrypter;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (obj == this) {
+ return true;
+ }
+ if (!(obj instanceof OAuth2Client)) {
+ return false;
+ }
+ final OAuth2Client other = (OAuth2Client) obj;
+ if (this.gadgetUri == null) {
+ if (other.gadgetUri != null) {
+ return false;
+ }
+ } else if (!this.gadgetUri.equals(other.gadgetUri)) {
+ return false;
+ }
+ if (this.serviceName == null) {
+ if (other.serviceName != null) {
+ return false;
+ }
+ } else if (!this.serviceName.equals(other.serviceName)) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Returns authorization endpoint
+ *
+ * @return authorization endpoint
+ */
+ public String getAuthorizationUrl() {
+ return this.authorizationUrl;
+ }
+
+ /**
+ * Returns client authentication type
+ *
+ * @return client authentication type
+ */
+ public String getClientAuthenticationType() {
+ return this.clientAuthenticationType;
+ }
+
+ /**
+ * Returns client id.
+ *
+ * @return client id
+ */
+ public String getClientId() {
+ return this.clientId;
+ }
+
+ /**
+ * Returns client secret
+ *
+ * @return client secret
+ */
+ public byte[] getClientSecret() {
+ return this.clientSecret;
+ }
+
+ /**
+ * Returns encrypted secret
+ *
+ * @return encrypted secret
+ */
+ public byte[] getEncryptedSecret() {
+ return this.encryptedSecret;
+ }
+
+ public OAuth2Encrypter getEncrypter() {
+ return this.encrypter;
+ }
+
+ public String getGadgetUri() {
+ return this.gadgetUri;
+ }
+
+ public String getGrantType() {
+ return this.grantType;
+ }
+
+ public String getRedirectUri() {
+ return this.redirectUri;
+ }
+
+ public String getServiceName() {
+ return this.serviceName;
+ }
+
+ public String getTokenUrl() {
+ return this.tokenUrl;
+ }
+
+ public OAuth2Accessor.Type getType() {
+ return this.type;
+ }
+
+ @Override
+ public int hashCode() {
+ if ((this.serviceName != null) && (this.gadgetUri != null)) {
+ return (this.serviceName + ":" + this.gadgetUri).hashCode();
+ }
+
+ return 0;
+ }
+
+ public boolean isAllowModuleOverride() {
+ return this.allowModuleOverride;
+ }
+
+ public boolean isAuthorizationHeader() {
+ return this.authorizationHeader;
+ }
+
+ public boolean isUrlParameter() {
+ return this.urlParameter;
+ }
+
+ public void setAllowModuleOverride(final boolean alllowModuleOverride) {
+ this.allowModuleOverride = alllowModuleOverride;
+ }
+
+ public void setAuthorizationHeader(boolean authorizationHeader) {
+ this.authorizationHeader = authorizationHeader;
+ }
+
+ public void setAuthorizationUrl(final String authorizationUrl) {
+ this.authorizationUrl = authorizationUrl;
+ }
+
+ public void setClientAuthenticationType(final String clientAuthenticationType) {
+ this.clientAuthenticationType = clientAuthenticationType;
+ }
+
+ public void setClientId(final String clientId) {
+ this.clientId = clientId;
+ }
+
+ public void setClientSecret(final byte[] secret) throws OAuth2EncryptionException {
+ this.clientSecret = secret;
+ this.encryptedSecret = this.encrypter.encrypt(secret);
+ }
+
+ public void setEncryptedSecret(final byte[] encryptedSecret) throws OAuth2EncryptionException {
+ this.encryptedSecret = encryptedSecret;
+ this.clientSecret = this.encrypter.decrypt(encryptedSecret);
+ }
+
+ public void setGadgetUri(final String gadgetUri) {
+ this.gadgetUri = gadgetUri;
+ }
+
+ public void setGrantType(final String grantType) {
+ this.grantType = grantType;
+ }
+
+ public void setRedirectUri(final String redirectUri) {
+ this.redirectUri = redirectUri;
+ }
+
+ public void setServiceName(final String serviceName) {
+ this.serviceName = serviceName;
+ }
+
+ public void setTokenUrl(final String tokenUrl) {
+ this.tokenUrl = tokenUrl;
+ }
+
+ public void setType(final OAuth2Accessor.Type type) {
+ this.type = type;
+ }
+
+ public void setUrlParameter(boolean urlParameter) {
+ this.urlParameter = urlParameter;
+ }
+
+ @Override
+ public String toString() {
+ return "org.apache.shindig.gadgets.oauth2.persistence.sample.OAuth2ClientImpl: serviceName = "
+ + this.serviceName + " , redirectUri = " + this.redirectUri + " , gadgetUri = "
+ + this.gadgetUri + " , clientId = " + this.clientId + " , grantType = " + this.grantType
+ + " , type = " + this.type.name() + " , grantType = " + this.grantType + " , tokenUrl = "
+ + this.tokenUrl + " , authorizationUrl = " + this.authorizationUrl
+ + " , this.clientAuthenticationType = " + this.clientAuthenticationType;
+ }
+}
Added: shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/persistence/OAuth2Encrypter.java
URL: http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/persistence/OAuth2Encrypter.java?rev=1182565&view=auto
==============================================================================
--- shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/persistence/OAuth2Encrypter.java (added)
+++ shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/persistence/OAuth2Encrypter.java Wed Oct 12 20:10:39 2011
@@ -0,0 +1,44 @@
+/*
+ * 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.apache.shindig.gadgets.oauth2.persistence;
+
+
+/**
+ * Injected into the system to encrypt/decrypt client and token secrets in the
+ * persistence layer.
+ *
+ * This does not apply to any broader concept of token signing or other signing
+ * from the OAuth 1.0 implementation.
+ *
+ */
+public interface OAuth2Encrypter {
+ /**
+ * Decrypts client and token secret
+ *
+ * @param encryptedSecret
+ * @return decryptedSecret
+ */
+ public byte[] decrypt(byte[] encryptedSecret) throws OAuth2EncryptionException;
+
+ /**
+ * Encrypts client and token secret
+ *
+ * @param plainSecret
+ * @return encryptedSecret
+ */
+ public byte[] encrypt(byte[] plainSecret) throws OAuth2EncryptionException;
+}
Added: shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/persistence/OAuth2EncryptionException.java
URL: http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/persistence/OAuth2EncryptionException.java?rev=1182565&view=auto
==============================================================================
--- shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/persistence/OAuth2EncryptionException.java (added)
+++ shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/persistence/OAuth2EncryptionException.java Wed Oct 12 20:10:39 2011
@@ -0,0 +1,32 @@
+/*
+ * 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.apache.shindig.gadgets.oauth2.persistence;
+
+import org.apache.shindig.gadgets.GadgetException;
+
+/**
+ * Subclass of {@link OAuth2PersistenceException} for secret
+ * encryption/decryption issues.
+ *
+ */
+public class OAuth2EncryptionException extends GadgetException {
+ private static final long serialVersionUID = -3884237661767049433L;
+
+ public OAuth2EncryptionException(final Exception cause) {
+ super(Code.OAUTH_STORAGE_ERROR, cause);
+ }
+}
Added: shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/persistence/OAuth2PersistenceException.java
URL: http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/persistence/OAuth2PersistenceException.java?rev=1182565&view=auto
==============================================================================
--- shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/persistence/OAuth2PersistenceException.java (added)
+++ shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/persistence/OAuth2PersistenceException.java Wed Oct 12 20:10:39 2011
@@ -0,0 +1,28 @@
+/*
+ * 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.apache.shindig.gadgets.oauth2.persistence;
+
+/**
+ * Exception class for errors that occur in the persistence layer.
+ */
+public class OAuth2PersistenceException extends Exception {
+ private static final long serialVersionUID = -8550943441259921635L;
+
+ public OAuth2PersistenceException(final Exception cause) {
+ super(cause);
+ }
+}
Added: shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/persistence/OAuth2Persister.java
URL: http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/persistence/OAuth2Persister.java?rev=1182565&view=auto
==============================================================================
--- shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/persistence/OAuth2Persister.java (added)
+++ shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/persistence/OAuth2Persister.java Wed Oct 12 20:10:39 2011
@@ -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.apache.shindig.gadgets.oauth2.persistence;
+
+import java.util.Set;
+
+import org.apache.shindig.gadgets.oauth2.BasicOAuth2Store;
+import org.apache.shindig.gadgets.oauth2.OAuth2Accessor;
+import org.apache.shindig.gadgets.oauth2.OAuth2Store;
+import org.apache.shindig.gadgets.oauth2.OAuth2Token;
+import org.apache.shindig.gadgets.oauth2.persistence.sample.JSONOAuth2Persister;
+
+/**
+ * Interface, used primarily by {@link OAuth2Store}, to manage
+ * {@link OAuth2Accessor} and {@link OAuth2Token} storage.
+ *
+ * An {@link OAuth2Accessor} has the same basic information as the
+ * {@link OAuth2Client}, merged with gadget spec and request prefs.
+ *
+ * {@link OAuth2Accessor} is short lived, for the life of one request.
+ *
+ * {@link OAuth2Clients} is intended to be persisted and cached.
+ *
+ * The default persister for shindig is {@link JSONOAuth2Persister}
+ *
+ */
+public interface OAuth2Persister {
+ /**
+ *
+ * @return a new {@link OAuth2Token} suitable for initialization and storage.
+ */
+ OAuth2Token createToken();
+
+ /**
+ *
+ * @param gadgetUri
+ * @param serviceName
+ * @return the client in the given mapping
+ * @throws OAuth2PersistenceException
+ */
+ OAuth2Client findClient(String gadgetUri, String serviceName) throws OAuth2PersistenceException;
+
+ /**
+ *
+ * @param gadgetUri
+ * @param serviceName
+ * @param user
+ * @param scope
+ * @param type
+ * @return the token in the given mapping
+ * @throws OAuth2PersistenceException
+ */
+ OAuth2Token findToken(String gadgetUri, String serviceName, String user, String scope,
+ OAuth2Token.Type type) throws OAuth2PersistenceException;
+
+ /**
+ * Inserts a new {@link OAuth2Token} into the persistence layer.
+ *
+ * @param token
+ * @throws OAuth2PersistenceException
+ */
+ void insertToken(OAuth2Token token) throws OAuth2PersistenceException;
+
+ /**
+ * Load all the clients from the persistence layer. The
+ * {@link BasicOAuth2Store#init()} method will call this to prepopulate the
+ * cache.
+ *
+ * @return
+ * @throws OAuth2PersistenceException
+ */
+ Set<OAuth2Client> loadClients() throws OAuth2PersistenceException;
+
+ /**
+ * Load all the tokens from the persistence layer. The
+ * {@link BasicOAuth2Store#init()} method will call this to prepopulate the
+ * cache.
+ *
+ * @return
+ * @throws OAuth2PersistenceException
+ */
+ Set<OAuth2Token> loadTokens() throws OAuth2PersistenceException;
+
+ /**
+ * Removes a token from the persistence layer.
+ *
+ * @param gadgetUri
+ * @param serviceName
+ * @param user
+ * @param scope
+ * @param type
+ * @return
+ * @throws OAuth2PersistenceException
+ */
+ boolean removeToken(String gadgetUri, String serviceName, String user, String scope,
+ OAuth2Token.Type type) throws OAuth2PersistenceException;
+
+ /**
+ * Updates an existing {@link OAuth2Token} in the persistence layer.
+ *
+ * @param token
+ * @throws OAuth2PersistenceException
+ */
+ void updateToken(OAuth2Token token) throws OAuth2PersistenceException;
+}
Added: shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/persistence/OAuth2TokenPersistence.java
URL: http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/persistence/OAuth2TokenPersistence.java?rev=1182565&view=auto
==============================================================================
--- shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/persistence/OAuth2TokenPersistence.java (added)
+++ shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/persistence/OAuth2TokenPersistence.java Wed Oct 12 20:10:39 2011
@@ -0,0 +1,265 @@
+/*
+ * 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.apache.shindig.gadgets.oauth2.persistence;
+
+import java.util.Map;
+
+import org.apache.shindig.gadgets.oauth2.OAuth2Error;
+import org.apache.shindig.gadgets.oauth2.OAuth2Message;
+import org.apache.shindig.gadgets.oauth2.OAuth2RequestException;
+import org.apache.shindig.gadgets.oauth2.OAuth2Token;
+
+import com.google.common.collect.Maps;
+import com.google.inject.Inject;
+
+/**
+ * see {@link OAuth2Token}
+ *
+ */
+public class OAuth2TokenPersistence implements OAuth2Token {
+ private static final long serialVersionUID = 6853969404389015886L;
+
+ private byte[] encryptedMacSecret;
+ private byte[] encryptedSecret;
+ private transient final OAuth2Encrypter encrypter;
+ private long expiresAt;
+ private String gadgetUri;
+ private long issuedAt;
+ private String macAlgorithm;
+ private String macExt;
+ private byte[] macSecret;
+ private final Map<String, String> properties;
+ private String scope;
+ private byte[] secret;
+ private String serviceName;
+ private String tokenType;
+ private Type type;
+ private String user;
+
+ @Inject
+ public OAuth2TokenPersistence(final OAuth2Encrypter encrypter) {
+ this.encrypter = encrypter;
+ this.properties = Maps.newHashMap();
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (obj == this) {
+ return true;
+ }
+ if (!(obj instanceof OAuth2Token)) {
+ return false;
+ }
+ final OAuth2Token other = (OAuth2Token) obj;
+ if (this.gadgetUri == null) {
+ if (other.getGadgetUri() != null) {
+ return false;
+ }
+ } else if (!this.gadgetUri.equals(other.getGadgetUri())) {
+ return false;
+ }
+ if (this.serviceName == null) {
+ if (other.getServiceName() != null) {
+ return false;
+ }
+ } else if (!this.serviceName.equals(other.getServiceName())) {
+ return false;
+ }
+
+ if (this.user == null) {
+ if (other.getUser() != null) {
+ return false;
+ }
+ } else if (!this.user.equals(other.getUser())) {
+ return false;
+ }
+ if (this.scope == null) {
+ if (other.getScope() != null) {
+ return false;
+ }
+ } else if (!this.scope.equals(other.getScope())) {
+ return false;
+ }
+ if (this.type == null) {
+ if (other.getType() != null) {
+ return false;
+ }
+ } else if (!this.type.equals(other.getType())) {
+ return false;
+ }
+
+ return true;
+ }
+
+ public byte[] getEncryptedMacSecret() {
+ return this.encryptedMacSecret;
+ }
+
+ public byte[] getEncryptedSecret() {
+ return this.encryptedSecret;
+ }
+
+ public long getExpiresAt() {
+ return this.expiresAt;
+ }
+
+ public String getGadgetUri() {
+ return this.gadgetUri;
+ }
+
+ public long getIssuedAt() {
+ return this.issuedAt;
+ }
+
+ public String getMacAlgorithm() {
+ return this.macAlgorithm;
+ }
+
+ public String getMacExt() {
+ return this.macExt;
+ }
+
+ public byte[] getMacSecret() {
+ return this.macSecret;
+ }
+
+ public Map<String, String> getProperties() {
+ return this.properties;
+ }
+
+ public String getScope() {
+ return this.scope;
+ }
+
+ public byte[] getSecret() {
+ return this.secret;
+ }
+
+ public String getServiceName() {
+ return this.serviceName;
+ }
+
+ public String getTokenType() {
+ if ((this.tokenType == null) || (this.tokenType.length() == 0)) {
+ this.tokenType = OAuth2Message.BEARER_TOKEN_TYPE;
+ }
+ return this.tokenType;
+ }
+
+ public Type getType() {
+ return this.type;
+ }
+
+ public String getUser() {
+ return this.user;
+ }
+
+ @Override
+ public int hashCode() {
+ if ((this.serviceName != null) && (this.gadgetUri != null)) {
+ return (this.serviceName + ":" + this.gadgetUri + ":" + this.user + ":" + this.scope + ":" + this.type)
+ .hashCode();
+ }
+
+ return 0;
+ }
+
+ public void setEncryptedMacSecret(final byte[] encryptedSecret) throws OAuth2EncryptionException {
+ this.encryptedMacSecret = encryptedSecret;
+ this.macSecret = this.encrypter.decrypt(encryptedSecret);
+ }
+
+ public void setEncryptedSecret(final byte[] encryptedSecret) throws OAuth2EncryptionException {
+ this.encryptedSecret = encryptedSecret;
+ this.secret = this.encrypter.decrypt(encryptedSecret);
+ }
+
+ public void setExpiresAt(long expiresAt) {
+ this.expiresAt = expiresAt;
+ }
+
+ public void setGadgetUri(final String gadgetUri) {
+ this.gadgetUri = gadgetUri;
+ }
+
+ public void setIssuedAt(long issuedAt) {
+ this.issuedAt = issuedAt;
+ }
+
+ public void setMacAlgorithm(String algorithm) {
+ this.macAlgorithm = algorithm;
+ }
+
+ public void setMacExt(String macExt) {
+ this.macExt = macExt;
+ }
+
+ public void setMacSecret(byte[] secret) throws OAuth2RequestException {
+ this.macSecret = secret;
+ try {
+ this.encryptedMacSecret = this.encrypter.encrypt(secret);
+ } catch (final OAuth2EncryptionException e) {
+ throw new OAuth2RequestException(OAuth2Error.SECRET_ENCRYPTION_PROBLEM,
+ "OAuth2TokenPersistence could not encrypt the mac secret", e);
+ }
+ }
+
+ public void setProperties(final Map<String, String> properties) {
+ this.properties.clear();
+ if (properties != null) {
+ this.properties.putAll(properties);
+ }
+ }
+
+ public void setScope(final String scope) {
+ this.scope = scope;
+ }
+
+ public void setSecret(final byte[] secret) throws OAuth2RequestException {
+ this.secret = secret;
+ try {
+ this.encryptedSecret = this.encrypter.encrypt(secret);
+ } catch (final OAuth2EncryptionException e) {
+ throw new OAuth2RequestException(OAuth2Error.SECRET_ENCRYPTION_PROBLEM,
+ "OAuth2TokenPersistence could not encrypt the token secret", e);
+ }
+ }
+
+ public void setServiceName(final String serviceName) {
+ this.serviceName = serviceName;
+ }
+
+ public void setTokenType(final String tokenType) {
+ this.tokenType = tokenType;
+ }
+
+ public void setType(final Type type) {
+ this.type = type;
+ }
+
+ public void setUser(final String user) {
+ this.user = user;
+ }
+
+ @Override
+ public String toString() {
+ return "org.apache.shindig.gadgets.oauth2.persistence.sample.OAuth2TokenImpl: serviceName = "
+ + this.serviceName + " , user = " + this.user + " , gadgetUri = " + this.gadgetUri
+ + " , scope = " + this.scope + " , tokenType = " + this.getTokenType() + " , issuedAt = "
+ + this.issuedAt + " , expiresAt = " + this.expiresAt + " , type = " + this.type;
+ }
+}
Added: shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/persistence/sample/InMemoryCache.java
URL: http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/persistence/sample/InMemoryCache.java?rev=1182565&view=auto
==============================================================================
--- shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/persistence/sample/InMemoryCache.java (added)
+++ shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/persistence/sample/InMemoryCache.java Wed Oct 12 20:10:39 2011
@@ -0,0 +1,166 @@
+/*
+ * 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.apache.shindig.gadgets.oauth2.persistence.sample;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.shindig.gadgets.oauth2.OAuth2Accessor;
+import org.apache.shindig.gadgets.oauth2.OAuth2Token;
+import org.apache.shindig.gadgets.oauth2.persistence.OAuth2Cache;
+import org.apache.shindig.gadgets.oauth2.persistence.OAuth2CacheException;
+import org.apache.shindig.gadgets.oauth2.persistence.OAuth2Client;
+
+import com.google.common.collect.Maps;
+import com.google.inject.Inject;
+import com.google.inject.Singleton;
+
+/**
+ *
+ * {@link OAuth2Cache} implementation using in-memory {@link HashMap}s.
+ *
+ */
+@Singleton
+public class InMemoryCache implements OAuth2Cache {
+ private final static String OAUTH2_CLIENT_PREFIX = InMemoryCache.OAUTH2_PREFIX + "CLIENT_";
+
+ private final static String OAUTH2_PREFIX = "OAUTH2_";
+ private final static String OAUTH2_TOKEN_PREFIX = InMemoryCache.OAUTH2_PREFIX + "TOKEN_";
+
+ private final Map<Integer, OAuth2Accessor> accessors;
+ private final Map<Integer, OAuth2Client> clients;
+ private final Map<Integer, OAuth2Token> tokens;
+
+ @Inject
+ public InMemoryCache() {
+ this.tokens = Maps.newHashMap();
+ this.clients = Maps.newHashMap();
+ this.accessors = Maps.newHashMap();
+ }
+
+ public void clearClients() throws OAuth2CacheException {
+ this.clients.clear();
+ }
+
+ public void clearTokens() throws OAuth2CacheException {
+ this.tokens.clear();
+ }
+
+ public OAuth2Client getClient(final Integer index) {
+ final OAuth2Client ret = this.clients.get(index);
+ return ret;
+ }
+
+ public Integer getClientIndex(final String gadgetUri, final String serviceName) {
+ return Integer
+ .valueOf((InMemoryCache.OAUTH2_CLIENT_PREFIX + ":" + gadgetUri + ":" + serviceName)
+ .hashCode());
+ }
+
+ public OAuth2Accessor getOAuth2Accessor(final Integer index) {
+ OAuth2Accessor ret = null;
+ if (index != null) {
+ ret = this.accessors.get(index);
+ }
+
+ return ret;
+ }
+
+ public Integer getOAuth2AccessorIndex(final String gadgetUri, final String serviceName,
+ final String user, final String scope) {
+ return Integer.valueOf((gadgetUri + ":" + serviceName + ":" + ":" + user + ":" + scope)
+ .hashCode());
+ }
+
+ public OAuth2Token getToken(final Integer index) {
+ return this.tokens.get(index);
+ }
+
+ public Integer getTokenIndex(final OAuth2Token token) {
+ if (token != null) {
+ return this.getTokenIndex(token.getGadgetUri(), token.getServiceName(), token.getUser(),
+ token.getScope(), token.getType());
+ }
+
+ return null;
+ }
+
+ public Integer getTokenIndex(final String gadgetUri, final String serviceName, final String user,
+ final String scope, final OAuth2Token.Type type) {
+
+ return Integer.valueOf((InMemoryCache.OAUTH2_TOKEN_PREFIX + ":" + gadgetUri + ":" + serviceName
+ + ":" + user + ":" + scope + ":" + type.name()).hashCode());
+ }
+
+ public OAuth2Client removeClient(final Integer index) throws OAuth2CacheException {
+ return this.clients.remove(index);
+ }
+
+ public OAuth2Accessor removeOAuth2Accessor(final Integer index) {
+ return this.accessors.remove(index);
+ }
+
+ public OAuth2Token removeToken(final Integer index) throws OAuth2CacheException {
+ return this.tokens.remove(index);
+ }
+
+ public Integer storeClient(final OAuth2Client client) throws OAuth2CacheException {
+ if (client != null) {
+ final Integer index = this.getClientIndex(client.getGadgetUri(), client.getServiceName());
+ this.clients.put(index, client);
+ return index;
+ }
+
+ return null;
+ }
+
+ public void storeClients(final Collection<OAuth2Client> storeClients) throws OAuth2CacheException {
+ for (final OAuth2Client client : storeClients) {
+ final Integer index = this.getClientIndex(client.getGadgetUri(), client.getServiceName());
+ this.clients.put(index, client);
+ }
+ }
+
+ public Integer storeOAuth2Accessor(final OAuth2Accessor accessor) {
+ if (accessor != null) {
+ final Integer index = this.getOAuth2AccessorIndex(accessor.getGadgetUri(),
+ accessor.getServiceName(), accessor.getUser(), accessor.getScope());
+ this.accessors.put(index, accessor);
+ return index;
+ }
+
+ return null;
+ }
+
+ public Integer storeToken(final OAuth2Token token) throws OAuth2CacheException {
+ if (token != null) {
+ final Integer index = this.getTokenIndex(token);
+ this.tokens.put(index, token);
+ return index;
+ }
+
+ return null;
+ }
+
+ public void storeTokens(final Collection<OAuth2Token> storeTokens) throws OAuth2CacheException {
+ for (final OAuth2Token token : storeTokens) {
+ final Integer index = this.getTokenIndex(token);
+ this.tokens.put(index, token);
+ }
+ }
+}