Category: Software Engineering

  • Using Go To Call Salesforce with the JWT Bearer OAuth Flow

    When using Go to call Salesforce’s OAuth with the JWT Bearer Flow you may see hard to resolve authentication errors if you are using the jtw.RegisteredClaims struct to build your JWT claims. We found that Salesforce requires the Audience claim to be a single string, for example "aud": "https://login.salesforce.com". The jwt package defaults to sending Registered Claims as an array of strings.

    This sample code shows how RegisteredClaims may be used to build a JWT. This JWT will fail authentication.

    claims := jwt.RegisteredClaims{
      Audience:  jwt.ClaimStrings{"https://login.salesforce.com"},
      Issuer:    "your-client-id",
      Subject:   "user@example.com",
      ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Hour)),
    }
    token := jwt.NewWithClaims(jwt.SigningMethodRS256, claims) // FAILS
    

    There are two neat solutions for this problem (and one very un-neat solution which Claude tried, and succeeded, when we encountered this). A simple solution is to use jwt.MapClaims. This solution lacks the type safety of RegisteredClaims

    claims := jwt.MapClaims{
      "aud": "https://login.salesforce.com",
      "iss": "your-client-id",
      "sub": "user@example.com",
      "exp": time.Now().Add(time.Hour).Unix(),
    }
    token := jwt.NewWithClaims(jwt.SigningMethodRS256, claims)
    

    The RegisteredClaims package provides a global variable which, when set to false, will cause the library to marshal any single entry jwt.ClaimStrings as a string. This is a global setting, so lacks fine grain control. It worked in this situation because we only have one ClaimStrings.

    jwt.MarshalSingleStringAsArray = false
    
    claims := jwt.RegisteredClaims{
      Audience:  jwt.ClaimStrings{"https://login.salesforce.com"},
      Issuer:    "your-client-id",
      Subject:   "user@example.com",
      ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Hour)),
    }
    token := jwt.NewWithClaims(jwt.SigningMethodRS256, claims)
    

    Claude’s solution? Claude wrote a custom RegisteredClaims implementation which satisfied the required interfaces. This is longer code and works, but I wonder how maintainable it is especially as the library evolves.

    There are two security practices that I believe are important if you are doing this type of work:

    • Restrict the host names that you will send tokens to in order to login. If you are writing this as bespoke work and only have one org or always use login.salesforce.com and test.salesforce.com as your login domains then this is easy. Just hard-code these and provide a configuration switch between sandbox and production.
    • Trust the instance URL returned by Salesforce in their token response. This guarantees that API requests cannot be sent to the wrong host.

    Remember also that the JWT signing key and the access tokens that you receive on successful authentication are highly sensitive information. Compromise of either could be devastating.

    Resources

  • The Vortex Game

    Alongside starting this web site I am changing some of my old projects on GitHub to public projects. This allows the code to be shared.

    This project is a tool to help play the Vortex Game from the 1980’s TV show “The Adventure Game”. See https://en.wikipedia.org/wiki/The_Adventure_Game.

    We initially played this game with out Scout Troop using a grid chalked on the floor. The vortex was controlled using a printed copy of the grid and tokens to track the positions of the player and vortex. The Scouts enjoyed as much controlleing the Vortex and trying to catch eachother as they did crossing the grid.

    This tool allows the game to be managed using a phone or tablet. It allows rules to be enforced, so allowing control to he handed to a Scout to operate. It provides sound effects using the Web Audio API in order to add some atmosphere and to give the player some indication of how close they are to being “vapourised”.

    The project was useful for me to experiment with Redux for state management in React. Redux gave me built-in tools for Undo And Redo. It also gave nice separation of state, state transitions (business logic) and separate components (the Sound subsystem).

    The code is at https://github.com/m0rjc/VortexGame

    Screen shot of the Vortex Game on my mobile phone
    Screen shot of the Vortex Game on my mobile phone
    <