Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Setting up Server to Server Authorization Using Google's OAuth 2.0 Service Accounts on Mule

DZone's Guide to

Setting up Server to Server Authorization Using Google's OAuth 2.0 Service Accounts on Mule

Accessing the Google API through Mule requires a JWT token. See how you can generate these tokens to authorize your Mule flows to call the API directly.

· Integration Zone ·
Free Resource

The Future of Enterprise Integration: Learn how organizations are re-architecting their integration strategy with data-driven app integration for true digital transformation.

One of the recent demos I was working on required me to integrate with GSuite Admin's Directory API. In most use-cases, working on the API's authorization using OAuth 2.0 is straightforward. However, since the use-case was a backend synchronization of user details domain-wide, it makes a lot more sense for to use the server to server authorization using service accounts. This requires you to use JWT to authorize access to Google APIs. Unfortunately, Mule does not have an out of the box component to generate JWT tokens. Thus, I needed to implement a JWT token generator with my service account credentials.

Using JWT to Authorize Access to Google API on Mule

You can find all the details of what's required from the Google's documentation on service accounts. When you create the service account, you will download a JSON file that provides you with the service account's private key. You need to extract the PEM formatted private key into a file named gsuite.key as per shown below in the screenshot. My Java class in my project expects to find the file in the main/resources directory of the project. Do note that I removed the "-----BEGIN PRIVATE KEY-----" and "-----END PRIVATE KEY-----" portion of the key in the file.

gsuite.key

You will also need to ensure that you set up the service account to have domain-wide authority. You can find details of that here.

For my demo, I decided to leverage on the Java JWT (JJWT) library to help me generate the JWT token. I also used the bouncycastle library to decode the PEM certificate of which I would use to create a private key that would be used to signed the JWT token.

The following is a snippet of the pom.xml dependency that I used to install those libraries.

<!-- for JWT generation -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.7.0</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
    <artifactId>bcprov-jdk16</artifactId>
    <version>1.45</version>
</dependency>

To keep this guide simpler, I've pushed my Mule project in a GitHub repository here so that I can directly zoom into the main parts of the implementation. The Mule project itself is a simple System API that provides two resources: organization unit and users. You may find this useful, but the key flow that you want to get to know is the get_bearer_token flow in the google_auth.xml configuration file.

Get authorization bearer token using JWT for Google API

You'll notice that I've implemented the authorization flow wrapped in a cache scope, which would return the bearer token's string. This string would essentially be used with message enricher to save the bearer token in a flow variable to be used in the API requests.

The main gist of the flow lies on the Java component that calls the GenerateJwtToken class. The class loads the GSuite service account credentials from the mule-app.properties. You can, of course, use a custom properties file or even use the credentials vault to store the properties securely. But since this was for a demo that would be deployed to CloudHub, mule-app.properties it is for this case.

//Get the required Google JWT properties.
String issuer = eventContext.getMuleContext().getRegistry().get("googleJWT.issuer");
String scope = eventContext.getMuleContext().getRegistry().get("googleJWT.scope");
String subject = eventContext.getMuleContext().getRegistry().get("googleJWT.subject");
String audience = eventContext.getMuleContext().getRegistry().get("googleJWT.audience");
String ttlMsStr = eventContext.getMuleContext().getRegistry().get("googleJWT.ttlMs");

Google also requires the use of RS256 algorithm with its JWT. The following portion of the code shows you how I've created the RSA private key with the key you got with your service account.

RSAPrivateKey prikey = null;
try {
//Load the gsuite,key used to sign the token
ClassLoader classLoader = getClass().getClassLoader();
URL gsuiteKeyResource = classLoader.getResource("gsuite.key");

File filePrivateKey = new File(gsuiteKeyResource.getFile());
FileInputStream fis = new FileInputStream(gsuiteKeyResource.getFile());

byte[] privateKey = new byte[(int) filePrivateKey.length()];
fis.read(privateKey);
fis.close();

byte[] encoded = Base64.decode(privateKey);

java.security.KeyFactory keyFactory = java.security.KeyFactory.getInstance("RSA");
PKCS8EncodedKeySpec privatekeySpec = new PKCS8EncodedKeySpec(encoded);
prikey = (RSAPrivateKey) keyFactory.generatePrivate(privatekeySpec);
...

The last bit of the code is where you finally build the JWT.

//The JWT signature algorithm we will be using to sign the token
SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.RS256;
long nowMs = System.currentTimeMillis();
long expMs = nowMs + Long.parseLong(ttlMsStr);
Date now = new Date(nowMs);
Date exp = new Date(expMs);

//Let's set the JWT Claims
JwtBuilder builder = Jwts.builder()
.setIssuedAt(now)
.setSubject(subject)
.setIssuer(issuer)
.setAudience(audience)
.claim("scope",scope)
.signWith(signatureAlgorithm, prikey)
.setExpiration(exp);

//Builds the JWT and serializes it to a compact, URL-safe string
return builder.compact();

And with that, you should now be able to easily authorize your Mule flows to call those Google APIs directly without any needing to redirecting to a user to authorise the access.

I hope that this simple example project and the guide above is helpful.

Make your mark on the industry’s leading annual report. Fill out the State of API Integration 2019 Survey and receive $25 to the Cloud Elements store.

Topics:
mule ,jwt ,google ,api ,authorization ,integration

Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}