I received an email from Google informing me that I need to migrate my Android app that uses FCM for client-to-client communication by early May 2022 to the more secure V1 protocol, along with a link to instructions. Following the link, I modified my server endpoint but am not sure where to get the authorization token:
final String serverKey = "Authorization: Bearer <valid Oauth 2.0 token>";
The docs () go on to say the following:
Depending on the details of your server environment, use a combination of these strategies to authorize server requests to Firebase services:
Google Application Default Credentials (ADC)
A service account JSON file
A short-lived OAuth 2.0 access token derived from a service account
At first glance, it looked like I needed to authenticate via ADC, but after more reading, it seems that ADC is used if I have my own code running on a Google server. I don't; I'm just pushing notifications to the user. So how should I proceed?
The following doc give you clear steps to migrate to HTTP V1.
https://firebase.google.com/docs/cloud-messaging/migrate-v1
Related
TL;DR - How can I refresh tokens backend-side if the oauth2 authorization happens in native android/ios app?
I am working on oauth2 integration with google calendar. My stack is react SPA app as web client and we have a backend API (in elixir). We are also using hybrid native apps, so our JS code is transformed into corresponding iOS/Android apps (using capacitor).
The flow is as follows:
user authorizes us to modify their calendars using oauth2, we ask for offline access
we acquire client-side authorization code from google
we send it to our backend and it uses the auth code to acquire access token and refresh token, the tokens are then persisted in our DB
we use the access token to perform updates to google calendar. When token expires we refresh it backend-side
This is the flow that is working on the web client, but with native apps (android/ios) I am stuck. When I use corresponding to ios/android apps clientIds from google console project credentials, my backend cannot successfully use it to acquire refresh and access tokens, I get the following response from https://oauth2.googleapis.com/token:
%{"error" => "invalid_client", "error_description" => "Unauthorized"}
I am considering moving the process of exchanging authorization code to refresh token and access token to the native apps, but how can the backend then have access to new access tokens? I can't refresh the tokens backend side if they were generated in the native app, I will again have clientId mismatch (also backend uses clientSecret, while native apps are exempt from using clientSecret).
You cant. The refresh token is client id based. You need the client id and client secret that were used to create it in order to refresh it.
The client used for Ios and android apps doesn't have a client id and secret that you could use backend.
You can do it the other way around though. If you created the refresh token in your backend app. The ios and android apps could refresh it as long as the client id is part of the same project.
I suspect there is something internal in the android and ios sdk's that allow for this. It just doesn't work with any other type of client due to the lack of client secret.
take a look at this documentation, it works form me in the same problem.
https://developers.google.com/identity/sign-in/ios/offline-access
"On your app's backend server, exchange the auth code for access and refresh tokens. Use the access token to call Google APIs on behalf of the user and, optionally, store the refresh token to acquire a new access token when the access token expires."
serverAuthCode is used on this api https://developers.google.com/identity/protocols/oauth2/native-app#exchange-authorization-code to generate a new refresh_token
I had the same issue and finally ended up.
In order to design user authentication from the mobile/front-end side and send the authorization code to the server-side to exchange it for access_token and referesh_token you have not to follow the Mobile or Installed App flow:
In this way, you've created Android app OAuth2 credentials in the google developer console and used its client_id for google oauth2 page preparation so at the end you will have access_token which works only on the mobile side and does not work on the backend as it doesn't have client_secret.
Therefore, if you want to have access to the google APIs on your server-side and just perform the google authentication on the mobile side you can choose one of the following flows:
As you can see from the above flows, there are three parts namely client-side (mobile), google, and server-side (backend) rather than communication just between mobile and google which is useful for installed applications, not web applications. To me, between these two flows, I prefer the last one as it has fewer requests to create access_token and refresh_token on the server-side.
Here's the whole procedure:
create a web application oauth2 credentials on the google developer console and use all sections in the backend and the client_id on the mobile side as well. Don't forget to enable the API you want to use.
create a /callback endpoint in the backend which is the same as redirect_uri that you will need on the mobile side. In this endpoint, you will get the authorization code from the google request and then exchange it to the access_token and referesh_token and persist that on the DB.
create an endpoint in order to call google API such as google calendar.
Bring up the google authorization page on the mobile using SDKs, web view, or browser with the following content: existing client_it (which is the same with server-side), redirect_uri (callback), response_type="code", scope="https://www.googleapis.com/auth/calendar", access_type="offline", include_granted_scopes=true, and state to put some string if you want, for example I sent user's uuid.
You can obtain access_token using refresh token by sending
POST https://oauth2.googleapis.com/token
x-www-form-urlencoded
client_id:CLIENTID
refresh_token:REFRESHTOKEN
grant_type:refresh_token
I am writing an Android app with a Google Cloud Endpoints backend, and I want to restrict my backend with a Google signin.
I have followed the Android instructions, and have successfully logged in. In other words, I have received a token, which I can then pass to the server and verify the user it stands for. Great.
However, I am missing the bigger picture here. Questions:
Am I supposed to be sending this token with each request back to the server, and repeat the process of verifying it in each request?
If yes, the token will expire at some point (1 hour I believe). I suppose the user does not have to login again, there should be away to avoid this, right?
Is a way to refresh the token (I think Google Signin is OAuth2)?
And most importantly, is all this the standard way someone uses Google signin to protect their backend? I was expecting this to be very straightforward process, since I am only using Google products. However, I am finding myself lost in pages and pages of documentation on Android and Cloud Enpoints with pieces of the puzzle.
Any help or insight is appreciated.
I have not used android authentication but google uses outh2 for all its authentication. Google SDKs may help you alleviate some of the pain of using oauth2. To answer your questions
Yes - You are in the world of token based authentication and you do send the token with every request.
Yes. token will expire after an hour. To get around this when you first do an oauth2 authentication, you also get a refresh token. When the token of the user expires you use the refresh token to get the new token. This refresh token can be stored on the client side. Client will find during one of its requests that that existing token is expired and would request for a new token using refresh token
Yes you use the google refresh token URL to use the refresh token and get the new token. I have given the important oauth URLs of google below.
This is indeed oauth2 process my friend.
since you are using cloud endpoint I believe that you would be making the authentication endpoints.
You generally make the following endpoints when doing oauth2 authentication using a service provider(google, facebook, github, etc):
https://webiste.com/auth/signin/{provider}
https://webiste.com/auth/callback/{provider}
https://webiste.com/auth/refresh/{provider}
Following are the google URLs for oauth2 that you would use:
oauth_url: 'https://accounts.google.com/o/oauth2/v2/auth', //start auth
token_url: 'https://accounts.google.com/o/oauth2/token', //get id_token, access_token, refresh_token token
refresh_token_url : 'https://www.googleapis.com/oauth2/v4/token',
token_info_url: 'https://www.googleapis.com/oauth2/v3/tokeninfo?id_token=', //validate token
You would also want to go through google's oauth2 documentation at https://developers.google.com/identity/protocols/OAuth2.
I think you should Firebase UI Android Library for Authentication. It provides you with Google, Facebook, Email, Twitter and Github signin options and good part is that it can be done by writing only few lines of code.
For more information click here.
It's best practice to use 3ed party code to do this. It will take much less time, will have much less bugs and will be very easy to expand to other methods later.
I would recommend Firebase because it's very easy, free, works well and owned by Google.
I'm doing a website in asp that uses Identity (v2.0) and also an Android app connected to the web site through Web API.
I've configured Identity to use Google OAuth signins and works quite well. Right now I'm trying to make a Web API for the app and I also need to authenticate mobile users.
I've reached to the point to configure Identity to manage bearer tokens for the api. But to perform a signin, the only way I've found is through user and password as documentation says:
grant_type=password&username=user&password=pass
Or perform OAuth challenge by web.
As Android also manages Google OAuth. Is there a way to configure Identity to perform signins using Google Oauth?
I have neither found a way to manage external bearer tokens or to use Google Authentication tokens to do a signing with Web Api with Identity.
Maybe I'm misunderstanding something.
Thanks in advance.
Ok, somehow I've found how to do it.
In Android, get an ID token using scope audience:server: as in Google "Accounts Authentication and Authorization" docs.
Send Web API token endpoin as user the email and as password the token.
grant_type=password&username={email}&password={GoogleToken}
In my extendend class from OAuthAuthorizationServerProvider in the server, I added token verification as from github repo googleplus/gplus-verifytoken-csharp to the method GrantResourceOwnerCredentials
If token is valid, I can populate a UserLoginInfo and find the user with UserManager.
Then normal authentication goes on and user is authenticated in identity as normal.
Anyway, I think there has to be a more elegant way to do it.
I'm building an Android app as part of a client/server architecture, where my server will provide a service to the Android client. The server will not communicate with any Google server, but will need to authenticate the user via their gmail account. That is, the server needs to be sure that the http(s) requests coming from the phone are indeed from the person with that specific gmail account.
I was looking into Android's C2DM framework, which I can certainly use for passing service-related data back and forth, but how can I use Google account authentication between an Android phone and a third-party (non-Google) server?
Will Oath2.0 work for this, or is Oath2.0 only used for direct authentication between the phone and Google's services?
You didn't mention which language code you're going to use in your server.
The easier way to use C2DM is inside Google App Engine which comes with native support for Android integrations with C2DM.
If that's not the case ( EX: youre using php in your own server ) I would take a look to AccountManager which can provides you the auth token ( the app-user must allow it ).
When registering a new device to your C2DM server you'll need the device to communicate also the token so you'll be able to know if the user is really owner of that gmail account through a connection between your server and Google Servers.
:)
I think you must have got the answer to your query by now. But I still would to answer this question to assist other users who are interested in achieving something like this.
So to use google account access token to authenticate and authorize your app user against your own services you have to follow following steps.
Create a project in Google Cloud Console with two components (Create components by clicking on "APIs $ Auth >Credetials" option on left pane ). First component will be your web component (e.g. web-services) and second component is your android application.
Try to get access token by querying account manager in android app by executing GoogleAuthUtil.getToken() method by passing the current context, email id(queried using account manager) and scope as ("audience:server:client_id:").
Where is the "Client ID" parameter of the web component available under the project created on Google Cloud Console.
The method will return you the ID token encoded as JSON web token or JWT.
This ID token everything that a app would require to authenticate user on server.
The ID token consists of following parameters
iss: always accounts.google.com
aud: the client ID of the web component of the project
azp: the client ID of the Android app component of project
email: the email which identifies the user requesting the token, along with some other fields.
Pass this token to your web component (e.g. web services) over https(mandatory) where the web component and Android component client id's are already stored.
After decoding the received JWT ID token on server, check if "aud" parameter of the token and stored web component client id are equal and hence authenticate the user.
User identity can be fetched by reading the email parameter of JWT ID token which specifies the email id provided to access the Id token in android application while executing GoogleAuthUtil.getToken() method.
Note : The ID token on android can only be fetched by executing GoogleAuthUtil.getToken() if it is the same application singed by same certificate specified while creating android component under the project on Google Cloud Console.
More information can be found on "https://developers.google.com/accounts/docs/CrossClientAuth"
I'd like to be able to send a POST request from an Android app to App Engine and have it linked to the user's Google account. I read that you need to obtain an authentication token and send it with the POST request. Does Android provide a way to request this token? And how would GAE process it?
I feel like this should be easy and I'm missing something obvious.
Thanks!
See my blog post on how to authenticate with an App Engine app using credentials stored in the phone.
It is possible to authenticate users programmatically. In the Python SDK, the appengine_rpc module performs this function. In a nutshell, the procedure is this:
Use ClientLogin to get a one-use authentication token given the user's username and password.
Make a POST request to yourapp.appspot.com/_ah/login, with the arguments continue=http://localhost/&auth=authtoken (where authtoken is the one-use token you got from step 1).
Intercept the 302 response returned and capture the returned Google cookie.
Supply the cookie on all subsequent requests.
For excruciating detail, see the source of appengine_rpc.py, linked above.
As of Android 2.0, you can use AccountManager to request an auth token for accounts of type com.google. You can then authenticate the user to an App Engine app by hitting the url:
http://[yourapp].appspot.com/_ah/login?auth=[theauthtoken]
The cookies set in the response can be piggybacked onto future requests to your app to authenticate the user against your app.
In the absence of sample code that does exactly this, you can check out the Sample Sync Adapter code (bundled with the SDK) for a general idea about requesting auth tokens.
EDIT: Just realized Nick wrote about the second part, but the AccountManager#getAuthToken bit is new as of Android 2.0.