I solved this exact issue for my app Push Actions - http://www.pushactions.com. For my solution, I did end up using GAE, but only to authenticate the token. The actual Push Actions app is hosted on Heroku. Here's my flow:
- Android app generates GAE token then posts the token & the account's email
address to Push Actions running on
Heroku
- Push Actions posts the token to my service running on GAE
- The GAE service takes the token, determines if it is valid, and returns the email address it is valid for
- Push Actions compares the email address returned by GAE with the email address from the android app, if they match, the token is valid for that email address. This means the token can be safely associated with the google user's openid email address.
As far as I know, this is the ONLY way to verify if a token generated by AccountManager is valid. True, it does require the use of GAE, but only for one small piece of your overall app. My GAE service ended up being like 1 class and a few lines of code, so it isn't much. You can think of the GAE piece as a service provided by google for authenticating tokens.
Here is the code for my GAE service:
package com.pushactions;
import java.io.IOException;
import java.util.logging.Logger;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.google.appengine.api.users.User;
import com.google.appengine.api.users.UserService;
import com.google.appengine.api.users.UserServiceFactory;
@SuppressWarnings("serial")
public class PushActionsAuthServlet extends HttpServlet {
private static final Logger log = Logger.getLogger(HttpServlet.class.getName());
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
UserService userService = UserServiceFactory.getUserService();
User user = userService.getCurrentUser();
if (user != null) {
req.setAttribute("user", user);
try {
req.getRequestDispatcher("/logged_in.jsp").forward(req, resp);
} catch (ServletException e) {
log.severe("Couldn't redirect to logged_in.jsp");
}
} else {
try {
req.getRequestDispatcher("/logged_out.jsp").forward(req, resp);
} catch (ServletException e) {
log.severe("Couldn't redirect to logged_out.jsp");
}
}
}
}
logged_in.jsp:
<%@ page import="com.google.appengine.api.users.User" %>
<% User user = (User)request.getAttribute("user"); %>
<?xml version="1.0" encoding="UTF-8"?>
<result>
<status>ok</status>
<user_name><%= user.getEmail() %></user_name>
</result>
logged_out.jsp:
<%@ page import="com.google.appengine.api.users.User" %>
<% User user = (User)request.getAttribute("user"); %>
<?xml version="1.0" encoding="UTF-8"?>
<result>
<status>error</status>
<message>not logged in</message>
</result>