Creating diagrams with Mermaid

illustrations illustrations illustrations illustrations illustrations illustrations illustrations
post-thumb

Published on 28 April 2022 by Andrew Owen (4 minutes)

I’m a convert to writing docs in Markdown. Most of this website is written using it (displayed with Hugo). But sometimes you need to include a chart or diagram in your docs.

Historically, this would likely have been in the form of an image file, exported from Microsoft Visio. Which is fine until you need to update the chart. At which point you had to find the source file, open it, edit it, export an updated image, and upload it to your website.

There’s a better way, and it’s called Mermaid. It’s a JavaScript based tool for creating charts and diagrams using a Markdown-inspired syntax. At the end of this article, I’ve included an example in context: an overview of Proof Key for Code Exchange (PKCE). Here’s the code that generates the image:

    sequenceDiagram
    participant User
    participant Mobile App
    participant STS
    participant API
    User->>Mobile App: 1. Click login link.
    
    loop challenge
    Mobile App->Mobile App: 2. Generate code verifier and code challenge.
    end
    
    Mobile App->>STS: 3. Authorization code request and code challenge to authorize.
    STS->>User: 4. Redirect to login/authorization prompt.
    User->>STS: 5. Authenticate and consent
    STS->>Mobile App: 6. Authorize code.
    Mobile App->>STS: 7. Authorization code and code verified to OAuth token.
    
    loop validate
    STS->STS: 8. Validate code verifier and challenge.
    end
    
    STS->>User: 9. ID token and access token.
    User->>API: 10. Request user data with access token.
    API->>User: 11. Response.

But before you can use Mermaid, you need to add it to your website. There’s a beginner’s guide, but as I’m using the Hugo static site generator for this website, I’ll explain how I added Mermaid to Hugo. It’s super easy.

First, grab the latest version and put the files in your Git repository in the /static/mermaid/ path.

Second, create a file in your Git repository with the path /layouts/shortcodes/mermaid.html containing:

    <link href="{{    "mermaid/mermaid.css" | relURL    }}" type="text/css" rel="stylesheet"/>
    <script defer src="{{    "mermaid/mermaid.js" | relURL    }}">mermaid.initialize({startOnLoad:true});</script>
    <div class="mermaid" align="{{     if .Get "align"     }}{{     .Get "align"     }}{{     else     }}center{{     end     }}" >{{     safeHTML .Inner      }}</div>

This creates a Hugo shortcode that enables you to use Mermaid on any page. And that’s it. You can now include Mermaid in your markdown. There are plug-ins for VSCode to display Mermaid, but if you’re using a headless CMS, then the easiest way to create your charts is in the live editor.


Proof key for code exchange

OAuth 2.0 public clients using the authorization code flow are susceptible to authorization code interception attack. You can mitigate against this by using a Proof Key for Code Exchange (PKCE as defined in OAuth 2.0 RFC 7636).

PKCE enables you to prevent malicious use of a custom URL scheme to capture redirects (for example MyApp://) that could potentially allow applications to receive an authorization code from your authorization server.

The PKCE authorization code flow adds a secret (a code_verifier generated using SHA-256) created by the client application that’s verified by the authorization server. The client application creates a transform value (hash string) of the code_verifier called the code_challenge which is sent using HTTPS to retrieve an authorization code. A malicious attacker can intercept this code, but can’t exchange it for a token without the code_verifier.

PKCE authorization code flow

The PKCE authorization code flow is similar to the standard authorization code flow. It uses a Secure Token Service (STS).

sequenceDiagram participant User participant Mobile App participant STS participant API User->>Mobile App: 1. Click login link. loop challenge Mobile App->Mobile App: 2. Generate code verifier and code challenge. end Mobile App->>STS: 3. Authorization code request and code challenge to authorize. STS->>User: 4. Redirect to login/authorization prompt. User->>STS: 5. Authenticate and consent STS->>Mobile App: 6. Authorize code. Mobile App->>STS: 7. Authorization code and code verified to OAuth token. loop validate STS->STS: 8. Validate code verifier and challenge. end STS->>User: 9. ID token and access token. User->>API: 10. Request user data with access token. API->>User: 11. Response.
  1. User login within the client application.
  2. Client creates cryptographically-random code_verifier and uses it to generate code_challenge.
  3. Client redirects user to STS with code_challenge.
  4. STS redirects user to login prompt.
  5. User authenticates.
  6. STS stores code_challenge and redirects user to client with authorization code.
  7. Client sends code and code_verifier to STS.
  8. STS verifies code_challenge and code_verifier.
  9. STS responds with ID token, access token and, optionally, refresh token.
  10. Cleint uses access token to call API to access user information.
  11. API responds with requested data.