Using Heroku Postgres from local development setup

When developing locally against a Heroku Postgres database (hosted on Heroku) you quickly realize you cannot connect due to a self-signed certificate (or rather Heroku signed certificate). The solution is to ensure that you use the non-validating SSL factory for the connection pool. This is easily done by appending “ssl=true” and “sslfactory=org.postgresql.ssl.NonValidatingFactory” to the database URL i.e. something like the following with the addition in bold:

DATABASE_URL=postgres://foo:bar@ec2-55-222-96-152.eu-west-1.compute.amazonaws.com:5432/baz?ssl=true&sslfactory=org.postgresql.ssl.NonValidatingFactory

Populating the user object with passport.js and Salesforce OAuth

Using passport.js is a great option for doing authentication in node.js applications with great strategies for authenticating through just about anything on the planet including Salesforce. Using passport.js with Salesforce involves using the OAuth2Strategy but the user object in the session is not usable really as I really want actual information about the user to be there. The solution I came up with was overriding the userProfile-method and adding a call to the Salesforce userinfo endpoint as shown below.

// configure authentication using oauth2
app.use(passport.initialize());
passport.serializeUser(function(user, done) {
    done(null, user.username);
});
passport.deserializeUser(function(login, done) {
    done(undefined, {
        "username": login
    });
});

OAuth2Strategy.prototype.userProfile = function(accessToken, done) {
    this._oauth2.get(`https://${process.env.SF_LOGIN_URL || "login.salesforce.com"}/services/oauth2/userinfo`, accessToken, function (err, body, res) {
        if (err) { return done(new InternalOAuthError('Failed to fetch user profile', err)); }
        try {
            let json = JSON.parse(body);
            let profile = {
                "provider": "Salesforce.com",
                "username": json.preferred_username,
                "name": json.name,
                "email": json.email,
                "firstname": json.given_name,
                "lastname": json.family_name,
                "payload": json
            };
            
            done(null, profile);
        } catch(e) {
            done(e);
        }
    });
}

passport.use(new OAuth2Strategy({
        authorizationURL: `https://${process.env.SF_LOGIN_URL || "login.salesforce.com"}/services/oauth2/authorize`,
        tokenURL: `https://${process.env.SF_LOGIN_URL || "login.salesforce.com"}/services/oauth2/token`,
        clientID: process.env.SF_CLIENT_ID,
        clientSecret: process.env.SF_CLIENT_SECRET,
        callbackURL: process.env.SF_CALLBACK_URL
    },
    function(accessToken, refreshToken, profile, cb) {
        cb(undefined, profile);
    }
));

The interesting piece is really the code in bold where I inject a call to /services/oauth2/userinfo to get information about the user and then add that as the user object.

Of course after having done all this I found passport-salesforce which is a strategy that does exactly the same thing – duh!!! Anyways it was fun to code it up.

Dark Mode in Salesforce with the Lightning Extension

If you’re using Salesforce and you’re a lover of Dark Mode like it’s seen in macOS (or will be in iOS soon) you’re going to love the Lightning Extension. The Lightning Extension is a Google Chrome extension that allows you to change certain behaviors of Salesforce on the fly. One of the things you can change is the theme by changing into Dark Mode. I’ve been using it for a few days and love it.

YMMV

Google Chrome Lightning Extension

kafka-node with Heroku Kafka

The other day I was building a demo for a customer around Heroku and Heroku Kafka. My language of choice these days is node.js so I needed a Kafka library for node.js and I settled on kafka-node. Now I needed to figure how to use the library using the environment variables provided by Heroku to access my Kafka cluster.

After having bound my Kafka add-on to the app I had 5 environment variables added to my app. The variables are well explained in the Heroku DevCenter but how to use them with kafka-node had me spend some time on it. The root cause seemed to be that the name in the certificate presented by the Kafka brokers did not match the name in the certificate provided to me by Heroku. Since the library uses the node.js TLS module under the covers the solution was to implement some of the verification login myself using the checkServerIdentity method. In the method I verify the cryptographic fingerprint of the root issuer certificate as provided by Heroku (KAFKA_TRUSTED_CERT) with that of the issuing certificate of the Kafka broker. I also had to remove the “kafka+ssl://” part from the Kafka broker URL’s. I do that using regular expressions.

Below is the code. YMMW.

const kafka = require("kafka-node");
const x509 = require('x509');
const Client = kafka.KafkaClient;

const kafkaHosts = process.env.KAFKA_URL.replace(/kafka\+ssl:\/\//gi, "");
const kafkaCert = x509.parseCert(process.env.KAFKA_TRUSTED_CERT);

const options = {
  "key": process.env.KAFKA_CLIENT_CERT_KEY,
  "cert": process.env.KAFKA_CLIENT_CERT,
  "ca": [process.env.KAFKA_TRUSTED_CERT],
  "checkServerIdentity": (host, cert) => {
    if (kafkaCert.fingerPrint === cert.issuerCertificate.fingerprint) return undefined;
    return Error('Not authentic')
  }
}

module.exports = {
    "client": () => {
        return new Client({
            "kafkaHost": kafkaHosts,
            "sslOptions": options
        });
    },
    "topic": `${process.env.KAFKA_PREFIX}safe-habour`
}

Yet another reason for using Platform as a Service (PaaS)

I’m using a Platform as a Service (PaaS) for all my application development — because why wouldn’t I?! Heroku is the platform of choice with the full disclaimer that Heroku is a Salesforce company and I work for Salesforce.

However the driving reason of my usage of Heroku is that being a PaaS Heroku provides me with a high level of abstraction of the underlying compute infrastructure. On Heroku I just worry about the app and not anything else. No load balancing. No compute instances. No gluing and regluing stuff together. Just the app.

As part of the applications I have on Heroku I have a wide variety of databases including Heroku Postgres (a fully managed and elastic Postgres instance). A nice aspect of this is that for me Postgres is just another data store but I do not have to worry about the operations of it. This is great as I’m much better at writing apps than managing an always-on, fully load balanced and highly available database cluster.

Yesterday I received a notice about upcoming maintenance and one section in the email made me take notice so I thought I would share:

Your database must undergo maintenance.

At that time, we will create a hidden follower, wait for it to catch up, push the hidden follower’s creds to your app, unfollow it from your former leader and repoint any followers you may have to properly follow your new leader.

Let’s break that out really quick… When they — Heroku — do the maintenance for me and I won’t have to lift a finger they will:

  • Create a hidden follower (database)
  • Wait for it to catch up (to allow uninterrupted operations)
  • Push the hidden follower’s creds to your app (so the app uses the new follower database)
  • Unfollow it from your former leader (to ensure smooth operations)
  • Repoint any followers you may have to properly follow your new leader (again to ensure smooth operations)

All this without me doing anything. Again I just worry about my app that will continue running without any change by the way. How cool is that?! I just worry about the app.

Just another reason for using a PaaS…