B4A Class [class][B4X] Google OAuth2

Status
Not open for further replies.
GoogleOAuth2 class is compatible with B4A, B4i and B4J (new).

It is no longer possible to use WebView to implement Google's OAuth2 authentication.
The solution is to open the default browser and set the redirection uri in such a way that the browser will redirect the response back to our app.

GoogleOAuth2 class takes care of several tasks:

1. Opening the browser and getting the authorization code.
2. Getting and saving the access token and refresh token from the authorization code.
3. Getting a new access token when it expires using the refresh token.

The process is documented here: https://developers.google.com/identity/protocols/OAuth2InstalledApp

Setup

1. Go to Google developer console, create a new project if needed and add a client id:

SS-2017-05-11_15.14.36.png


For the Android client you need to get the SHA-1 signature. It is available under Tools - Private Sign Key.
Set the package name or bundle identifier fields to your app's package name.

2. B4A:
Add to the manifest editor:
B4X:
AddActivityText(Main,
  <intent-filter>
  <action android:name="android.intent.action.VIEW" />
  <category android:name="android.intent.category.DEFAULT" />
  <category android:name="android.intent.category.BROWSABLE" />
  <data android:scheme="$PACKAGE$" />
  </intent-filter>
   )
B4i:
Change b4i.example2 with your package name.
B4X:
#UrlScheme: b4i.example2

3. B4A code:
B4X:
Sub Activity_Resume
   oauth2.CallFromResume(Activity.GetStartingIntent)
End Sub
B4i code:
B4X:
Sub Application_OpenUrl (Url As String, Data As Object, SourceApplication As String) As Boolean
   oauth2.CallFromOpenUrl(Url)
   Return True
End Sub

B4J:
Create a new OAuth Client id with the type set to Other.
You need to add both the client id and the client secret to the project (client secret is not required in the the mobile solutions).
The Initialize methods expects two additional parameters: client secret and the path where the token will be stored.


3. Initialize GoogleOAuth2 with the required scopes (based on the API that you want to call).
Call GoogleOAuth2.GetAccessToken. The AccessTokenAvailable will be raised when the token is available.
Once you have the access token, you can access the relevant Google web service.
In this example we will access the People API. You need to enable it in Google console.
Example:
B4X:
Sub btnGetData_Click
   oauth2.GetAccessToken
   Wait For OAuth2_AccessTokenAvailable (Success As Boolean, Token As String)
   If Success = False Then
     ToastMessageShow("Error accessing account.", True)
     Return
   End If
   Dim j As HttpJob
   j.Initialize("", Me)
   j.Download2("https://people.googleapis.com/v1/people/me", _
       Array As String("access_token", Token, "requestMask.includeField", "person.email_addresses,person.birthdays,person.names"))
   Wait For (j) JobDone(j As HttpJob)
   If j.Success Then
     ParsePersonData(j.GetString)
   Else
     ToastMessageShow("Online data not available.", True)
   End If
   j.Release
End Sub

SS-2017-05-11_15.25.44.png


SS-2017-05-11_15.29.51.png


SS-2017-05-11_15.30.18.png


SS-2017-06-20_17.56.27.png


Updates:

- B4XPages project is attached. Don't miss:
  • Different ClientId for each platform
  • ClientSecret is only needed in B4J
  • Manifest snippet in B4A
  • #UrlScheme and Sub Application_OpenUrl in B4i (Main module)
- v2.11: added "access_type":"offline" to the token request. This is a new requirement for offline token refreshes. Thanks @DonManfred!
 

Attachments

  • B4XGoogleContacts.zip
    19.1 KB · Views: 306
Last edited:

Intiwhiz

Member
Licensed User
Dear @Erel
why I am getting error with these code

Wait For OAuth2_AccessTokenAvailable (Success As Boolean, Token As String)
Wait For (j) JobDone(j As HttpJob)

Thanks
 

Erel

B4X founder
Staff member
Licensed User
Longtime User
Quoting the first post:

"Note that the code uses the new resumable subs feature added in B4A v7.0 (beta will be released next week) and B4i v4.0. It makes it easier to manage asynchronous tasks.
It shouldn't be too difficult to open the project in an older version. You will need to rewrite the subs that call Wait For and implement the logic with standard events."
 

DonManfred

Expert
Licensed User
Longtime User

keirS

Well-Known Member
Licensed User
Longtime User
Just like to point out that the B4J implementation is not to OAuth 2 specification. A Client Credentials grant is only supposed to be used for server to server authorization where a user interface is not possible. So it's fine for a B4J server app but it should not be used for a distributed desktop app. The theory behind this is a desktop app could be cracked and the Client ID and Client Secret found. See here for further details
 

Erel

B4X founder
Staff member
Licensed User
Longtime User
That's not correct. The B4J implementation is the desktop apps implementation. It follows Google instructions: https://developers.google.com/identity/protocols/OAuth2InstalledApp

Maybe it was not clear, though you can see it if you run the project or go over the source code, the process is very similar to the mobile process. The default browser opens and the user needs to authorize your app to access the requested scopes. This is the most important step of OAuth2. The user explicitly grants access through a trusted third party application.
 
Last edited:

keirS

Well-Known Member
Licensed User
Longtime User
The difference is the mobile apps do not require the client secret. Storing both the Client ID and the Client Secret in a Jar file is a concern. If you can run Jetty from a UI app (never tried this) then I would be tempted to implement this as a Implicit Grant.
 

Duque

Active Member
Licensed User
Longtime User
I discovered that apparently only works with google chrome browser, try other browsers and got an ugly error ...

b4a
 

JohnC

Expert
Licensed User
Longtime User
Erel,

Great job on all the code you wrote for this functionality. Makes it very easy to use!

The only thing I added to it is a sub to do a quiet check if the token is valid or not without launching a browser, because the user could get confused why their browser is opening up (and also possibly show a browser intent selection box if they have multiple browsers) when they just want to send an email. This way, my app will be able to silently see the token is not valid and pop up a small window explaining what is going to happen next (that they need to do a one-time authorization to allow my app to access their google account in order to send gmails).

B4X:
Public Sub TokenValid
    Return ti.Valid
End Sub
 
Status
Not open for further replies.
Top