Sunday, November 28, 2021

Google Cloud API Gateway - M2M client, GCF server

Summary

I'll be showing some of the detailed configuration necessary to deploy API Gateway with a Cloud Functions back-end and authentication for a non-human (machine) client.  I'll be focusing on the front and back-end authentication configuration.  I'll also be showing the client side in Node.js which is very thinly documented by Google.


Architecture




Authentication

Back-end:  Cloud Functions

The back-end GCF is deployed requiring authentication.  The API Gateway is configured to operate under a Service Account that has the Cloud Function Invoker role.

Front-end:  Machine Client

Configuration here is significantly more complicated than the back-end.  Configuration areas:
  • A Service Account needs to be created and a SA key downloaded.  That key is then used to sign a JWT for authentication to the API Gateway.
  • Security definitions must be added to OpenAPI spec (Swagger 2.0) that specify that SA as an allowed user.
  • The Machine Client itself must generate a JWT to the API Gateway specs and sign that JWT with the SA key.

Code

OpenAPI Security Definition

  1. securityDefinitions:
  2. machine-service:
  3. authorizationUrl: ""
  4. flow: "implicit"
  5. type: "oauth2"
  6. x-google-issuer: "machine-service@kvpstore.iam.gserviceaccount.com"
  7. x-google-jwks_uri: "https://www.googleapis.com/robot/v1/metadata/x509/machine-service@kvpstore.iam.gserviceaccount.com"
  8. security:
  9. - machine-service: []

Machine Client-side 


  1. 'use strict';
  2. const fetch = require('node-fetch');
  3. const jwt = require('jsonwebtoken');
  4. const sakey = require('./sakey.json'); //json file downloaded from Google IAM
  5. const EMAIL = sakey.client_email;
  6. const AUDIENCE = 'your audience';// this value corresponds to the "Managed service" name of the API Gateway
  7. const ALGORITHM = 'RS256';
  8. const GWY_URL = 'your URL';
  9. const KEY = sakey.private_key
  10.  
  11. function exampleAPICall(email, audience, key, algorithm) {
  12. const payload = {
  13. iat: Date.now(),
  14. exp: Date.now() + 3600,
  15. iss: email,
  16. aud: audience,
  17. sub: email,
  18. email: email
  19. }
  20.  
  21. const token = jwt.sign(payload, key, {algorithm: algorithm});
  22. const response = await fetch(`${gwyurl}/guid`, {
  23. method: 'GET',
  24. headers: {
  25. 'Authorization': `Bearer ${token}`
  26. }
  27. });
  28. return await response.json();
  29. }
  1. Copyright ©1993-2024 Joey E Whelan, All rights reserved.