wissel.net

Usability - Productivity - Business - The web - Singapore & Twins

Reuse a 3rd Party Json Web Token (JWT) for Salesforce authentication


The scenario

You run an app, could be a mobile native, a SPA, a PWA or just an application with JavaScript logic, in your domain that needs to incorporate data from your Salesforce instance or one of your Salesforce communities.

Users have authenticated with your website and the app is using a JWT Bearer Token to establish identity. You don't want to bother users with an additional authentication.

What you need

Salesforce has very specific requirements how a JWT must be formed to qualify for authentication. For example the token can be valid only for 5 minutes. It is very unlikely that your token matches the requirements.

Therefore you will need to extract the user identity from existing token, while checking that it isn't spoofed and create a new token that you present to Salesforce to obtain the session token. So you need:

  1. The key that can be used to verify the existing token. This could be a simple String, used for symmetrical signature or an X509 Public Key
  2. A private key for Salesforce to sign a new JWT (See below)
  3. A configured Connected App in Salesforce where you upload they full certificate and obtain the Consumer Key
  4. Some place to run the code, like Heroku

Authentication Flow for 3rd party JWT


Read more

Posted by on 2018-05-03 10:42 | Comments (0) | categories: Heroku Salesforce

Function length and double byte languages


Complexity is a prime enemy of maintainability. So the conventional wisdom suggests methods should be around 20 lines, with some evidence suggesting up to 100+ lines.

When I review code written by non-native English speakers, especially when their primary language is double byte based, I find methods in the 500-1000 lines range, with some special champions up to 5000 lines. So I wondered what might contribute to these function/method worms.


Read more

Posted by on 2018-04-09 10:18 | Comments (0) | categories: Java JavaScript NodeJS Software

Creative logging with $A.log()


In Lightning applications there are two ways to log: console.log(..) and $A.log(...). This has led to some confusion what to use.

The official statement: $A.log() will eventually go away, use console.log()

This is a real pity, since $A.log() is quite powerful and closer to what a developer would expect from logging. One reason for its demise: in a production setting $A.log() would output - nothing. There's no official documentation how to change that and the $A.logger.subscribe(...) method is neither documented nor guaranteed, only mentioned on Stack Exchange. So?

Enjoy it while it lasts

The simple case to activate console output in production is to add a helper function that can be triggered by a button or whatever you find necessary:

$A.logger.subscribe( "INFO", function( level, message, error ) {
                                console.log( message );
                                console.log( error );
                             });

Instead of sending output to the console, which could confuse users seeing all that ?tech' stuff, you could redirect it into a custom component (the following snippet fits into an onInit script):

var target = component.find("loggerlist").getElement();
$A.logger.subscribe( "INFO", function( level, message, error ) {
                               target.innerHTML += "<li>"+message+"</li><li>"+error+"</li>";
                             });

The target element would be <ol auraid="loggerlist"> so you get a running list.

Across the network

One is not limited to staying on the same machine. With a few lines of code logging can happen on a remote location as well. The following shows logging using websockets. For a production run (e.g. permanent instrumentation) I would make it a little more robust, like keeping the connection open and check if it is still there or send JSON, but for the occasional support this is good enough:

$A.logger.subscribe( "INFO", function( level, message, error ) {
    var wsEndPoint = 'wss://somewebsocket.url/ws/log';
    var connection = new WebSocket(wsEndPoint);
     connection.onopen = function(event) {
        connection.send(message);
        connection.send(error);
        connection.close();
    };
});

I'll show a potential receiving end implementation in a future post.
As I said: enjoy it while it lasts, it might go away soon. YMMV


Posted by on 2018-04-03 02:50 | Comments (0) | categories: Salesforce

Salesforce one year on


A year ago I said Good by IBM, Hello Salesforce. A lot has happened in the last 12 month. Salesforce is only my second salaried job, I've been running my own companies and been freelance before.

Coming from IBM, where Resource Actions had efficiently killed employee engagement, Salesforce's Ohana culture was a refreshing different. It makes such a difference to work with people who are genuinely interested in your success, without exception. In summary:

  • I became a Trailblazer Ranger, completing 30 trails, 206 badges and collecting 169625 points
  • Passed five Salesforce certifications
  • Contributed to customer success in Singapore, Australia and Korea
  • Wrote 25 blog entries (Way to little, more are coming)
  • Moved my blog from Domino to git (more on that below)
  • Contributed to OpenSource on github:
    • Maintainer for node-red-contrib-salesforce. The nodes that connect NodeRED to Salesforce, including the support for platform events
    • Excel2XML: Tool that converts XLSX tables into XML, so data can be extracted in command line applications. Main purpose is to make Excel data accessible in build pipelines (e.g. sample values for tests)
    • Spring Boot and Salesforce Canvas: Sample application that turns a Canvas POST into a JWT authentication, so classic multi pages applications can be integrated into Salesforce Canvas
    • Vert.x proxy Filtering proxy implemented in Apache vert.x. It allows to front a web application and filter HTML, JSON etc. based on content and URL
    • SFDC Platform Events: Modules for Apache vert.x to connect to Salesforce. It includes authentication and processing of platform events. This allows for high performance multi-threaded interaction with Salesforce APIs, not limited to platform events
    • Blog Comments Tool that accepts a JSON formated comment structure and creates a Bitbucket file, a commit and a pull request. Allows for a database free comment engine
    • BlogEngine: The application that powers this blog. It generates static files when commits/merges happen to my master branch on Bitbucket

What a ride, onto year two!


Posted by on 2018-04-01 12:50 | Comments (2) | categories: Salesforce

Boolean to get major overhaul


George Boole didn't seem to understand his five teenage daughters, (he didn't have sons, so this is about teenagers, not daughters) otherwise his boolean logic would encompass not only true and false, but also maybe or don't know. Luckily that omission will be addressed now.

Boolean to merge with Ternary

Quick recap: a boolean value has the values true (usually 1), false (usually 0). Ternary has 3 states, typically denoted -1, 0, 1. Not to confuse ternary with QBits which are true and false at the same time.

To reflect the real world, where nothing is certain, and cater to teenage level developers, the ternary and boolean data types will be merged into a new type: RealBoolean.

Proposals are under way to incorporate RealBoolean into all major programming languages ASAP. RealBoolean will have the values true, undecided and false. While it is up to the programming languages how these values are represented, consensus is, that the most likely candidates are -1, 0 and 1.

New hardware

Like specialized mining hardware for Crypto, RealBoolean will benefit from purpose build ternary computers. Early models had been running since 1958. Ternary computing also has arrived in micro processor architectures. Of course there are doubters

Transition period

Having multiple data types to express the truth might fit the political desire for alternate facts, but is an unsustainable confusion in programming. Therefore the classic boolean values will become illegal April 01, 2042.
In the transition period classic booleans will be ducktyped into RealBoolean whenever the values true, false or 1 are used. For boolean 0 or -1 (as some unfortunate languages use) compilers and runtimes are mandated to issue a warning for the first 5 years, thereafter a stern warning before they finally become illegal

Enforcement

All version control repositories will be scanned (the NSA does that anyway) and offending code flagged with new issues. Binary code, not compiled from a repository, will be treated as virus, blocked and deleted. After the deadline all remaining offending code will be transpiled into COBOL - good luck with finding developers to make sense of that code thereafter


Posted by on 2018-04-01 12:50 | Comments (4) | categories: After hours Software Technology

Authenticate from Salesforce to Heroku with JWT


Heroku PAAS is an easy and flexible way to extend Salesforce functionality.
Its easy to call out to a Heroku REST service build with a method of your choice: Java, JavaScript, Ruby etc.
The usual sticky point between two platforms is the identity of the caller.

In a lot of cases the only requirement is ?a valid Salesforce user?, eventually with some additional claims added.
For this scenario a JWT Bearer authentication (RFC 7519) is a good pick.

When you look around, most examples revolve around a JWT token being issued after some means of authentication from the same system that was authenticated against.
This scenario is different: The Salesforce server issues the JWT token and code on Heroku validates the token as authorization.
The beauty of the approach: no extra calls need to be made to get this working.

What you will need:

  • A valid certificate, in this case self signed is good enough (it won't be used by a browser)
  • OpenSSL installed on your computer
  • A Heroku account

Preparing the certificate

In Salesforce setup open Certificate and Key management.
Create or pick a key. Note down the name. For this article I will use YourCertNameHere. Open the key and click on Download Certificate.
The cert will be downloaded in crt format. We use this file to extract the public key that Heroku will use to verify the signature. To get the key use:

openssl x509 -pubkey -noout -in YourCertNameHere.crt

The String we need is between the BEGIN and END lines, excluding the lines. You can store it into a file or create a Heroku environment variable.
Since it is a public key, you don't need to guard it as fiercly as your private keys.

The APEX code

Before making a call-out to Heroku, you need to componse the signed JWT token. That's done in just a few lines:

public static String getJWTBearer(String subject, String keyName) {
    Auth.JWT jwt = new Auth.JWT();
    jwt.setSub(subject);
    Auth.JWS myJws = new Auth.JWS(jwt, keyName);
    return myJws.getCompactSerialization();
}

You might opt to add additional claims beside the subject, when your use case does require that.
The header value gets added to the Authorization header as Bearer authorization.

Java code

I'm using the jjwt library which is available on Maven Central.
It makes it simple to retrieve a claim. An expired claim or an invalid signature will throw an error, so wrap it into a try/catch.

import java.security.Key;
import java.security.KeyFactory;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;

public class JwtVerifier {
	public static Claims getClaims(String key, String token) throws Exception {

		byte[] byteKey = Base64.getMimeDecoder().decode(key);
		X509EncodedKeySpec X509publicKey = new X509EncodedKeySpec(byteKey);
		KeyFactory kf = KeyFactory.getInstance("RSA");
		Key realKey = kf.generatePublic(X509publicKey);
		return Jwts.parser().setSigningKey(realKey).parseClaimsJws(token).getBody();
	}
}

The only catch in the code was the need for MimeDecoder instead of a standard Decoder for Base64 decoding.
The subject, typically the user, can be retrieved using claims.getSubject()

Next stop, for another blog entry: the NodeJS equivalent.

As usual YMMV!


Posted by on 2018-03-23 04:40 | Comments (0) | categories: Heroku Java Salesforce

Using LetsEncrypt certificates in your JKS


Dealing with certificates in Java is always fun. The keystore Java uses is different from the certificate files you are used to in your web server or node.js.

Salesforce is build on Java, so we have to make peace with the Keystore. This article outlines the steps to use a LetsEncrypt certificate in a keystore. You will need:

  • Internet connection
  • OpenSSL installed
  • Able to run the LetsEncrypt challenge
  • Access to your DNS to add a record (for the challenge)
  • Java runtime installed
  • Public IP address

For this sample I will use the Domain ???demo.example.com???

Obtaining a PEM certficate from LetsEncrypt

Easiest is to use the certbot utility on a Linux machine (e.g. spin up an instance on Heroku). DigitalOcean has detailed instructions.
There used to be a tls-sni challenge which was marked insecure, so you want to the DNS challenge.

sudo certbot certonly --manual --preferred-challenges dns -d demo.example.com

Convert PEM to PKCS12 format

First concatenate all PEM files into one. Presuming you used the Letsencrypt mechanism:

sudo cat /etc/letsencrypt/life/demo.example.com/*.pem > fullcert.pem

Then use OpenSSL to convert that into PKCS12 format. Note: if you do that on a Windows command prompt you must run the command prompt as administrator otherwise you just get an error

openssl pkcs12 -export -out fullchain.pkcs12 -in fullchain.pem

Prepare a Java JSK keystore

You can't just create an empty keystore, so create a new temp key and specify a new keystore, then delete that key. That gives you the empty keystore:

keytool -genkey -keyalg RSA -alias sfdcsec -keystore sfdcsec.ks
keytool -delete -alias sfdcsec -keystore sfdcsec.ks

Import pkcs12 into JKS

Almost final steps. Don't forget your passwords

keytool -v -importkeystore -srckeystore fullchain.pkcs12 -destkeystore sfdcsec.ks -deststoretype JKS

Adjust alias for Salesforce import

The Salesforce import utility is picky about Alias names. The previous import created the entry
Alias name: 1 which needs to be updated:

keytool -keystore sfdcsec.ks -changealias -alias 1 -destalias demo_example_com

And voilah, you have a properly signed certificate for your Salesforce instance. Downside: to be repeated every 90 days.

As usual YMMV!


Posted by on 2018-03-22 03:18 | Comments (0) | categories: Java Salesforce

A filtering proxy server with vert.x


Scenario

You have this nice application running in your (cloud or on premises) environment and then a big scare hits. Suddenly you need to remove or mask different streams of data depending on all sorts of conditions your legal department is torturing advising you.

Until your applications natively can do that, you might resort to a content filter that sits as a proxy between you and the application (technically it is a reverse proxy, but that's fine print).

To explore the feasibility of such an approach I created SampleProxy based on work of Julien Viet using vert.x as my runtime environment.

Requirements

  • Needs to be a content filter, not a URL blocker
  • Need to provide functionality for practical use out-of-the-box, but needs to be extensible (configuration over code)
  • Need to be able to filter HTML, JSON, XML and Text. No need to filter binary formats. Contemplating about JavaScript (you could use the text filter for that)
  • Filter based on mime-type and URL as standard, but extensible to use anything in the request or reply to decide what to filter
  • Configurable FilterChain: a filter decides what to filter (with the mime-type as minimum condition) and hands actual filter operation to a chain of subfilters that do the actual stream manipulation
  • configurable subfilters. E.g. a filter that can remove JSON nodes from JSON data should read the qualifier from a configuration, so the same filter class can be reused for different filter purposes
  • CSS isn't on the radar yet, but contributions would be happily accepted

The flow

Flow from browser to proxy to application and back

Things I learned along the way

There are always a few lessons to be had, here are some from this project:

  • http is a chunked beast. When you send larger amount of content, probability approaches 1 that your server uses chunked - until HTTP/2 resolves us from it. A hard choice needs to be made to either use a stream based processing of a chunk (think SAX) or collecting the Junks to be able to process a DOM. To be fully flexible I opted for a DOM/Object based approach, but you are free to create whatever you deem necessary
  • Jsoup is a reliable HTML parser. It supports CSS selectors that make addressing HTML elements a breeze. Solves one of the hardest problems: targeting
  • Targeting JSON data is much harder that it needs to be, the very moment Arrays appear in your JSON structure. There is RFC6901 JSON Pointer, but it targets exactly one element, while a typical use case would be: ?from the list (array) of discussion posts, pick the list of comments and those who have an eMail, mask them?. So I implemented 2 variations: a simple path style address /discussion/posts/comments/email which automatically traverses arrays and an XPath based approach where I convert JSON to a strict XML syntax and back. More detail here, examples in a future post

Items on the ToDo list

  • Better documentation
  • Code cleanup
  • Tests
  • Deploy to Heroku button
  • More filters

Your turn

Go check it out and let me know what you think! (Yeah - documentation needs some work).

Caveat (a.k.a disclaimer): this is a prototype and work in progress, YMMV!


Posted by on 2018-03-04 03:18 | Comments (0) | categories: Heroku Java vert.x

Query a JSON object like XPath in Java


I'm fond of XML especially XSLT and the related XPath query possibilities.
Moving into the wonderworld of JSON I'm missing those platform independent query and rendering options.
For templating Mustache comes close, especially in regards of platform support, but XPath still has to find its match in the JSON world.

The closest equivalent is JSONPath (also available for Java ) with a nice interactive playground.

I was looking at adopting it for one of my projects written in vert.x.
JSON isn't native to Java and there are several competing implementations around JSON: Google's GSON, Jackson
and vert.x core JsonObject (there are probably more).

So I was wondering: What if I could use XPath and by extension XSLT directly on JSON? The first step there would be a save way to transform JSON to XML and back.
Using vert.x JsonObject and JsonArray as starting point,
I had the following considerations:

  • I can't use XML tags to map to JSON labels, since labels can contain any character, XML tags are restricted
  • The resulting XML only needs 2 elements: Element and Array
  • An element can have a scalar value, my first test deals with strings only, or can contain another element or array
  • An array does not have a value. It can contain zero or more scalar values and/or zero or more arrays or elements

So I build a small prototype. A simple class that reads a json file from the command line, prints it to the console, transforms it to XML, prints it to the console, transforms it back and prints it again.
The prototype depends on vert.x core.

The result can be found in this gist or read more.


Read more

Posted by on 2018-02-28 03:50 | Comments (0) | categories: Java vert.x

Spring Boot and Salesforce Canvas


The challenge

Salesforce canvas offers a capable integration point between Salesforce and external applications to surface them inside the Salesforce UI. One of the aspects is establishing identity. There are two options: OAuth and a signed request. I???m looking at the later. A signed request posts (as in HTTP POST) a digitally signed JSON request to the external application.

When all you need is a single page, validating the request and returning the result is all that needs to be done. It becomes trickier when you want to navigate in the application and when that application runs in the cloud with multiple load balanced instances, so you might end up on a different instance mid-flight.

Most of the sample code available uses the sophisticated Canvas JavaScript SDK, so I decided to focus on backend code here.

The project

All the code can be found on Github including sources. Feel free to open issues. To try it out you can deploy it to Heroku (button in the Readme on Github) and configure a Canvas app in Salesforce. Use https://yourappname.herokuapp.com/sfdcauth/hw as Canvas URL

The approach

Build a Spring Boot application that provides an authentication endpoint suitable for a Canvas POST and other endpoints that only allow authenticated access. The security will be provided by Json Web Tokens a.k.a JWT or RFC 7519.

As added challenge: The application will require standard link and form based navigation, so we can't rely on AJAX to provide additional ?stuff? into the requests from/to the server. And yes - needs to be able to run on Heroku on multiple instances (Dynos in Heroku language) without the sticky session feature switched on.

Lessons learned

  • Spring Boot performs magic. Sometimes a little too much magic
  • Base64 isn't Base64. The Java8 decoder works different from the Apache Commons, so the signed checksums don't tally. Pain in the ?proverbial? to get the validation code from the SDK running
  • Spring security is well thought through. I like the approach: the very moment you add it to a project, all is closed until you specifically open it
  • You can't stuff the entire JSON coming from Salesforce back into a cookie
  • JSON in Java is still a pain (Bearable with JsonNode)
  • The information around custom error pages in Spring is confusing. It seems to have evolved over time and conflicting information is presented
  • Json Web Tokens (JWT) rock
  • Cookies behave different in Salesforce canvas than in regular iFrames. In an iFrame http cookies are considered ?native? to their environment, in canvas they seem to run as third-party cookies (unless I miss something). Stole a few hours tracking the issue down
  • Avonni Creator is a nice tool to play with Lightning Design System layouts

As usual YMMV


Posted by on 2018-02-20 09:34 | Comments (0) | categories: Heroku Java Salesforce