Skip to content

Commit

Permalink
TFJ-762 add Application-only authentication feature.
Browse files Browse the repository at this point in the history
  • Loading branch information
komiya-atsushi committed Apr 21, 2013
1 parent b25e57a commit cad1650
Show file tree
Hide file tree
Showing 14 changed files with 749 additions and 27 deletions.
2 changes: 2 additions & 0 deletions twitter4j-core/src/main/java/twitter4j/Twitter.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
package twitter4j;

import twitter4j.api.*;
import twitter4j.auth.OAuth2Support;
import twitter4j.auth.OAuthSupport;

/**
Expand All @@ -24,6 +25,7 @@
*/
public interface Twitter extends java.io.Serializable,
OAuthSupport,
OAuth2Support,
TwitterBase,
TimelinesResources,
TweetsResources,
Expand Down
61 changes: 50 additions & 11 deletions twitter4j-core/src/main/java/twitter4j/TwitterBaseImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
*
* @author Yusuke Yamamoto - yusuke at mac.com
*/
abstract class TwitterBaseImpl implements TwitterBase, java.io.Serializable, OAuthSupport, HttpResponseListener {
abstract class TwitterBaseImpl implements TwitterBase, java.io.Serializable, OAuthSupport, OAuth2Support, HttpResponseListener {
protected Configuration conf;
protected transient String screenName = null;
protected transient long id = 0;
Expand All @@ -61,13 +61,24 @@ private void init() {
String consumerSecret = conf.getOAuthConsumerSecret();
// try to find oauth tokens in the configuration
if (consumerKey != null && consumerSecret != null) {
OAuthAuthorization oauth = new OAuthAuthorization(conf);
String accessToken = conf.getOAuthAccessToken();
String accessTokenSecret = conf.getOAuthAccessTokenSecret();
if (accessToken != null && accessTokenSecret != null) {
oauth.setOAuthAccessToken(new AccessToken(accessToken, accessTokenSecret));
if (conf.isApplicationOnlyAuthEnabled()) {
OAuth2Authorization oauth2 = new OAuth2Authorization(conf);
String tokenType = conf.getOAuth2TokenType();
String accessToken = conf.getOAuth2AccessToken();
if (tokenType != null && accessToken != null) {
oauth2.setOAuth2Token(new OAuth2Token(tokenType, accessToken));
}
this.auth = oauth2;

} else {
OAuthAuthorization oauth = new OAuthAuthorization(conf);
String accessToken = conf.getOAuthAccessToken();
String accessTokenSecret = conf.getOAuthAccessTokenSecret();
if (accessToken != null && accessTokenSecret != null) {
oauth.setOAuthAccessToken(new AccessToken(accessToken, accessTokenSecret));
}
this.auth = oauth;
}
this.auth = oauth;
} else {
this.auth = NullAuthorization.getInstance();
}
Expand Down Expand Up @@ -253,14 +264,20 @@ public synchronized void setOAuthConsumer(String consumerKey, String consumerSec
throw new NullPointerException("consumer secret is null");
}
if (auth instanceof NullAuthorization) {
OAuthAuthorization oauth = new OAuthAuthorization(conf);
oauth.setOAuthConsumer(consumerKey, consumerSecret);
auth = oauth;
if (conf.isApplicationOnlyAuthEnabled()) {
OAuth2Authorization oauth2 = new OAuth2Authorization(conf);
oauth2.setOAuthConsumer(consumerKey, consumerSecret);
auth = oauth2;
} else {
OAuthAuthorization oauth = new OAuthAuthorization(conf);
oauth.setOAuthConsumer(consumerKey, consumerSecret);
auth = oauth;
}
} else if (auth instanceof BasicAuthorization) {
XAuthAuthorization xauth = new XAuthAuthorization((BasicAuthorization) auth);
xauth.setOAuthConsumer(consumerKey, consumerSecret);
auth = xauth;
} else if (auth instanceof OAuthAuthorization) {
} else if (auth instanceof OAuthAuthorization || auth instanceof OAuth2Authorization) {
throw new IllegalStateException("consumer key/secret pair already set.");
}
}
Expand Down Expand Up @@ -389,6 +406,28 @@ private OAuthSupport getOAuth() {
return (OAuthSupport) auth;
}

@Override
public synchronized OAuth2Token getOAuth2Token() throws TwitterException {
return getOAuth2().getOAuth2Token();
}

@Override
public void setOAuth2Token(OAuth2Token oauth2Token) {
getOAuth2().setOAuth2Token(oauth2Token);
}

@Override
public synchronized void invalidateOAuth2Token() throws TwitterException {
getOAuth2().invalidateOAuth2Token();
}

private OAuth2Support getOAuth2() {
if (!(auth instanceof OAuth2Support)) {
throw new IllegalStateException(
"OAuth consumer key/secret combination not supplied");
}
return (OAuth2Support) auth;
}

@Override
public boolean equals(Object o) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,8 @@ public interface AuthorizationConfiguration {
String getOAuthAccessToken();

String getOAuthAccessTokenSecret();

String getOAuth2TokenType();

String getOAuth2AccessToken();
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,25 @@ public static Authorization getInstance(Configuration conf) {
String consumerSecret = conf.getOAuthConsumerSecret();

if (consumerKey != null && consumerSecret != null) {
OAuthAuthorization oauth;
oauth = new OAuthAuthorization(conf);
String accessToken = conf.getOAuthAccessToken();
String accessTokenSecret = conf.getOAuthAccessTokenSecret();
if (accessToken != null && accessTokenSecret != null) {
oauth.setOAuthAccessToken(new AccessToken(accessToken, accessTokenSecret));
if (conf.isApplicationOnlyAuthEnabled()) {
OAuth2Authorization oauth2 = new OAuth2Authorization(conf);
String tokenType = conf.getOAuth2TokenType();
String accessToken = conf.getOAuth2AccessToken();
if (tokenType != null && accessToken != null) {
oauth2.setOAuth2Token(new OAuth2Token(tokenType, accessToken));
}
auth = oauth2;

} else {
OAuthAuthorization oauth;
oauth = new OAuthAuthorization(conf);
String accessToken = conf.getOAuthAccessToken();
String accessTokenSecret = conf.getOAuthAccessTokenSecret();
if (accessToken != null && accessTokenSecret != null) {
oauth.setOAuthAccessToken(new AccessToken(accessToken, accessTokenSecret));
}
auth = oauth;
}
auth = oauth;
} else {
String screenName = conf.getUser();
String password = conf.getPassword();
Expand Down
151 changes: 151 additions & 0 deletions twitter4j-core/src/main/java/twitter4j/auth/OAuth2Authorization.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
package twitter4j.auth;

import twitter4j.TwitterException;
import twitter4j.conf.Configuration;
import twitter4j.internal.http.*;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;

/**
* @author KOMIYA Atsushi - komiya.atsushi at gmail.com
* @see <a href="https://dev.twitter.com/docs/auth/application-only-auth">Application-only authentication</a>
*/
public class OAuth2Authorization implements Authorization, java.io.Serializable, OAuth2Support {
private static final long serialVersionUID = 4274784415515174129L;

private final Configuration conf;

private HttpClientWrapper http;

private String consumerKey;

private String consumerSecret;

private OAuth2Token token;

public OAuth2Authorization(Configuration conf) {
this.conf = conf;
setOAuthConsumer(conf.getOAuthConsumerKey(), conf.getOAuthConsumerSecret());
http = new HttpClientWrapper(conf);
}

@Override
public void setOAuthConsumer(String consumerKey, String consumerSecret) {
this.consumerKey = consumerKey != null ? consumerKey : "";
this.consumerSecret = consumerSecret != null ? consumerSecret : "";
}

@Override
public OAuth2Token getOAuth2Token() throws TwitterException {
if (token != null) {
throw new IllegalStateException("OAuth 2 Bearer Token is already available.");
}

HttpParameter[] params = new HttpParameter[1];
params[0] = new HttpParameter("grant_type", "client_credentials");

HttpResponse res = http.post(conf.getOAuth2TokenURL(), params, this);
if (res.getStatusCode() != 200) {
throw new TwitterException("Obtaining OAuth 2 Bearer Token failed.", res);
}
token = new OAuth2Token(res);
return token;
}

@Override
public void setOAuth2Token(OAuth2Token oauth2Token) {
this.token = oauth2Token;
}

@Override
public void invalidateOAuth2Token() throws TwitterException {
if (token == null) {
throw new IllegalStateException("OAuth 2 Bearer Token is not available.");
}

HttpParameter[] params = new HttpParameter[1];
params[0] = new HttpParameter("access_token", token.getAccessToken());

OAuth2Token _token = token;
boolean succeed = false;

try {
token = null;

HttpResponse res = http.post(conf.getOAuth2InvalidateTokenURL(), params, this);
if (res.getStatusCode() != 200) {
throw new TwitterException("Invalidating OAuth 2 Bearer Token failed.", res);
}

succeed = true;

} finally {
if (!succeed) {
token = _token;
}
}
}

@Override
public String getAuthorizationHeader(HttpRequest req) {
if (token == null) {
String credentials = "";
try {
credentials =
URLEncoder.encode(consumerKey, "UTF-8")
+ ":"
+ URLEncoder.encode(consumerSecret, "UTF-8");

} catch (UnsupportedEncodingException ignore) {
}

return "Basic " + BASE64Encoder.encode(credentials.getBytes());

} else {
return token.generateAuthorizationHeader();
}
}

@Override
public boolean isEnabled() {
return token != null;
}

@Override
public boolean equals(Object obj) {
if (obj == null || !(obj instanceof OAuth2Authorization)) {
return false;
}

OAuth2Authorization that = (OAuth2Authorization) obj;
if (consumerKey != null ? !consumerKey.equals(that.consumerKey) : that.consumerKey != null) {
return false;
}
if (consumerSecret != null ? !consumerSecret.equals(that.consumerSecret) : that.consumerSecret != null) {
return false;
}
if (token != null ? !token.equals(that.token) : that.token != null) {
return false;
}

return true;
}

@Override
public int hashCode() {
int result = consumerKey != null ? consumerKey.hashCode() : 0;
result = 31 * result + (consumerSecret != null ? consumerSecret.hashCode() : 0);
result = 31 * result + (token != null ? token.hashCode() : 0);
return result;
}

@Override
public String toString() {
return "OAuth2Authorization{" +
"consumerKey='" + consumerKey + '\'' +
", consumerSecret='******************************************\'" +
", token=" + token.toString() +
'}';
}
}
43 changes: 43 additions & 0 deletions twitter4j-core/src/main/java/twitter4j/auth/OAuth2Support.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package twitter4j.auth;

import twitter4j.TwitterException;

/**
* @author KOMIYA Atsushi - komiya.atsushi at gmail.com
* @see <a href="https://dev.twitter.com/docs/auth/application-only-auth">Application-only authentication | Twitter Developers</a>
*/
public interface OAuth2Support {
/**
* Sets the OAuth consumer key and consumer secret.
*
* @param consumerKey OAuth consumer key
* @param consumerSecret OAuth consumer secret
* @throws IllegalStateException when OAuth consumer has already been set, or the instance is using basic authorization.
*/
void setOAuthConsumer(String consumerKey, String consumerSecret);

/**
* Obtains an OAuth 2 Bearer token.
*
* @return
* @throws TwitterException when Twitter service or network is unavailable, or connecting non-SSL endpoints.
* @throws IllegalStateException when Bearer token is already available, or OAuth consumer is not available.
* @see <a href="https://dev.twitter.com/docs/api/1.1/post/oauth2/token">POST oauth2/token | Twitter Developers</a>
*/
OAuth2Token getOAuth2Token() throws TwitterException;

/**
* Sets the OAuth 2 Bearer token.
*
* @param oauth2Token OAuth 2 Bearer token
*/
void setOAuth2Token(OAuth2Token oauth2Token);

/**
* Revokes an issued OAuth 2 Bearer Token.
*
* @throws TwitterException when Twitter service or network is unavailable, or connecting non-SSL endpoints.
* @throws IllegalStateException when Bearer token is not available.
*/
void invalidateOAuth2Token() throws TwitterException;
}
Loading

0 comments on commit cad1650

Please sign in to comment.