Day 52: Reverse Engineer an npm Package

Continued my web security studies. Reading through the codebase for the PassportJS package. I am going out on a limb here and trying to produce a sort of walkthrough for how the package works under the hood. This is challenging because of the fact that I have not done this before and the codebase is using older JavaScript that I am not as comfortable working with. The patterns and tricks are unfamiliar to me but they are necessary for backwards compatibility. The PassportJS package gets over 1.5 million weekly downloads (at the time of writing). That is a crazy number so breaking this down will definitely be a step in the right direction for me personally.

Okay, so how am I going to get this done. I started by mapping out the folder structure. I then mapped out all the modules and their corresponding dependencies. Finally, I am going to work my way through all the modules to summarize their purpose and functionality. I am going to start with all the modules that have no dependencies and work my way up to the modules that are reliant on ones I have already covered.

I may have to adjust my plans along the way but honestly I am excited. This is the type of work that you won’t get in a course or YouTube tutorial. This is where I want to be figuring out how it all works and making it my own to use how I want. Who knows, maybe after all this I might make my own version of an authentication framework that can compete or at least somewhat compare to PassportJS. All I have to do is try and that is exactly what I am going to do!

TLDR;

Okay, so here are the highlights of what I did:

  • Backend -> Continued studying the concepts mentioned in the web security section. I started reading through the package’s code base to fill in some of the gaps that are not fully covered in the documentation. The goal is to finish compiling all the information in this docs page as well as all the other examples and sources to construct my own notes that ensure this framework is clear and easy for me to use in the future. Decided to spend some time trying to reverse engineer the package as an exercise in understanding codebases I have no familiarity with.

Passport Package Breakdown Notes

The notes are to cover how the PassportJS package is structured and how it works from a reverse engineering approach rather than a surface level usage approach. This is my first attempt at something like this. We will see how it goes.

Overview

When we want to use the passport module we will install it using npm install passport and import it using CommonJS modules and the require statement. We will get an instance of Passport’s Authenticator Function/Class from the import.

const passport = require('passport')

Package Structure

The passport package folder structure is:

  • Root:
    • sponsors
    • lib:
      • errors
      • framework
      • http
      • middleware
      • strategies

Root Folder Files

The files in the root folder do not provide much functionality besides the package.json file.

The main field is a module ID that is the primary entry point to your program. That is, if your package is named foo, and a user installs it, and then does require("foo"), then your main module’s exports object will be returned.

This should be a module relative to the root of your package folder. For most modules, it makes the most sense to have a main script and often not much else. If main is not set it defaults to index.js in the package’s root folder.

The package’s functionality starts with the index.js file in the lib directory. All the other files are irrelevant for these notes but are listed below:

  • Root:
    • CHANGELOG.md
    • LICENSE
    • README.md
    • package.json

Sponsors Folder Files

We will ignore these because they are just image files related to the current sponsors of the package.

lib Folder Files

  • lib:
    • index.js
    • authenticator.js
    • sessionmanager.js
    • errors:
      • authenticationerror.js
    • framework:
      • connect.js
    • http:
      • request.js
    • middleware:
      • authenticate.js
      • initialize.js
    • strategies:
      • session.js

Classes / Function exports from lib Modules

In older versions of JavaScript, classes are represented by constructor functions. The constructor functions were often denoted by capitalized names similar to proper nouns i.e. Authenticator. So when we see this in the package modules we can understand that an instance of such ‘classes’ that come from Constructor Functions are in fact objects themselves and not functions. Somewhat confusing but Functions and Classes in JavaScript are not the same as other traditional OOP languages.

  • index.js -> Exports an Authenticator instance (object) with additional properties attached i.e. the passport object
    • requires:
      • authenticator.js -> for the additional Authenticator and Passport properties added to the exported instance
      • strategies/session.js -> for the additional strategies.sessionStrategy added to the exported instance
      • passport-strategy node modules package -> FILL IN
  • authenticator.js -> Exports the Authenticator class/Constructor Function
    • requires:
      • strategies/session.js ->
      • sessionmanager.js ->
      • framework/connect.js ->
  • sessionmanager.js -> Exports the SessionManager class/Constructor Function
    • utils-merge node modules package -> FILL IN
  • errors/authenticationerror.js -> Exports the AuthenticationError class/Constructor Function
    • requires: NOTHING
  • framework/connect.js -> Exports a nameless class/Constructor Function that returns an object with and initialize and authenticate property
    • requires:
      • middleware/initialize.js
      • middleware/authenticate.js
  • http/request.js -> Exports a nameless object with methods loginlogoutisAuthenticated, and isUnAuthenticated.
    • requires: NOTHING
  • middleware/authenticate.js -> Exports an initialize function
    • requires:
      • http/request.js
  • middleware/initialize.js -> Exports an authenticate function
    • requires:
      • http Node.js module
      • http/request.js
      • errors/authenticationerror.js
  • strategies/session.js -> Exports a SessionStrategy Class/Constructor Function
    • requires:
      • pause node modules package
      • util Node.js module
      • passport-strategy node modules package

Understanding What Is Happening

The strategy for breaking down packages or projects like this is to look at the modules that have no external dependencies first. That way we can work up from there with knowledge on how the required dependencies are being used in the more complex modules. The modules that have no dependencies are:

  • http/request.js -> Exports a nameless object with methods loginlogoutisAuthenticated, and isUnAuthenticated.
  • errors/authenticationerror.js -> Exports the AuthenticationError class/Constructor Function

Meta Data

Started On: 2022-08-15

References:


Goal For Round 8 of the #100DaysofCode Challenge

This is my eighth round of the “#100daysofcode” challenge. I will be continuing my work from round five, six, and seven into round eight. I was working through the book “Cracking the Coding Interview” by Gayle Laakmann McDowell. My goal was to become more familiar with algorithms and data structures. This goal was derived from my goal to better understand operating systems and key programs that I use in the terminal regularly e.g. Git. This goal was in turn derived from my desire to better understand the fundamental tools used for coding outside of popular GUIs. This in turn was derived from my desire to be a better back-end developer.

I am currently putting a pause on the algorithm work to build some backend/full stack projects. I primarily want to improve my skills with the back-end from an implementation perspective. I have improved tremendously in terminal and CLI skills but I lost focus due to how abstract the algorithm concepts got. I wanted to work on things that were more tangible until I can get to a position where I could directly benefit from improving my algorithm skills and theoretical knowledge. So that’s the focus right now. Build my backend skills and prove my full stack capabilities by building some dope projects.

Again, I still have no idea if my path is correct but I am walking down this road anyways. Worst case scenario I learn a whole bunch of stuff that will help me out on my own personal projects. Best case scenario I actually become one of those unicorn developers that go on to start a billion dollar company… You never know LOL.