I'm trying to create a simple Andriod App which allows users to login using Google+ Sign in.
Once signed in, they can access a J2ee server urls. As part of J2ee server logic, i want to validate whether the requests are coming from authenticated and\
riod app.
Based on google help documentation and lot of other blogs, i have created 2 clientds ( under Credentails section in google developer console ).
Client ID for Android application
Service account
private static final String scopes = "audience:server:client_id:" + SERVER_CLIENT_ID; // id from Service Account
String accountName = Plus.AccountApi.getAccountName(mGoogleApiClient);
Account account = new Account(accountName, GoogleAuthUtil.GOOGLE_ACCOUNT_TYPE);
String idToken = GoogleAuthUtil.getToken(getApplicationContext(), account, scopes);
I am getting error at the last line ( GoogleAuthUtil.getToken ).
com.google.android.gms.auth.GoogleAuthException: Unknown
I am not able to proceed further. Am i doing something wrong here??
I see a lot of similar questions on stackoverflow, however most of them seem to their issues fixed. I tried every suggestion. Looks like i am doing somethi\
ng wrong.
Can someone point me in the correct direction.
Related
I have been trying to solve this for a few days now but i can't figure out what the problem is.
I have a user pool and an identity pool on AWS Cognito. I have run the sample code and used it to log in and register users with Facebook and Google+ successfully. After login i am able to authenticate using the token to use SNS or the Sync services.
I have registered a user and got a token (after logging in) with Cognito Identity. However the next step is to use the token to authenticate into the identity pool. This is where i keep getting the error
I have followed the instructions from Integrating User Pools with Amazon Cognito Identity and I get a token which I then try to pass it along with the pool id to the credentials provider.
credentialsProvider.clear();
credentialsProvider.withLogins(loginMap).refresh();
My code fails on refresh(). At this point credentialsProvider is a AWSBasicCognitoIdentityProvider and refresh() fails in the super.refresh() which calls getIdentityId() in the abstract parent class AWSAbstractCognitoIdentityProvider
#Override
public String getIdentityId() {
if (identityId == null) {
GetIdRequest getIdRequest = new GetIdRequest()
.withAccountId(getAccountId())
.withIdentityPoolId(getIdentityPoolId())
.withLogins(loginsMap);
appendUserAgent(getIdRequest, getUserAgent());
GetIdResult getIdResult = cib.getId(getIdRequest);
No matter what values i put in the loginsMap, i get the error
Invalid login token. Issuer doesn't match providerName
at cid.getid(getIdRequest).
Most of the code is available to download free if you create an app in the Mobile Hub and generate the code. You can then configure authentication providers - FB, Google , etc.
What am I doing wrong ?
Thanks.
Edit : Here are examples of what i have tried
The token is always the object in the map. Below are the different keys
"cognito-identity.amazonaws.com"
the User Pool id - us-east-1_xxxxxxxxx
the User Pool ARN - cognito-idp:us-east-1:xxxxxxxxxxxx:userpool/us-east-1_xxxxxxxxx
OK i found the answer - I was putting in the wrong key value in the loginMap.
it should be
cognito-idp.<region>.amazonaws.com/<YOUR_USER_POOL_ID>
as it says in the documentation linked in the question
I don't know how I didn't see that.
I'm trying to develop an application that makes use of some basic Google+ Apis. The app request a token from Google that then upload on my server and my server check for its validation with Google. What I don't understand (I'm a bit confused) is what's the difference between Client ID for Web application and Client ID for Android application in Google Developers Console. I've tried both of them on the Android app and both work (successfully obtained a token). Obviously, when using the Web Client ID, my SCOPE that I pass using GoogleAuthUtil.getToken() is different from the one using Android Client ID. So, what's the difference between them? I think that I should go for the Android Client ID, but I'd like to know the really differences.
On client side I use:
final String token = GoogleAuthUtil.getToken(mContext, userEmail, G_PLUS_SCOPE);
Where G_PLUS_SCOPE = oauth2:https://www.googleapis.com/auth/plus.me
On server side, I check with Google with this code:
GoogleIdToken token = GoogleIdToken.parse(mJFactory, getRequest().getAuthToken());
if (mVerifier.verify(token)) {
GoogleIdToken.Payload tempPayload = token.getPayload();
if (!tempPayload.getAudience().equals(mAudience)) {
problem = "Audience mismatch";
errorMessage = new ErrorMessage(ErrorCodes.AUDIENCE_MISMATCH,problem,null);
mResponse = new ErrorResponse( errorMessage);
}
else if (!mClientIDs.contains(tempPayload.getAuthorizedParty())) {
problem = "Client ID mismatch";
errorMessage = new ErrorMessage(ErrorCodes.CLIENT_ID_MISMATCH,problem,null);
mResponse = new ErrorResponse(errorMessage);
}
I also don't understand what's the exact value of mAudience. Do I need to put the Client ID as mAudience? And, is the mClientIDs the array containing all the key (Including the Android client ID key)?
Thanks for your help
EDIT: Following http://android-developers.blogspot.it/2013/01/verifying-back-end-calls-from-android.html I've read that the Audience is the Client ID for Web Application and the mIds are all the ID for installed application (1 for me because I've only Android). But I'm not sure if this is the right way of thinking it for every case.
I don't have answer to your question but I found this blog which can help you out:
http://www.androidhive.info/2014/02/android-login-with-google-plus-account-1/
I hope this helps you.
Technically the audience is the client ID which the ID token is intended to authenticate the user to, where the authorized party is the client ID which the ID token was issued to:
http://openid.net/specs/openid-connect-core-1_0.html#IDToken
You should verify both when both are provided. When requesting an ID Token from your Android app, you should use the Client ID of your server to make the request. Your server should then verify that it is the audience for the token when it receives it from your Android client.
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
Update:
Just now I signed up to Google API with the Google account I'm also using for the Google App Engine and now the error has changed to com.google.android.gms.auth.GoogleAuthException: Unknown
Google just released a new way to sign up to one's app via a Google Account and has given some explanation in their blogpost, too.
I'm writing an Android app you have to sign up for to create a user account and I'm using Google App Engine for the back end. With the play services, I want to get the users email affiliated with their Android device and a token. I can already get the email, however, getting the token only throws errors and due to the documentation being quite sparse, I don't know how to fix these. That's how I get the email:
private String[] getAccountNames() {
mAccountManager = AccountManager.get(this);
Account[] accounts = mAccountManager.getAccountsByType(GoogleAuthUtil.GOOGLE_ACCOUNT_TYPE);
names = new String[accounts.length];
for (int i = 0; i < names.length; i++) {
names[i] = accounts[i].name;
}
return names;
}
However, when I'm calling token = GoogleAuthUtil.getToken(context, email,
"scope", it gives me these errors:
GooglePlayServices not available due to error 1 and com.google.android.gms.auth.GooglePlayServicesAvailabilityException: GooglePlayServicesNotAvailable.
Now my question is, do I have to set any permissions or include any libraries to fix that? And what is the scope parameter? An example for how to get a token and what to put in for scope is given in their blogpost to set the scope variable to "https://www.googleapis.com/auth/userinfo.profile" but I still get the same error unfortunately.
I also registered my app for the Google API console and enabled the G+ API, do I have to configure something else there, too?
I had the same problem using the Google Client Library for Google Drive.
The solution is pretty easy. Just prepend "oauth2:" to your scopeUrl.
Wrong:
GoogleAuthUtil.getToken(this, account.name, DriveScopes.DRIVE);
Right:
GoogleAuthUtil.getToken(this, account.name, "oauth2:" + DriveScopes.DRIVE);
You first need to pass the correctly formatted scope, like this:
private final static String G_PLUS_SCOPE =
"oauth2:https://www.googleapis.com/auth/plus.me";
private final static String USERINFO_SCOPE =
"https://www.googleapis.com/auth/userinfo.profile";
private final static String SCOPES = G_PLUS_SCOPE + " " + USERINFO_SCOPE;
You also need to install Google Play services from here, https://play.google.com/store/apps/details?id=com.google.android.gms. Google Play services has started to roll out to all devices with Google Play installed (Froyo+).
There is more information provided here: http://android-developers.blogspot.com/2012/09/google-play-services-and-oauth-identity.html
You can only get a token for Google services that support OAuth2. If you are writing your own webservice, you should authenticate to it by using its native authentication mechanism (username and password?). "Scope" is obviously an invalid scope, but it seems that you don't have Google Play Services installed, and that is the cause of your error. You can install it from the Play Store, but it won't really work for you, since your are not using a Google service.
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