Obtaining offline access for web backend using Firebase for Android - android

I am using Firebase SDK for authorising user on the Android app for a project which is on App Engine and already using many of the GCP and`G-Suite functionalities.
The web application relies on getting offline access to the user's Google Account.
The Android app is trying to use the same backend APIs that web front end is using. For this, I am sending the ID token of the user to backend.
The problem is that this ID token expires after some time and I am forced to re-authenticate the user to get the new ID token. Initially, I wanted it to not expire or generate a new ID token automatically on the Android app itself, but then I checked the OAuth2 documentation for this, which mentions the following statement -
It is important that the Android app never attempt to exchange the
code for a refresh token on its own. This would require that the app
store the server's client ID and client secret. Including these in
your Android app is insecure, because apps can be easily decomposed.
The recommended flow is mentioned there, but I couldn't find anything which can help me do the same using the Firebase Android SDK.
Is it possible to get the authorization code using Firebase which can be later exchanged for refresh token by the backend? If yes, then can you point me to correct documentation or code example for the same?

Related

Google OAuth2: perform token refreshing server-side while refresh token or authorization code acquired via mobile app

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

How to Authenticate with Firebase, Using Microsoft on Android [duplicate]

I am trying to add the "Microsoft" sign in method to my Firebase project, with the hope of allowing users to login to my Android app using their Azure AD credentials. I already have everything set up to use the "Email/Password" provider, which is working well.
I don't plan on accessing any Azure APIs, I just need to authenticate a given user so that when an organization terminates said users account, he is no longer able to login to my app.
I am following https://firebase.google.com/docs/auth/android/microsoft-oauth this guide. I have registered an app on my Azure AD, set it to allow accounts from any organization as well as personal accounts, and added the client ID and secret to my Firebase project. I have also added the redirect url from the Firebase project to the App registration on Azure.
I start the login process using startActivityForSignInWithProvider like in the example. The chrome tab loads and takes me through the entire authentication process. The problem is this always returns a failure with the exception Error: (invalid_client) AADSTS700025: Client is public so neither 'client_assertion' nor 'client_secret' should be presented'
This is confusing, since, in order to enable this sign-in provider on Firebase, you are required to enter the client ID and client secret.
I've tried with the app registration setting "Treat application as public client" set to Yes and No. I've also tried with a blank scopes collection and adding 'openId' to the scopes as a stab in the dark.
I'm a bit out of my depth with this Microsoft Authentication stuff, so any nudge in the right direction would be greatly appreciated.
Register the app in Azure as web app instead of Native App. Because the URL provided by Firebase is for Web App. Hope this helps.

Cross-client Google OAuth: Xamarin/Android to .NET web service

I have a similar question as found in this post, but for Xamarin.
Cross-client Google OAuth: Get auth code on iOS and access token on server
I'm using Xamarin.Auth to successfully get a token back from Google for the user of my app. I'd like to send that token to the web service, so it can do background queries of Google APIs impersonating that logged in user. (i.e. querying their liked videos). The web service would have to configured with the Xamarin client ID to use the token, but it seems cleaner to use separate client IDs for front-end/back-end.
Xamarin app is using the Google API client ID, which is setup for Android (and has no client secret). I'm using a 'local' package name redirect URI in the app itself, so it never hits a server component to obtain the token. Also, I've created a web application Google API client which has both client id and secrets.
Unless I use the Xamarin/Android client ID for the web service as well, If I'm reading the cross-client docs correctly, I need to somehow transfer the token between these clients (on front-end and back-end). I've tried using the web app client ID/secret to obtain a refresh token, for the Xamarin access token, but get an invalid client error. Which makes sense, I guess, since the token was created with a different client.
I'm supporting multiple OAuth logins (i.e. Google, Facebook, Instagram), and was planning to create a shadow user in my database, which would hold the active token. I'm letting the auth code->token workflow all happen on the client (using Xamarin.Auth.OAuth2Authenticator).
To make this work, do I need implement the authorization code->token transfer on the backend web service during my app login (using web service client ID), or is there some other way to transfer tokens between app/web service clients?
Or does it seem fine to just use the Xamarin client ID on the back-end, and be done with it?
Thanks!

How can my server authenticate Android users with their Google accounts?

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"

Authenticated communication b/w Android app And GAE server using OAuth2

New to OAuth2. I am writing an Android app that communicates with an App engine server application.
The app needs to authenticate itself with the server on behalf of the user, using Google account info of the user. The server needs to retrieve the user's basic info and create an account . That's the easy part and I know how to do this.
Furthermore, the Android app will also have the user authenticate himself/herself using Oauth2 and retrieve basic user info using Google account info of the user. I can do this as well.
This is where I need help Assuming the previous steps have been completed successfully, how can I use the Android app (where the user has logged in) to communicate with the server securely using the user's credentials.
Any ideas or am I missing something obvious?
The Android to App Engine OAuth2 communication is documented in this answer:
google app engine oauth2 provider
Using OAuth, 1.0 or 2.0, doesn’t matter in this, leads to the app obtaining an access token - then based on the API of your server, you pass this access token with requests instead of login and password. I guess the way to attach the access token string to URL requests may be slightly different between different APIs, see the documentation for yourself. Or if you are making the server app at the same time, then you need to figure out your way to do so (like sending a HTTP header Authorization: OAuth access_token=abcdefgh….

Categories

Resources