Toby Hobson

Passlock

Serverless Passkey authentication platform, supporting all major tech stacks.

Passlock

Passlock

  • Industry: Technology
  • Size: FOSS project
  • Website: passlock.dev
Passlock enables development teams to integrate strong, yet frictionless multi factor authentication into their web apps. Passlock is framework agnostic, working with all major frontend and backend stacks.

Tech used

  • AWS Serverless & SST
  • DynamoDB - Single Table Design
  • Typescript FP (Effect)

Features

  • Biometrics
  • Serverless - AWS/SST
  • Functional Typescript - Effect

My role

Lead developer/maintainer. The great thing about a side gig is the ability to choose your own tech stack. I wanted a change from Scala, Java and the JVM in general and Passlock gave me the opportunity to do so 😁

Features

Passlock makes Passkey authentication really simple. I’ve abstracted the complexity associated with public key cryptography into a simple Typescript library and serverless backend.

  • Supports all major frontend frameworks (React, Angular, Svelte)
  • Supports most fullstack frameworks (Next.js, Nuxt, Sveltekit etc)
  • Works with almost all backend languages (Python, Java, Go)

The solution

Passlock is composed of 3 major projects:

Frontend client library - A framework agnostic JS/TS library.
Serverless API - Powered by AWS Gateway and Lambda functions.
Management console - SvelteKit 2 project.

Some performance (and memory) critical aspects of the system are written in Go and deployed as lambda functions, however the majority of the code is written in Typescript. All three projects make extensive use of the Effect library. Users of the frontend library are not (by default) exposed to the functional aspects of the library, however they can hook into the effects by importing functions from an fp/ package.

The primary database used by the API is DynamoDB, for which I’ve adopted a single table design. I’m also using DynamoDB streams for change data capture. This enables logging, aggregation and “tripwire” alerting.

I use AWS Key Management System and Parameter store for credentials, and EventBridge for async, event driven programming.

The API and Console are deployed via Cloudformation stacks. I chose to use the awesome SST framework over CDK/Serverless. This allows me to spin up full production like environments in a few minutes. 👌

What did I learn?

I’m glad I chose a serverless architecture and the SST framework. The ops aspect of devops took up far too much of my time on previous projects, and if I’m honest it’s not something I really enjoy. SST has allowed me to concentrate on functionality, security and usability without needing to think (too much) about stability and scalability.

However lambda cold starts are an issue. I managed to get them down to around 800ms but that’s still too slow, especially when the frontend needs to hit multiple lambdas to perform an operation. Perceptions is often more important than reality, especially where usability is concerned. I’ve added “warmers” to both the API itself and the frontend client.

Essentially when a user lands on the login page I fire off a few “pings” to the lambda endpoints to warm them. By the time the user actually presses the login button the lamdbas are ready for them. Likewise, some API calls are logically followed by subsequent calls to other endpoints. By firing off pings during the initial calls, the API can warm itself. Of course the calls need to happen asyncronously, and this is one area where EventBridge came in useful.

However, I can’t help thinking that there’s too much effort involved here. I haven’t actually had feedback that cold starts are an issue, it’s something I judged to be an issue. In hindsight I should have waited to hear feedback from other developers and end users before going down this route. It was a classic case of premature optimisation.

Need help with your project?

Do you need some help or guidance with your project? Reach out to me (email is best)