Reputation: 146
Summary: I'm trying to use stored Google accounts on an Android application to authenticate users in a native application, with an API provided by a Rails 3 + Devise application, and I'm stuck.
Details: We have an application (http://push-poll.com) which lets users gather feedback from a bunch of their friends. We've also built a native Android application. Our web app allows you to log in with your Google account, and we want to extend that functionality to the native Android app. The web app accomplishes this with Devise (for account permissions) + Omniauth (for Google account info and OAuth interaction).
Versions: Android 2.1+, Rails 3.2.2, Devise 2.1.2, Omniauth 1.1.0
Proposed authentication workflow:
I've scoured Google's documentation, but I am totally stuck on (4) and (5). Once I have the Google-provided email address, everything works as it does now (for either standard logins or Google/Omniauth/Devise accounts). By my best guess, this can be solved with either of the following:
I've been banging my head against a wall on this one for at least a week.
FYI: I'm the web dev, and our Android dev has been kind enough to furnish me with a stubbed-out Android app that'll send an access token from Android to the API endpoint of my choosing.
Upvotes: 1
Views: 1442
Reputation: 146
OK, so I was able to resolve this with a little better understanding of OAuth. Apparently tokens are able to be passed around between different servers and it doesn't really matter who holds them, they continue to function.
So, using Android's AccountManager I was able to extract a token with sufficient permissions for the scope userinfo.email, and then sending that to the server. Then the server can hit:
https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=TOKENVALUE
Note: This is being sent to the Rails app via HTTPS - you should never send a token over the internet in clear text.
Here's a partial clip of how we do this:
# Use Google's Token Verification scheme to extract the user's email address
token = params[:token]
uri = URI.parse("https://www.googleapis.com")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
path = "/oauth2/v1/tokeninfo?access_token=#{token}"
resp, data = http.get(path)
data = JSON.parse(data)
if resp.code == "200"
# Find a user
@user = User.where(:email => data["email"]).first
if !@user
#Create a user with the data we just got back
end
else
# Bad or revoked token
end
Upvotes: 2