/*
* Copyright 2007 Yusuke Yamamoto
*
* Licensed 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 twitter4j.auth;
import twitter4j.*;
import twitter4j.conf.Configuration;
import twitter4j.conf.ConfigurationBuilder;
import twitter4j.conf.ConfigurationContext;
import twitter4j.conf.PropertyConfiguration;
import twitter4j.internal.http.*;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectOutputStream;
import java.util.*;
/**
* @author Yusuke Yamamoto - yusuke at mac.com
*/
public class OAuthTest extends TwitterTestBase {
public OAuthTest(String name) {
super(name);
}
@Override
protected void setUp() throws Exception {
super.setUp();
}
public void testDeterministic() throws Exception {
ArrayList list1 = new ArrayList();
ArrayList list2 = new ArrayList();
assertEquals(list1, list2);
Twitter twitter1 = new TwitterFactory().getInstance();
twitter1.setOAuthConsumer(browserConsumerKey, browserConsumerSecret);
Twitter twitter2 = new TwitterFactory().getInstance();
twitter2.setOAuthConsumer(browserConsumerKey, browserConsumerSecret);
assertTrue(twitter1.equals(twitter2));
assertEquals(twitter1, twitter2);
}
public void testOAuth() throws Exception {
ConfigurationBuilder build = new ConfigurationBuilder();
String oAuthAccessToken = p.getProperty("id1.oauth.accessToken");
String oAuthAccessTokenSecret = p.getProperty("id1.oauth.accessTokenSecret");
String oAuthConsumerKey = p.getProperty("oauth.consumerKey");
String oAuthConsumerSecret = p.getProperty("oauth.consumerSecret");
build.setOAuthAccessToken(oAuthAccessToken);
build.setOAuthAccessTokenSecret(oAuthAccessTokenSecret);
build.setOAuthConsumerKey(oAuthConsumerKey);
build.setOAuthConsumerSecret(oAuthConsumerSecret);
OAuthAuthorization auth = new OAuthAuthorization(build.build());
Twitter twitter = new TwitterFactory().getInstance(auth);
twitter.verifyCredentials();
}
public void testDesktopClient() throws Exception {
RequestToken rt;
Twitter twitter = new TwitterFactory().getInstance();
HttpClientImpl http;
HttpResponse response;
String resStr;
String authorizeURL;
HttpParameter[] params;
AccessToken at;
String cookie;
http = new HttpClientImpl();
// desktop client - requiring pin
Twitter unauthenticated = new TwitterFactory().getInstance();
unauthenticated.setOAuthConsumer(desktopConsumerKey, desktopConsumerSecret);
rt = unauthenticated.getOAuthRequestToken();
rt.hashCode();
// trying to get an access token without permitting the request token.
try {
unauthenticated.getOAuthAccessToken();
fail();
} catch (TwitterException te) {
assertEquals(401, te.getStatusCode());
}
twitter.setOAuthConsumer(desktopConsumerKey, desktopConsumerSecret);
rt = twitter.getOAuthRequestToken(null, "read");
// trying to get an access token without permitting the request token.
try {
twitter.getOAuthAccessToken(rt.getToken(), rt.getTokenSecret());
fail();
} catch (TwitterException te) {
assertEquals(401, te.getStatusCode());
}
Map<String, String> props = new HashMap<String, String>();
response = http.get(rt.getAuthorizationURL());
cookie = response.getResponseHeader("Set-Cookie");
// http.setRequestHeader("Cookie", cookie);
props.put("Cookie", cookie);
resStr = response.asString();
authorizeURL = catchPattern(resStr, "<form action=\"", "\" id=\"oauth_form\"");
params = new HttpParameter[4];
params[0] = new HttpParameter("authenticity_token"
, catchPattern(resStr, "\"authenticity_token\" type=\"hidden\" value=\"", "\" />"));
params[1] = new HttpParameter("oauth_token",
catchPattern(resStr, "name=\"oauth_token\" type=\"hidden\" value=\"", "\" />"));
params[2] = new HttpParameter("session[username_or_email]", numberId);
params[3] = new HttpParameter("session[password]", numberPass);
response = http.request(new HttpRequest(RequestMethod.POST, authorizeURL, params, null, props));
resStr = response.asString();
String pin = catchPattern(resStr, "<kbd aria-labelledby=\"code-desc\"><code>", "</code></kbd>");
at = twitter.getOAuthAccessToken(rt, pin);
try {
twitter.getOAuthRequestToken();
} catch (TwitterException te) {
fail("expecting IllegalStateException as access token is already available.");
} catch (IllegalStateException expected) {
}
assertEquals(at.getScreenName(), numberId);
assertEquals(at.getUserId(), numberIdId);
AccessToken at1 = twitter.getOAuthAccessToken();
assertEquals(at, at1);
TwitterResponse res = twitter.getLanguages();
assertEquals(TwitterResponse.READ, res.getAccessLevel());
}
public void testIllegalStatus() throws Exception {
try {
new TwitterFactory().getInstance().getOAuthAccessToken();
fail("should throw IllegalStateException since request token hasn't been acquired.");
} catch (IllegalStateException ignore) {
}
}
public void testSigninWithTwitter() throws Exception {
RequestToken rt;
Twitter twitter = new TwitterFactory().getInstance();
HttpClientImpl http;
HttpResponse response;
String resStr;
String authorizeURL;
HttpParameter[] params;
AccessToken at;
String cookie;
http = new HttpClientImpl();
// browser client - not requiring pin
twitter.setOAuthConsumer(browserConsumerKey, browserConsumerSecret);
rt = twitter.getOAuthRequestToken();
Map<String, String> props = new HashMap<String, String>();
response = http.get(rt.getAuthenticationURL());
cookie = response.getResponseHeader("Set-Cookie");
// http.setRequestHeader("Cookie", cookie);
props.put("Cookie", cookie);
resStr = response.asString();
authorizeURL = catchPattern(resStr, "<form action=\"", "\" id=\"oauth_form\"");
params = new HttpParameter[4];
params[0] = new HttpParameter("authenticity_token"
, catchPattern(resStr, "\"authenticity_token\" type=\"hidden\" value=\"", "\" />"));
params[1] = new HttpParameter("oauth_token",
catchPattern(resStr, "name=\"oauth_token\" type=\"hidden\" value=\"", "\" />"));
params[2] = new HttpParameter("session[username_or_email]", id1.screenName);
params[3] = new HttpParameter("session[password]", id1.password);
response = http.request(new HttpRequest(RequestMethod.POST, authorizeURL, params, null, props));
// response = http.post(authorizeURL, params);
resStr = response.asString();
String oauthVerifier = catchPattern(resStr, "&oauth_verifier=", "\">");
at = twitter.getOAuthAccessToken(rt, oauthVerifier);
assertEquals(at.getScreenName(), id1.screenName);
assertEquals(at.getUserId(), id1.id);
}
public void testBrowserClient() throws Exception {
RequestToken rt;
Twitter twitter = new TwitterFactory().getInstance();
HttpClientImpl http;
HttpResponse response;
String resStr;
String authorizeURL;
HttpParameter[] params;
AccessToken at;
String cookie;
http = new HttpClientImpl();
// browser client - not requiring pin
twitter.setOAuthConsumer(browserConsumerKey, browserConsumerSecret);
rt = twitter.getOAuthRequestToken();
response = http.get(rt.getAuthorizationURL());
Map<String, String> props = new HashMap<String, String>();
cookie = response.getResponseHeader("Set-Cookie");
props.put("Cookie", cookie);
resStr = response.asString();
authorizeURL = catchPattern(resStr, "<form action=\"", "\" id=\"oauth_form\"");
params = new HttpParameter[4];
params[0] = new HttpParameter("authenticity_token"
, catchPattern(resStr, "\"authenticity_token\" type=\"hidden\" value=\"", "\" />"));
params[1] = new HttpParameter("oauth_token",
catchPattern(resStr, "name=\"oauth_token\" type=\"hidden\" value=\"", "\" />"));
params[2] = new HttpParameter("session[username_or_email]", id1.screenName);
params[3] = new HttpParameter("session[password]", id1.password);
response = http.request(new HttpRequest(RequestMethod.POST, authorizeURL, params, null, props));
resStr = response.asString();
String oauthVerifier = catchPattern(resStr, "&oauth_verifier=", "\">");
at = twitter.getOAuthAccessToken(rt, oauthVerifier);
assertEquals(at.getScreenName(), id1.screenName);
assertEquals(at.getUserId(), id1.id);
}
public void testBrowserClientWithCustomCallback() throws Exception {
RequestToken rt;
Twitter twitter = new TwitterFactory().getInstance();
HttpClientImpl http;
HttpResponse response;
String resStr;
String authorizeURL;
HttpParameter[] params;
AccessToken at;
String cookie;
http = new HttpClientImpl();
// browser client - not requiring pin / overriding callback url
twitter = new TwitterFactory().getInstance();
twitter.setOAuthConsumer(browserConsumerKey, browserConsumerSecret);
rt = twitter.getOAuthRequestToken("http://yusuke.homeip.net/twitter4j/custom_callback");
http = new HttpClientImpl();
System.out.println("AuthorizationURL: " + rt.getAuthorizationURL());
response = http.get(rt.getAuthorizationURL());
Map<String, String> props = new HashMap<String, String>();
cookie = response.getResponseHeader("Set-Cookie");
// http.setRequestHeader("Cookie", cookie);
props.put("Cookie", cookie);
resStr = response.asString();
authorizeURL = catchPattern(resStr, "<form action=\"", "\" id=\"oauth_form\"");
params = new HttpParameter[4];
params[0] = new HttpParameter("authenticity_token"
, catchPattern(resStr, "\"authenticity_token\" type=\"hidden\" value=\"", "\" />"));
params[1] = new HttpParameter("oauth_token",
catchPattern(resStr, "name=\"oauth_token\" type=\"hidden\" value=\"", "\" />"));
params[2] = new HttpParameter("session[username_or_email]", id1.screenName);
params[3] = new HttpParameter("session[password]", id1.password);
response = http.request(new HttpRequest(RequestMethod.POST, authorizeURL, params, null, props));
// response = http.post(authorizeURL, params);
resStr = response.asString();
String oauthVerifier = catchPattern(resStr, "&oauth_verifier=", "\">");
at = twitter.getOAuthAccessToken(rt, oauthVerifier);
assertEquals(at.getScreenName(), id1.screenName);
assertEquals(at.getUserId(), id1.id);
}
private static String catchPattern(String body, String before, String after) {
int beforeIndex = body.indexOf(before);
int afterIndex = body.indexOf(after, beforeIndex);
return body.substring(beforeIndex + before.length(), afterIndex);
}
public void testAccessToken() {
AccessToken at = new AccessToken("oauth_token=6377362-kW0YV1ymaqEUCSHP29ux169mDeA4kQfhEuqkdvHk&oauth_token_secret=ghoTpd7LuMLHtJDyHkhYo40Uq5bWSxeCyOUAkbsOoOY&user_id=6377362&screen_name=twit4j2");
assertEquals("6377362-kW0YV1ymaqEUCSHP29ux169mDeA4kQfhEuqkdvHk", at.getToken());
assertEquals("ghoTpd7LuMLHtJDyHkhYo40Uq5bWSxeCyOUAkbsOoOY", at.getTokenSecret());
assertEquals("twit4j2", at.getScreenName());
assertEquals(6377362, at.getUserId());
}
public void testSign() throws Exception {
String baseStr = "GET&http%3A%2F%2Fphotos.example.net%2Fphotos&file%3Dvacation.jpg%26oauth_consumer_key%3Ddpf43f3p2l4k3l03%26oauth_nonce%3Dkllo9940pd9333jh%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1191242096%26oauth_token%3Dnnch734d00sl2jdk%26oauth_version%3D1.0%26size%3Doriginal";
OAuthAuthorization oauth = new OAuthAuthorization(ConfigurationContext.getInstance());
oauth.setOAuthConsumer("dpf43f3p2l4k3l03", "kd94hf93k423kf44");
trySerializable(oauth);
//http://wiki.oauth.net/TestCases
assertEquals("tR3+Ty81lMeYAr/Fid0kMTYa/WM=", oauth.generateSignature(baseStr, new RequestToken("nnch734d00sl2jdk", "pfkkdhi9sl3r4s00")));
oauth = new OAuthAuthorization(ConfigurationContext.getInstance());
oauth.setOAuthConsumer(desktopConsumerKey, "cs");
assertEquals("egQqG5AJep5sJ7anhXju1unge2I=", oauth.generateSignature("bs", new RequestToken("nnch734d00sl2jdk", "")));
assertEquals("VZVjXceV7JgPq/dOTnNmEfO0Fv8=", oauth.generateSignature("bs", new RequestToken("nnch734d00sl2jdk", "ts")));
oauth = new OAuthAuthorization(ConfigurationContext.getInstance());
oauth.setOAuthConsumer(desktopConsumerKey, "kd94hf93k423kf44");
assertEquals("tR3+Ty81lMeYAr/Fid0kMTYa/WM=", oauth.generateSignature("GET&http%3A%2F%2Fphotos.example.net%2Fphotos&file%3Dvacation.jpg%26oauth_consumer_key%3Ddpf43f3p2l4k3l03%26oauth_nonce%3Dkllo9940pd9333jh%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1191242096%26oauth_token%3Dnnch734d00sl2jdk%26oauth_version%3D1.0%26size%3Doriginal", new RequestToken("nnch734d00sl2jdk", "pfkkdhi9sl3r4s00")));
}
public void testHeader() throws Exception {
HttpParameter[] params = new HttpParameter[2];
params[0] = new HttpParameter("file", "vacation.jpg");
params[1] = new HttpParameter("size", "original");
OAuthAuthorization oauth = new OAuthAuthorization(ConfigurationContext.getInstance());
oauth.setOAuthConsumer("dpf43f3p2l4k3l03", "kd94hf93k423kf44");
String expected = "OAuth oauth_consumer_key=\"dpf43f3p2l4k3l03\",oauth_signature_method=\"HMAC-SHA1\",oauth_timestamp=\"1191242096\",oauth_nonce=\"kllo9940pd9333jh\",oauth_version=\"1.0\",oauth_token=\"nnch734d00sl2jdk\",oauth_signature=\"tR3%2BTy81lMeYAr%2FFid0kMTYa%2FWM%3D\"";
assertEquals(expected, oauth.generateAuthorizationHeader("GET", "http://photos.example.net/photos", params, "kllo9940pd9333jh", "1191242096", new RequestToken("nnch734d00sl2jdk", "pfkkdhi9sl3r4s00")));
}
public void testEncodeParameter() throws Exception {
//http://wiki.oauth.net/TestCases
assertEquals("abcABC123", HttpParameter.encode("abcABC123"));
assertEquals("-._~", HttpParameter.encode("-._~"));
assertEquals("%25", HttpParameter.encode("%"));
assertEquals("%2B", HttpParameter.encode("+"));
assertEquals("%26%3D%2A", HttpParameter.encode("&=*"));
assertEquals("%0A", HttpParameter.encode("\n"));
assertEquals("%20", HttpParameter.encode("\u0020"));
assertEquals("%7F", HttpParameter.encode("\u007F"));
assertEquals("%C2%80", HttpParameter.encode("\u0080"));
assertEquals("%E3%80%81", HttpParameter.encode("\u3001"));
String unreserved = "abcdefghijklmnopqrstuvwzyxABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._~";
assertEquals(unreserved, HttpParameter.encode(unreserved));
}
public void testNormalizeRequestParameters() throws Exception {
// a=1, c=hi%20there, f=25, f=50, f=a, z=p, z=t
HttpParameter[] params = new HttpParameter[]{
new HttpParameter("a", "1"),
new HttpParameter("c", "hi there"),
new HttpParameter("f", "50"),
new HttpParameter("f", "25"),
new HttpParameter("z", "t"),
new HttpParameter("z", "p"),
new HttpParameter("f", "a"),
};
assertEquals("a=1&c=hi%20there&f=25&f=50&f=a&z=p&z=t", OAuthAuthorization.normalizeRequestParameters(params));
// test cases from http://wiki.oauth.net/TestCases - Normalize Request Parameters (section 9.1.1)
params = new HttpParameter[]{
new HttpParameter("name", ""),
};
assertEquals("name=", OAuthAuthorization.normalizeRequestParameters(params));
params = new HttpParameter[]{
new HttpParameter("a", "b"),
};
assertEquals("a=b", OAuthAuthorization.normalizeRequestParameters(params));
params = new HttpParameter[]{
new HttpParameter("a", "b"),
new HttpParameter("c", "d"),
};
assertEquals("a=b&c=d", OAuthAuthorization.normalizeRequestParameters(params));
params = new HttpParameter[]{
new HttpParameter("a", "x!y"),
new HttpParameter("a", "x y"),
};
assertEquals("a=x%20y&a=x%21y", OAuthAuthorization.normalizeRequestParameters(params));
params = new HttpParameter[]{
new HttpParameter("x!y", "a"),
new HttpParameter("x", "a"),
};
assertEquals("x=a&x%21y=a", OAuthAuthorization.normalizeRequestParameters(params));
}
public void testConstructRequestURL() throws Exception {
//http://oauth.net/core/1.0#rfc.section.9.1.2
assertEquals("http://example.com/resource", OAuthAuthorization.constructRequestURL("HTTP://Example.com:80/resource?id=123"));
assertEquals("http://example.com:8080/resource", OAuthAuthorization.constructRequestURL("HTTP://Example.com:8080/resource?id=123"));
assertEquals("http://example.com/resource", OAuthAuthorization.constructRequestURL("HTTP://Example.com/resource?id=123"));
assertEquals("https://example.com/resource", OAuthAuthorization.constructRequestURL("HTTPS://Example.com:443/resource?id=123"));
assertEquals("https://example.com:8443/resource", OAuthAuthorization.constructRequestURL("HTTPS://Example.com:8443/resource?id=123"));
assertEquals("https://example.com/resource", OAuthAuthorization.constructRequestURL("HTTPS://Example.com/resource?id=123"));
}
public void testXAuth() throws Exception {
ConfigurationBuilder builder = new ConfigurationBuilder();
builder.setOAuthConsumerKey(desktopConsumerKey);
builder.setOAuthConsumerSecret(desktopConsumerSecret);
Twitter twitter = new TwitterFactory(builder.build()).getInstance();
try {
twitter.getOAuthAccessToken(id1.screenName, id2.password);
fail("expecting TwitterException");
} catch (TwitterException te) {
// id1 doesn't have access to xAuth
assertEquals(401, te.getStatusCode());
}
InputStream is = OAuthTest.class.getResourceAsStream("/xauth-test.properties");
if (null == is) {
System.out.println("xauth-test.properties not found. skipping xAuth test.");
} else {
Properties props = new Properties();
props.load(is);
Configuration conf = new PropertyConfiguration(props);
twitter = new TwitterFactory(conf).getInstance();
AccessToken at = twitter.getOAuthAccessToken(id1.screenName, id1.password);
twitter.updateStatus(new Date() + ": xAuth test.");
twitter = new TwitterFactory().getInstance();
twitter.setOAuthConsumer(conf.getOAuthConsumerKey(), conf.getOAuthConsumerSecret());
twitter.getOAuthAccessToken(id1.screenName, id1.password);
}
}
private void trySerializable(Object obj) throws IOException {
ObjectOutputStream oos = new ObjectOutputStream(new ByteArrayOutputStream());
oos.writeObject(obj);
}
}