How to make AccountManager (authtoken) and OpenID

2020-05-19 07:32发布

问题:

I am making an Android app which should be able to get data from a web service (which is not part of GAE). Users are able to log in to web service through their browser by using OpenId (only Google accounts are allowed).

AccountManager can give me authtoken. I could save this authtoken on my server, together with user's google account name (email) and then use this account name to connect his openid login with app registration.

But this does not solve anything because I have no way to verify this token against user's OpenID information... Or do I? I thought I could use user's authtoken to "somehow" link his android account to the web account.

This looks more and more like a wrong way to handle this but I do not want to save users Google's username/password in SharedPreferences and use these data for login.

Any creative ideas? Thanks

回答1:

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:

  1. Android app generates GAE token then posts the token & the account's email address to Push Actions running on Heroku
  2. Push Actions posts the token to my service running on GAE
  3. The GAE service takes the token, determines if it is valid, and returns the email address it is valid for
  4. 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>