Google Connector - OAuth 2.0
Overview
Using Google OAuth 2.0, this module helps in generating access tokens and refresh tokens with Client ID and Client Secret.
- Access Token - It can be used with any of the Google APIs, such as the Google Drive API.
- Refresh Token - Once the access token has expired, it will be used to generate a new one.
Documentation
Typical usage scenario
Google OAuth 2.0 implements the Google web-server authorisation code flow end to end inside Mendix, using nothing but standard model constructs. An administrator records a client id, client secret and scope on a GoogleOAuthSettings page, clicks Generate Token, and the module builds the Google consent URL, opens it in the browser, receives the redirect on its own published REST endpoint (rest/oauth/v2/callback), exchanges the authorisation code for an access token and a refresh token, encrypts both with the Encryption module, and stores them against the record. A scheduled event then keeps the access token fresh in the background. There are no Java actions, no JavaScript actions and no JAR files — the whole flow is microflows, a nanoflow, a published REST service and a JSON import mapping.
• Connect a Google account once, and keep it connected. One consent round trip produces a long-lived refresh token; SCE_RefreshToken replaces the hourly access token from then on, so nobody is asked to consent again.
• Call any Google API on the account's behalf. The stored access token is a plain bearer token — Drive, Contacts, Calendar, Gmail, Sheets, Cloud APIs. Retrieve the record, decrypt AccessToken, put it in an Authorization: Bearer header.
• Power the Google Drive and Google Contacts connectors. Both depend on this module. Install it first and those connectors have credentials to work with.
• Hold several independent Google connections side by side. One record per connection, each with its own client id, secret, scope and token pair, named by OAuthName. The Active flag decides which ones the scheduler keeps alive.
• Refresh or revoke without leaving the app. Refresh Token forces an immediate refresh; Revoke Access posts the token to Google's revoke endpoint and clears the stored tokens.
• Prove the credentials before writing any logic. The overview, new, edit and error pages give you a complete admin UI on day one.
The problem this solves is that OAuth 2.0 is not hard in principle and fiddly in practice. The authorisation code flow needs a publicly reachable callback exempt from authentication, a redirect URI matching Google's registration character for character, a form-encoded token exchange, an expiry you track yourself, a refresh cycle that runs without a user present, and secrets that should not sit in the database in clear text. Getting all of that right by hand takes a few days and is easy to get subtly wrong.
Dependencies
Read this before importing. This module has unresolved references to two other Marketplace modules, and importing it into an app that lacks them produces 29 consistency errors. That is expected and documented behaviour, not a defect.
• The module names must match exactly — references are by qualified name, so they must be called Encryption and CommunityCommons.
• No Java libraries of its own. Any missing JAR belongs to Encryption or Community Commons.
• Google Cloud setup is a prerequisite too — a project, the API enabled, an OAuth consent screen with your accounts as test users, and Web application credentials whose authorised redirect URI is <your app URL>/rest/oauth/v2/callback.
• The runtime's application root URL must be correct. Mendix Cloud sets it; for a container or on-premises deployment behind a proxy, set it explicitly, or the redirect URI will not match.
Installation
Import the two prerequisites first.
1. Google Cloud console. Create or open a project, enable the API you intend to call.
2. Configure the OAuth consent screen, add every scope you will request, and add each authorising Google account as a test user while in testing.
3. Create an OAuth client ID of type Web application. Under Authorised redirect URIs add, exactly: https://<your-app-domain>/rest/oauth/v2/callback for each deployed environment, and http://localhost:8080/rest/oauth/v2/callback for local development. One entry per environment. Copy the client id and secret.
4. Import the Encryption module and set its encryption key. Keep that key safe and identical across environments sharing a database — the tokens cannot be decrypted without it.
5. Import Community Commons. Confirm GetApplicationUrl exists.
6. Confirm Nanoflow Commons is present.
7. Now import this module and run Update project directory if prompted.
8. Check the error list. It should be empty.
9. Add GoogleOAuthSettings_Overview to your navigation and grant the Administrator module role.
10. Check the published REST service and the scheduled event. OAuth should be on rest/oauth/v2 with no authentication; SCE_RefreshToken should be enabled, and enabled in your environment's deployment settings too.
11. Verify the redirect URI your app actually sends matches a registered one character for character — same scheme, host, port, no trailing slash.
12. Create your first configuration and authorise it.
Configuration
Constants — all three are Google endpoints, hidden and not exposed to the client. Leave them alone unless Google changes an endpoint or you route outbound traffic through a gateway.
The settings record — click New and fill in OAuth Name (sent as the OAuth state and how the callback finds the record, so keep it unique and free of characters needing escaping), Client ID, Client secret and Scope. Tick Active, Save, then Generate Token.
How the client secret is protected
• Encrypted at rest by the Encryption module, on both the Save and Generate Token paths. Current releases write AES-GCM ciphertext with an {AES3} prefix.
• Decrypted only in memory, for the length of one REST call, never committed.
• Re-saving is safe — Encryption's Encrypt and Decrypt both test startsWith(…, '{AES') first, so pressing Save twice does not double-encrypt.
• The encryption key is the single point of failure. Lose or change it and every stored secret and token becomes undecryptable.
• Grant the User module role deliberately. That role has read access to ClientSecret, AccessToken and RefreshToken. Ciphertext, but still retrievable. If you do not need it, do not assign it.
• The state parameter is not a CSRF defence. It carries the OAuthName, which is not secret. Anyone who can reach the callback and knows or guesses an OAuth name can present their own authorisation code against that record. Keep the callback behind your normal network controls, use non-obvious OAuth names, and treat the stored tokens as belonging to whichever account last completed consent.
Scopes — request the narrowest that does the job. drive.file (only files your app creates), drive (full Drive), contacts / contacts.readonly, calendar.readonly, and so on.
Enter multiple scopes URL-encoded. The Scope value is concatenated straight into the consent URL without urlEncode(), so a space-separated list must be typed with %20 between scopes. A literal space produces a malformed authorisation URL.
Recommended first-run test
1. Run locally as an Administrator and open the overview.
2. Create a record with a single harmless scope, using a client whose redirect URIs include http://localhost:8080/rest/oauth/v2/callback.
3. Save, then Generate Token. Google's consent screen should open.
4. Consent with a test-user account. Success lands you back on /index.html.
5. Open Edit — both token fields should hold {AES3}… ciphertext and the expiry should be about an hour ahead.
6. Click Refresh Token and confirm a new expiry. This proves the refresh token and client secret are both stored correctly, which is the part that otherwise fails silently later.
7. Watch the log for SCE_RefreshToken activity as the expiry approaches.
8. If something fails: SUB_GenerateToken logs at Error, but GoogleCallback, SUB_RefreshToken and SUB_RevokeAccess log at Info — set those nodes to Info or lower, or you will see nothing.
Known bugs
None
Frequently Asked Questions
Why do I see 29 errors right after importing?
Because the prerequisites are missing — 13 calls to Encryption and 3 to CommunityCommons.GetApplicationUrl. Import both under exactly those module names and the errors clear.
Google says "redirect_uri_mismatch". What is wrong?
The URI your app sends is <application root URL>/rest/oauth/v2/callback, and Google compares character for character. Register that exact URI — right scheme, host and port, no trailing slash — with a separate entry for every environment.
Do I have to renew the token myself?
No. SCE_RefreshToken runs every minute and refreshes any active record expiring within five minutes, with no user present.
How do I use the token in my own microflow?
Retrieve the record, call Encryption.Decrypt on AccessToken, and put the result in an Authorization: Bearer <token> header.
Can I connect more than one Google account?
Yes — one record per connection. Note that consuming modules often retrieve the first record without a constraint, so check how the downstream module selects credentials before adding a second.
Does this let Google users sign in to my Mendix app?
No. id_token is not mapped and nothing links to System.User — this is not an OpenID Connect or SSO module.
I re-authorised an existing connection and got the error page. Why?
Google issues a refresh token only on the first consent for a client and account. Use Revoke Access first, then generate again.
Is the client secret stored in clear text?
No — client id, secret and both tokens are encrypted before commit and decrypted in memory only. The trade-off is that the encryption key becomes a deployment secret you must not lose.
Why does the callback endpoint allow anonymous access?
Google's redirect arrives without a Mendix session, so it must be reachable without authentication. Bear in mind state carries the OAuth name rather than an unguessable nonce, so the endpoint identifies the record but does not by itself prove who initiated the request.
Can I point the module at a different OAuth provider?
Technically the constants can be repointed, but the request bodies, the mapping and access_type=offline are all shaped for Google.
The scheduler runs every minute — can I slow it down?
Yes. If you widen the interval, widen the five-minute look-ahead window in the XPath by the same amount, or tokens will expire between runs.
Issues, suggestions and feature requests:
https://github.com/bharathidas/Google-Connector-OAuth-2.0/issues
Releases
**Google OAuth 2.0** — now supported on Mendix Studio Pro **10.24.17**
Rebuilt from Studio Pro 10.18.3 to **10.24.17** (LTS). No functional changes — this release only updates Studio Pro compatibility.
**Prerequisites** — import these before Google OAuth 2.0, or the module will show unresolved references:
- `Encryption`
- `CommunityCommons` (Community Commons)
Import `GoogleConnectorOAuth2.mpk` via *App Explorer > Import module package* in Studio Pro 10.24.17 or higher.
---
**Google OAuth 2.0**
Using Google OAuth 2.0, this module helps in generating access tokens and refresh tokens with Client ID and Client Secret.
• **Access Token** - It can be used with any of the Google APIs, such as the Google Drive API.
• **Refresh Token** - Once the access token has expired, it will be used to generate a new one.
**Dependencies:**
• Mendix modeler 9.24.18.
• Encryption module
• Community Commons Module
• Nanoflow Commons Module
**Configuration:**
Setup Client ID and Client Secret in Google
[https://developers.google.com/identity/gsi/web/guides/get-google-api-clientid](https://developers.google.com/identity/gsi/web/guides/get-google-api-clientid)
Configure ‘GoogleOAuthSettings_Overview’ to your Navigation.
**Generate Token:**
Add the following information in ‘GoogleOAuthSettings_Overview’ page new button
1. OAuth Name
2. Client ID
3. Client Secret
4. Scope
Save your configuration and click on ‘Generate Token’ button to generate the token using OAuth2.0 Authorization.
The access token and refresh token will be obtained, encrypted, and stored once the authorization has been successful.
When the access token expires, the scheduler "SCE RefreshToken" will automatically generate a fresh token.
**Refresh Token Manually:**
To Refresh the token manually, the user can click on Edit button in ‘GoogleOAuthSettings_Overview’ where the below details can be seen.
1. OAuth Name
2. Client ID
3. Client Secret
4. Scope
6. Access Token
7. Refresh Token
8. Token Expire Date&Time
To regenerate the Access token, click ‘Refresh token’.
**Revoke Access:**
If the Google OAuth access needs to be revoked for the configured OAuth Setting, click on ‘Revoke Access’ button to revoke the OAuth access. The access token and refresh token should be regenerated using the ‘Generate Token’ button after the OAuth access has been revoked.
**Reference:**
[https://developers.google.com/identity/protocols/oauth2/web-server](https://developers.google.com/identity/protocols/oauth2/web-server)