/*
* Copyright (c) 2005 Aetrion LLC.
*/
package com.googlecode.flickr2twitter.com.aetrion.flickr.auth;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;
import com.googlecode.flickr2twitter.com.aetrion.flickr.FlickrException;
import com.googlecode.flickr2twitter.com.aetrion.flickr.Parameter;
import com.googlecode.flickr2twitter.com.aetrion.flickr.Response;
import com.googlecode.flickr2twitter.com.aetrion.flickr.Transport;
import com.googlecode.flickr2twitter.com.aetrion.flickr.people.User;
import com.googlecode.flickr2twitter.com.aetrion.flickr.util.UrlUtilities;
import com.googlecode.flickr2twitter.com.aetrion.flickr.util.XMLUtilities;
import com.googlecode.flickr2twitter.com.twmacinta.util.MD5;
/**
* Authentication interface.
*
* @author Anthony Eden
*/
public class AuthInterface {
public static final String METHOD_CHECK_TOKEN = "flickr.auth.checkToken";
public static final String METHOD_GET_FROB = "flickr.auth.getFrob";
public static final String METHOD_GET_TOKEN = "flickr.auth.getToken";
public static final String METHOD_GET_FULL_TOKEN = "flickr.auth.getFullToken";
public static final String METHOD_GET_ACCESS_TOKEN = "flickr.auth.oauth.getAccessToken";
private String apiKey;
private String sharedSecret;
private Transport transportAPI;
/**
* Construct the AuthInterface.
*
* @param apiKey The API key
* @param transport The Transport interface
*/
public AuthInterface(
String apiKey,
String sharedSecret,
Transport transport
) {
this.apiKey = apiKey;
this.sharedSecret = sharedSecret;
this.transportAPI = transport;
}
/**
* Check the authentication token for validity.
*
* @param authToken The authentication token
* @return The Auth object
* @throws IOException
* @throws SAXException
* @throws FlickrException
*/
public Auth checkToken(String authToken) throws IOException, SAXException, FlickrException {
List<Parameter> parameters = new ArrayList<Parameter>();
parameters.add(new Parameter("method", METHOD_CHECK_TOKEN));
parameters.add(new Parameter("api_key", apiKey));
parameters.add(new Parameter("auth_token", authToken));
// This method call must be signed.
parameters.add(
new Parameter(
"api_sig",
AuthUtilities.getSignature(sharedSecret, parameters)
)
);
Response response = transportAPI.get(transportAPI.getPath(), parameters);
if (response.isError()) {
throw new FlickrException(response.getErrorCode(), response.getErrorMessage());
}
Auth auth = new Auth();
Element authElement = response.getPayload();
auth.setToken(XMLUtilities.getChildValue(authElement, "token"));
auth.setPermission(Permission.fromString(XMLUtilities.getChildValue(authElement, "perms")));
Element userElement = XMLUtilities.getChild(authElement, "user");
User user = new User();
user.setId(userElement.getAttribute("nsid"));
user.setUsername(userElement.getAttribute("username"));
user.setRealName(userElement.getAttribute("fullname"));
auth.setUser(user);
return auth;
}
/**
* Get the full authentication token for a mini-token.
* @param miniToken The mini-token typed in by a user.
* It should be 9 digits long. It may optionally contain dashes.
* @return an Auth object containing the full token, permissions and user info.
* @throws IOException
* @throws SAXException
* @throws FlickrException
*/
public Auth getFullToken(String miniToken) throws IOException, SAXException, FlickrException {
List<Parameter> parameters = new ArrayList<Parameter>();
parameters.add(new Parameter("method", METHOD_GET_FULL_TOKEN));
parameters.add(new Parameter("api_key", apiKey));
parameters.add(new Parameter("mini_token", miniToken));
// This method call must be signed.
parameters.add(new Parameter("api_sig", AuthUtilities.getSignature(sharedSecret, parameters)));
Response response = transportAPI.get(transportAPI.getPath(), parameters);
if (response.isError()) {
throw new FlickrException(response.getErrorCode(), response.getErrorMessage());
}
Auth auth = new Auth();
Element authElement = response.getPayload();
auth.setToken(XMLUtilities.getChildValue(authElement, "token"));
auth.setPermission(Permission.fromString(XMLUtilities.getChildValue(authElement, "perms")));
Element userElement = XMLUtilities.getChild(authElement, "user");
User user = new User();
user.setId(userElement.getAttribute("nsid"));
user.setUsername(userElement.getAttribute("username"));
user.setRealName(userElement.getAttribute("fullname"));
auth.setUser(user);
return auth;
}
/**
* Get a frob.
*
* @return the frob
* @throws IOException
* @throws SAXException
* @throws FlickrException
*/
public String getFrob() throws IOException, SAXException, FlickrException {
List<Parameter> parameters = new ArrayList<Parameter>();
parameters.add(new Parameter("method", METHOD_GET_FROB));
parameters.add(new Parameter("api_key", apiKey));
// This method call must be signed.
parameters.add(new Parameter("api_sig", AuthUtilities.getSignature(sharedSecret, parameters)));
Response response = transportAPI.get(transportAPI.getPath(), parameters);
if (response.isError()) {
throw new FlickrException(response.getErrorCode(), response.getErrorMessage());
}
return XMLUtilities.getValue(response.getPayload());
}
/**
* Get an authentication token for the specific frob.
*
* @param frob The frob
* @return The Auth object
* @throws IOException
* @throws SAXException
* @throws FlickrException
*/
public Auth getToken(String frob) throws IOException, SAXException, FlickrException {
List<Parameter> parameters = new ArrayList<Parameter>();
parameters.add(new Parameter("method", METHOD_GET_TOKEN));
parameters.add(new Parameter("api_key", apiKey));
parameters.add(new Parameter("frob", frob));
// This method call must be signed.
parameters.add(new Parameter("api_sig", AuthUtilities.getSignature(sharedSecret, parameters)));
Response response = transportAPI.get(transportAPI.getPath(), parameters);
if (response.isError()) {
throw new FlickrException(response.getErrorCode(), response.getErrorMessage());
}
Auth auth = new Auth();
Element authElement = response.getPayload();
auth.setToken(XMLUtilities.getChildValue(authElement, "token"));
auth.setPermission(Permission.fromString(XMLUtilities.getChildValue(authElement, "perms")));
Element userElement = XMLUtilities.getChild(authElement, "user");
User user = new User();
user.setId(userElement.getAttribute("nsid"));
user.setUsername(userElement.getAttribute("username"));
user.setRealName(userElement.getAttribute("fullname"));
auth.setUser(user);
return auth;
}
/**
* Exchange an auth token from the old Authentication API, to an OAuth access token.
* Calling this method will delete the auth token used to make the request.
*
* @return the new oauth token
* @throws IOException
* @throws SAXException
* @throws FlickrException
*/
public OAuth getOAuthRequestToken(String userOAuthToken) throws IOException, SAXException, FlickrException {
List<Parameter> parameters = new ArrayList<Parameter>();
parameters.add(new Parameter("method", METHOD_GET_ACCESS_TOKEN));
parameters.add(new Parameter("api_key", apiKey));
parameters.add(new Parameter("auth_token", userOAuthToken));
// This method call must be signed.
parameters.add(new Parameter("api_sig", AuthUtilities.getSignature(sharedSecret, parameters)));
Response response = transportAPI.get(transportAPI.getPath(), parameters);
if (response.isError()) {
throw new FlickrException(response.getErrorCode(), response.getErrorMessage());
}
Element authElement = response.getPayload();
Element tokenElement = XMLUtilities.getChild(authElement, "access_token");
String oauthToken = tokenElement.getAttribute("oauth_token");
String tokenSecret = tokenElement.getAttribute("oauth_token_secret");
return new OAuth(oauthToken, tokenSecret);
}
/**
* Build the authentication URL using the given permission and frob.
*
* The hostname used here is www.flickr.com. It differs from the api-default
* api.flickr.com.
*
* @param permission The Permission
* @param frob The frob returned from getFrob()
* @return The URL
* @throws MalformedURLException
* @throws UnsupportedEncodingException
*/
public URL buildAuthenticationUrl(Permission permission, String frob, String callbackUrl) throws MalformedURLException, UnsupportedEncodingException {
List<Parameter> parameters = new ArrayList<Parameter>();
parameters.add(new Parameter("api_key", apiKey));
parameters.add(new Parameter("frob", frob));
parameters.add(new Parameter("perms", permission.toString()));
// The parameters in the url must be signed
if (callbackUrl != null) {
//more detail could be found at http://www.flickr.com/groups/api/discuss/72157601198885954/
String enc = System.getProperty("file.encoding");
callbackUrl = URLEncoder.encode(callbackUrl, enc);
parameters.add(new Parameter("extra", callbackUrl));
String token = sharedSecret + "api_key" + apiKey + "extra" + callbackUrl + "frob" + frob + "perms" + permission.toString();
MD5 md5 = new MD5();
md5.Update(token);
parameters.add(new Parameter("api_sig", md5.asHex()));
} else {
parameters.add(new Parameter("api_sig", AuthUtilities.getSignature(sharedSecret, parameters)));
}
String host = "www.flickr.com";
int port = transportAPI.getPort();
String path = "/services/auth/";
return UrlUtilities.buildUrl(host, port, path, parameters);
}
}