Reputation: 6991
Im trying to create a mockup for an application that accesses the Mail of users after OAuth authentication. I intend to retrieve the mail using the following code snippet Based off the example here :http://code.google.com/p/google-mail-oauth2-tools/source/browse/trunk/java/com/google/code/samples/oauth2/OAuth2Authenticator.java
/**
* Performs OAuth2 authentication.
*
* <p>Before using this class, you must call {@code initialize} to install the
* OAuth2 SASL provider.
*/
public class OAuth2Authenticator {
private static final Logger logger =
Logger.getLogger(OAuth2Authenticator.class.getName());
public static final class OAuth2Provider extends Provider {
private static final long serialVersionUID = 1L;
public OAuth2Provider() {
super("Google OAuth2 Provider", 1.0,
"Provides the XOAUTH2 SASL Mechanism");
put("SaslClientFactory.XOAUTH2",
"com.test.OAuth2SaslClientFactory");
}
}
/**
* Installs the OAuth2 SASL provider. This must be called exactly once before
* calling other methods on this class.
*/
public static void initialize() {
Security.addProvider(new OAuth2Provider());
}
/**
* Connects and authenticates to an IMAP server with OAuth2. You must have
* called {@code initialize}.
*
* @param host Hostname of the imap server, for example {@code
* imap.googlemail.com}.
* @param port Port of the imap server, for example 993.
* @param userEmail Email address of the user to authenticate, for example
* {@code [email protected]}.
* @param oauthToken The user's OAuth token.
* @param debug Whether to enable debug logging on the IMAP connection.
*
* @return An authenticated IMAPStore that can be used for IMAP operations.
*/
public static IMAPStore connectToImap(String host,
int port,
String userEmail,
String oauthToken,
boolean debug) throws Exception {
Properties props = new Properties();
props.put("mail.imaps.sasl.enable", "true");
props.put("mail.imaps.sasl.mechanisms", "XOAUTH2");
props.put(OAuth2SaslClientFactory.OAUTH_TOKEN_PROP, oauthToken);
Session session = Session.getInstance(props);
session.setDebug(debug);
final URLName unusedUrlName = null;
IMAPSSLStore store = new IMAPSSLStore(session, unusedUrlName);
final String emptyPassword = "";
store.connect(host, port, userEmail, emptyPassword);
return store;
}
/**
* Connects and authenticates to an SMTP server with OAuth2. You must have
* called {@code initialize}.
*
* @param host Hostname of the smtp server, for example {@code
* smtp.googlemail.com}.
* @param port Port of the smtp server, for example 587.
* @param userEmail Email address of the user to authenticate, for example
* {@code [email protected]}.
* @param oauthToken The user's OAuth token.
* @param debug Whether to enable debug logging on the connection.
*
* @return An authenticated SMTPTransport that can be used for SMTP
* operations.
*/
public static SMTPTransport connectToSmtp(String host,
int port,
String userEmail,
String oauthToken,
boolean debug) throws Exception {
Properties props = new Properties();
props.put("mail.smtp.starttls.enable", "true");
props.put("mail.smtp.starttls.required", "true");
props.put("mail.smtp.sasl.enable", "true");
props.put("mail.smtp.sasl.mechanisms", "XOAUTH2");
props.put(OAuth2SaslClientFactory.OAUTH_TOKEN_PROP, oauthToken);
Session session = Session.getInstance(props);
session.setDebug(debug);
final URLName unusedUrlName = null;
SMTPTransport transport = new SMTPTransport(session, unusedUrlName);
// If the password is non-null, SMTP tries to do AUTH LOGIN.
final String emptyPassword = "";
transport.connect(host, port, userEmail, emptyPassword);
return transport;
}
/**
* Authenticates to IMAP with parameters passed in on the commandline.
*/
public static void main(String args[]) throws Exception {
/*if (args.length != 2) {
System.err.println(
"Usage: OAuth2Authenticator <email> <oauthToken>");
return;
}*/
String email = "[email protected]";//hard coded
String oauthToken = "4/ipdG328T75Z1RO-oU1ZpVx07-UY-.Mv7XkFpsg9USEnp6UAPFm0EIgurXgQI";// hard coded
initialize();
IMAPStore imapStore = connectToImap("imap.gmail.com",
993,
email,
oauthToken,
true);
System.out.println("Successfully authenticated to IMAP.\n");
SMTPTransport smtpTransport = connectToSmtp("smtp.gmail.com",
587,
email,
oauthToken,
true);
System.out.println("Successfully authenticated to SMTP.");
}
And Im trying to get the OAuth token using a web page similar to the one in this page http://ocpsoft.org/java/setting-up-google-oauth2-with-java/ by explicitly printing out the value of
request.getParameter("code")//value used for OAuth token in above code
which is supposed to be the OAuth token.
But when I try to run the above program I get an error saying Invalid Credentials
Here's a detailed stack trace:
DEBUG: setDebug: JavaMail version 1.5.0
DEBUG: mail.imap.fetchsize: 16384
DEBUG: mail.imap.statuscachetimeout: 1000
DEBUG: mail.imap.appendbuffersize: -1
DEBUG: mail.imap.minidletime: 10
DEBUG: enable SASL
DEBUG: SASL mechanisms allowed: XOAUTH2
DEBUG: trying to connect to host "imap.gmail.com", port 993, isSSL true
* OK Gimap ready for requests from 174.26.139.84 av9if2076257pac.214
A0 CAPABILITY
* CAPABILITY IMAP4rev1 UNSELECT IDLE NAMESPACE QUOTA ID XLIST CHILDREN X-GM-EXT-1 XYZZY SASL-IR AUTH=XOAUTH AUTH=XOAUTH2 AUTH=PLAIN AUTH=PLAIN-CLIENTTOKEN
A0 OK Thats all she wrote! av9if2076257pac.214
DEBUG IMAP: AUTH: XOAUTH
DEBUG IMAP: AUTH: XOAUTH2
DEBUG IMAP: AUTH: PLAIN
DEBUG IMAP: AUTH: PLAIN-CLIENTTOKEN
DEBUG: protocolConnect login, host=imap.gmail.com, [email protected], password=<non-null>
IMAP SASL DEBUG: Mechanisms: XOAUTH2
IMAP SASL DEBUG: SASL client XOAUTH2
A1 AUTHENTICATE XOAUTH2
+
IMAP SASL DEBUG: challenge: :
IMAP SASL DEBUG: callback length: 1
IMAP SASL DEBUG: callback 0: javax.security.auth.callback.NameCallback@57799932
IMAP SASL DEBUG: response: [email protected]=Bearer 4/ipdG328T75Z1RO-oU1ZpVx07-UY-.Mv7XkFpsg9USEnp6UAPFm0EIgurXgQI :
dXNlcj12aXZla21haGFkZXZhbi52QGdtYWlsLmNvbQFhdXRoPUJlYXJlciA0L2lwZEczMjhUNzVaMVJPLW9VMVpwVngwNy1VWS0uTXY3WGtGcHNnOVVTRW5wNlVBUEZtMEVJZ3VyWGdRSQEB
+ eyJzdGF0dXMiOiI0MDAiLCJzY2hlbWVzIjoiQmVhcmVyIiwic2NvcGUiOiJodHRwczovL21haWwuZ29vZ2xlLmNvbS8ifQ==
IMAP SASL DEBUG: no response
A1 NO [ALERT] Invalid credentials (Failure)
Exception in thread "main" javax.mail.AuthenticationFailedException: [ALERT] Invalid credentials (Failure)
at com.sun.mail.imap.IMAPStore.protocolConnect(IMAPStore.java:660)
at javax.mail.Service.connect(Service.java:345)
at com.test.OAuth2Authenticator.connectToImap(OAuth2Authenticator.java:73)
at com.test.OAuth2Authenticator.main(OAuth2Authenticator.java:129)
Any insight would be appreciated. Thanks!
Upvotes: 2
Views: 1979
Reputation: 71
What you're getting back (the authcode) has to be exchanged with google for an accesstoken.
oauth2.py, in the same project you started with, is the easiest way to grab a token for testing. If you want to do the token exchange in java, you can start with this library:
http://code.google.com/p/google-oauth-java-client/
final GoogleTokenResponse response = flow.newTokenRequest(code).setRedirectUri(CALLBACK_URI).execute();
String accessToken = response.getAccessToken();
It's kind of gross. But it works.
Upvotes: 2