/** * 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; } } }