/**
* Licensed to Apereo under one or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information regarding copyright ownership. Apereo
* 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 the
* following location:
*
* <p>http://www.apache.org/licenses/LICENSE-2.0
*
* <p>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.springframework.web.client.interceptors;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import javax.annotation.Resource;
import net.oauth.OAuthAccessor;
import net.oauth.OAuthConsumer;
import net.oauth.OAuthException;
import net.oauth.OAuthMessage;
import net.oauth.OAuthServiceProvider;
import org.springframework.beans.factory.annotation.Required;
import org.springframework.core.env.PropertyResolver;
import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.util.Assert;
/**
* Interceptor to add the authorization headers required for 0-legged oauth signing of requests.
*
*/
public class ZeroLeggedOAuthInterceptor implements ClientHttpRequestInterceptor {
private String id;
private PropertyResolver propertyResolver;
private RealmOAuthConsumer consumer;
@Required
public void setId(String id) {
this.id = id;
}
@Resource(name = "propertyResolver")
public void setPropertyResolver(final PropertyResolver resolver) {
this.propertyResolver = resolver;
}
/**
* Intercept a request and add the oauth headers.
*
* @param req the request
* @param body the request body
* @param execution the request execution.
* @return the request response
* @throws IOException on error
*/
@Override
public ClientHttpResponse intercept(
HttpRequest req, byte[] body, ClientHttpRequestExecution execution) throws IOException {
Assert.notNull(propertyResolver);
Assert.notNull(id);
try {
String authString = getOAuthAuthString(req);
req.getHeaders().add(Headers.Authorization.name(), authString);
} catch (Exception e) {
throw new IOException("Error building OAuth header", e);
}
return execution.execute(req, body);
}
/**
* Get the oauth Authorization string.
*
* @param req the request
* @return the Authorization string
*/
private String getOAuthAuthString(HttpRequest req)
throws OAuthException, IOException, URISyntaxException {
RealmOAuthConsumer consumer = getConsumer();
OAuthAccessor accessor = new OAuthAccessor(consumer);
String method = req.getMethod().name();
URI uri = req.getURI();
OAuthMessage msg = accessor.newRequestMessage(method, uri.toString(), null);
return msg.getAuthorizationHeader(consumer.getRealm());
}
/**
* Get the OAuthConsumer. Will initialize it lazily.
*
* @return the OAuthConsumer object.
*/
private synchronized RealmOAuthConsumer getConsumer() {
// could just inject these, but I kinda prefer pushing this out
// to the properties file...
if (consumer == null) {
OAuthServiceProvider serviceProvider = new OAuthServiceProvider("", "", "");
String realm =
propertyResolver.getProperty(
"org.jasig.rest.interceptor.oauth." + id + ".realm");
String consumerKey =
propertyResolver.getProperty(
"org.jasig.rest.interceptor.oauth." + id + ".consumerKey");
String secretKey =
propertyResolver.getProperty(
"org.jasig.rest.interceptor.oauth." + id + ".secretKey");
Assert.notNull(
consumerKey,
"The property \"org.jasig.rest.interceptor.oauth."
+ id
+ ".consumerKey\" must be set.");
Assert.notNull(
secretKey,
"The property \"org.jasig.rest.interceptor.oauth."
+ id
+ ".secretKey\" must be set.");
consumer = new RealmOAuthConsumer(consumerKey, secretKey, realm, serviceProvider);
}
return consumer;
}
/** Custom consumer that also tracks the realm. */
private static class RealmOAuthConsumer extends OAuthConsumer {
private String realm;
public RealmOAuthConsumer(
final String consumerKey,
final String consumerSecret,
final String realm,
final OAuthServiceProvider serviceProvider) {
super(null, consumerKey, consumerSecret, serviceProvider);
this.realm = realm;
}
public String getRealm() {
return realm;
}
}
}