AccountManager and OAuth - how to add account? - android

My application connects with the server, which uses OAuth authorization.
How should I store such accounts in Account Manager?
In case I have login and pass, it can look like below:
Account account = new Account("user1", context.getString(R.string.ACCOUNT_TYPE));
AccountManager am = AccountManager.get(context);
if (am.addAccountExplicitly(account, "pass1", null)) {
result = new Bundle();
Log.i(TAG, "account: "+account.name+", "+account.type);
result.putString(AccountManager.KEY_ACCOUNT_NAME, account.name);
result.putString(AccountManager.KEY_ACCOUNT_TYPE, account.type);
activity.setAccountAuthenticatorResult(result);
But what should be passed instead of user name and pass in case of OAuth-account?
And where should I store OAuth-secret? OAuth token should be stored in KEY_AUTHTOKEN?

Don't use the password you could setAuthToken, put the OAuth token there instead:
It's important to understand that AccountManager is not an encryption service or a keychain. It stores account credentials just as you pass them, in plain text. On most devices, this isn't a particular concern, because it stores them in a database that is only accessible to root. But on a rooted device, the credentials would be readable by anyone with adb access to the device.
With this in mind, you shouldn't pass the user's actual password to AccountManager.addAccountExplicitly(). Instead, you should store a cryptographically secure token that would be of limited use to an attacker. If your user credentials are protecting something valuable, you should carefully consider doing something similar.
http://developer.android.com/training/id-auth/custom_auth.html

Related

Android AccountManager and dmfs/oauth2-essentials using refresh token

I am trying to use dmfs/oauth2-essentials for oauth2 in an application. The problem is the refresh token. I am able to store the token string and refresh token string in AccountManager. Refresh token using userdata bundle. User first logins with ResourceOwnerPasswordGrant and receives a token with refresh token.
The problem is that Bundle accepts just primitive things like strings to be stored. But the dmfs/oauth2-essentials require the OAuth2AccessToken object when using TokenRefreshGrant()
Is there a way to use the refresh token string directly? am I missing something?
Thanks!
I don't know if you've solved your problem, but I'll write here my experience in case it's handy for somebody.
You can create an Account in android using AccountManager. You're right by storing AccessToken in the Account, but perhaps you haven't realised that you can store multiple tokens within an Account, just by typing different token type. That way, you can retrieve different tokens using peekAuthToken(Account account, String authTokenType) just by passing a different authTokenType String. Be careful not letting the user to retrieve a refreshToken outside your Authenticator in getAuthToken(AccountAuthenticatorResponse response, Account account, String authTokenType, Bundle options), I do so by comparing authTokenType string.

OAuth 2.0 on Android for Web login

I wish to login to a webpage that uses Google Oauth2.0 from native android app.
I was looking into account manager but I don't think it can work
AccountManager am = AccountManager.get(this);
Bundle options = new Bundle();
am.getAuthToken(
new Account("t....#gmail.com", "com.google"),// Account retrieved using getAccountsByType()
" some scope?", // Auth scope
options, // Authenticator-specific options
this, // Your activity
new OnTokenAcquired(), // Callback called when a token is successfully acquired
new Handler(new OnError()));
What scope should I use. Or will I have to follow a different way to login
from https://developers.google.com/accounts/docs/OAuth2Login (#2 may interest you)
The scope value must begin with the string openid and then include either or both of profile and email. Any permutation of those values will work but the most common will be openid email or openid profile.
As you have not included anything specific I am assuming "openid,email" should work for you and https://developers.google.com/oauthplayground/ can give you the list of scopes you can use.

accountmanager refresh token(offline access)

I use google login through account manager in my android app. I can get accesstoken which I send to server and server can create/login new user. Accesstoken is valid only 3600seconds. Problem is that server can not update user's info after this time expires. Web app requires check user's info periodically.
How can I get authentication token and refresh token from android account manager so than server can use refresh token to update data periodically? I don't want use login through webview in android app.
Thanks
This is now possible: https://developers.google.com/+/mobile/android/sign-in#server-side_access_for_your_app
You request a one-time authorisation code, send it to your server and your server exchanges it for an access token and refresh token.
Currently you can't, which I'm sure is not the answer you're hoping for, sorry about that! If you have a web sign in, you can use the hybrid flow to get a refresh token on the server as well (see https://developers.google.com/+/web/signin/server-side-flow), but there's no way of retrieving a code as part of the Android or iOS flows.
If this is something that you need for you use case, could you file a feature request on here: https://code.google.com/p/google-plus-platform/issues - we are actively looking at the number of stars on that to gauge demand for various features.
Google Authorization process through account manager:
Email id can be got from
AccountManager accountManager = AccountManager.get(getApplicationContext());
Account[] accounts = accountManager.getAccountsByType("com.google");
String emailID = accounts[0].name; // you can retrieve using google account chooser way also
These lines should be run in separate token(not in UI thread).
String scope = "oauth2:https://www.googleapis.com/auth/userinfo.profile https://gdata.youtube.com";
String accessToken = GoogleAuthUtil.getToken(mContext, emailID, scope);
save the the accessToken and use for your api access.
After one hour (i.e. 3600 seconds), we need to refresh the access token. But now google is not supporting access after one hour. We have to restart the application and use the following lines to get access token.
String scope = "oauth2:https://www.googleapis.com/auth/userinfo.profile https://gdata.youtube.com";
String accessToken = GoogleAuthUtil.getToken(mContext, emailID, scope);
This background thread will always run in background in while loop

Use Android AccountManager to do AppEngine login through UserService

I'm using Google AppEngine, and I'm using their UserService class to handle user accounts and logging in. I don't need to access any information about their account - I'm just using it to differentiate users.
Now the website is mostly just a backend. I'm using an Android app for the frontend. I know you can access Google user accounts on the device using the AccountManager. It's definitely the safest way to get a user to log in. And I got that much to work.
Where I'm stuck is passing the login information from the Android app to the AppEngine website. From what I've ready I should be using OAuth, and I see the walkthrough here for using it with Google APIs, but I don't need to access an API, just to log in. I've been able to acquire an Authentication Token in the app, but I'm not sure how to pass it to the website, or if that's even the right direction. Should I be using a specific OAuth login on the server, like this guy?
Any help would be greatly appreciated!
Here's the relevant code:
Server (GAE):
UserService userService = UserServiceFactory.getUserService();
User user = userService.getCurrentUser();
if (user == null) {
resp.sendRedirect(userService.createLoginURL(req.getRequestURI()));
return;
}
Client (Android):
AccountManager am = AccountManager.get(this);
Account[] accounts = am.getAccountsByType("com.google");
Bundle options = new Bundle();
am.getAuthToken(
accounts[0], // Account retrieved using getAccountsByType()
"Manage your tasks", // Auth scope
options, // Authenticator-specific options
this, // Your activity
new OnTokenAcquired(), // Callback called when a token is successfully acquired
new Handler(new OnError()));
//Now what!?
This blog post covered exactly what I needed.
For two alternate (and in my opinion less than ideal) solutions, check out this thread: Webservice credentials - OpenID/Android AccountManager?

Using authToken for Google Health Data

We have developed and published an app for Google Health. Now we want to avoid every time logging into the gmail account by asking username and password.
So as to do this i have heard that I can have following options.
1. OAuth
2. Account Manager
3.
The problem with OAuth is that it will go via Android -> Web App -> Health path so i will need to develop an web app as well which we dont wish to do it right now.
So I am trying to use Account Manager, here is my code with which I could get list of accounts and an valid authToken for the selected account.
AccountManager mgr = AccountManager.get(getApplicationContext());
System.out.println("Got account manager");
Account[] accts = mgr.getAccounts();
}
Account acct = accts[0];
AccountManagerFuture<Bundle> accountManagerFuture = mgr.getAuthToken(acct, "android", null, this, null, null);
Bundle authTokenBundle = accountManagerFuture.getResult();
System.out.println("Account name "+accts[0].name);
String authToken = authTokenBundle.get(AccountManager.KEY_AUTHTOKEN).toString();
System.out.println("Got token:"+authToken);
But now I am confused about how to use this token to access the health data.
For getting the demographic feed we used the following code,where we explicitly made user to login into our application.
String queryURL = "https://www.google.com/health/feeds/profile/ui/" + profileId +"/-/DEMOGRAPHICS";
getDemoGrInfoQuery = new Query(new URL(queryURL));
Feed dempGrResultFeed;
globals = new Globals();
dempGrResultFeed = healthService.query(getDemoGrInfoQuery, Feed.class);
And thus we used to get the Feed using the URL.
And now I want to skip the login process and use the above authToken for retrieving the feed. How can this be done?
Any help would be really appreciated!!!
Thanks in advance,
As the standard OAuth procedure is supposed to work, you open the OAuth URL in a WebView (or anything similar) with all the required parameters, users provide Google (not your app) with their user name and password, then google gives you a token which you can use for your future communications.
This way the user doesn't have to give you their login credentials. They give it only to google, and google gives you a token which will authenticate your app every time you use it.
I think you should be good to go with this, since it requires you to open a WebView only once, unless the user logs out of google using your application or denies access to your application.
After getting the token, you just start polling google with that token and never ask user for their login credentials. quite seamless.
UPDATE
After our conversation in chat, let me tell you that you'll have to register an application with google, which will give you an appID, this appID will be used by your Android app to tell google that it is requesting permission on behalf of the Application which this appID refers to.
UPDATE 2
open the Google OAUth with all the parameters, google will give you a code
use that code and create a POST request again to google, and google will now return a long lasting AccessToken
You can then use this AccessToken in all your future communications

Categories

Resources