Narration / Transcript

Building an AI-powered Financial Behavior Analyzer with NodeJS, Python, SvelteKit, and TailwindCSS - Part 2: GitHub OAuth

This is what the narrator says, not what the page shows: equations are read as sentences, code blocks are described, and citations are spoken as citations.

65 blocks · 1,863 spoken words · narrated Jul 26, 2026

  1. 0:00

    Introduction

  2. 0:02

    With the AI service completed, we now focus on setting up the base backend service. As outlined in the system's architecture, our main backend will be powered by Node.js with Express.js, using MongoDB as the database.

  3. 0:18

    While we could have chosen other combinations—such as Node dot js with Postgre SQL, Bun with Postgre SQL, or Django / Flask / Fast API / aiohttp with SQL / No SQL / New SQL —I opted for this stack as a refresher.

  4. 0:37

    We'll begin developing the backend service here and continue refining it in subsequent articles. Let's dive in! 🚀

  5. 0:45

    Prerequisite

  6. 0:47

    We assume you have already set up a TypeScript-based Express project. If not, follow these simple steps:

  7. 0:54

    Create a new folder, say backend, and change the directory into it

  8. 0:59

    Run npm init y to initialize a node project: The shell code below is 1 line.

  9. 1:06

    This will create a normal package dot json file with very basic entries.

  10. 1:12

    Install TypeScript and create a tsconfig dot json file The shell code below is 1 line.

  11. 1:19

    At this point, you have a minimal Node.js app with TypeScript support. However, for our project, we need a more structured setup. Modify your package dot json as follows: The diff code below is 32 lines, from package dot json.

  12. 1:35

    We want to use ESM instead of Common JS hence the type: module. We also want to use the latest node.js LTS (v22 at the time of writing). We also want some structure where all source files are in the src directory and tests in the tests directory with the entry point, during development, as src slash app dot ts (in production, it'll be dist slash app dot js). Next, make tsconfig dot json look like this: The JSON code below is 32 lines, from tsconfig dot json.

  13. 2:01

    You can get a better explanation for each of the entries tsconfig reference. The idea is we want to use the latest entries while being considerate. We also created aliases (that's what paths does) so that instead of doing.. slash.. slash.. slash src slash config slash base dot js, we would just do: dollar config slash base dot js. Nifty stuff!

  14. 2:25

    Source code Sirneij/finance-analyzer

  15. 2:28

    An AI-powered financial behavior analyzer and advisor written in Python (aiohttp) and TypeScript (ExpressJS & SvelteKit with Svelte 5) svelte typescript python javascript css3 html5

  16. 2:44

    Implementation

  17. 2:46

    Now it's time to get our hands dirty. We will be implementing the OAuth-based authentication system here.

  18. 2:53

    Step 1: Install dependencies and setup configurations

  19. 2:58

    We will use passports.js and passport-github2 for implementing the authentication strategy. Let's install the libraries (and types to keep TypeScript happy): The shell code below is 5 lines. Note: Create a Git Hub O Auth App

  20. 3:14

    As with most OAuth services, you need to create a new GitHub OAuth app to use its authentication strategy. After creation, you will be provided with GITHUB CLIENT ID and GITHUB CLIENT SECRET which are required by passport github2. Ensure you fill in your app details correctly.

  21. 3:33

    Having installed the packages, let's start with some configurations. Create src slash types slash misc dot types dot ts and populate it with: The TypeScript code below defines Providers and Base Config, 17 lines, from src slash types slash misc dot types dot ts.

  22. 3:53

    Though we are only supporting Git Hub OAuth for now, we defined an enum that includes Google as well. The Base Config interface will be used for all the app's configurations including auth and db which have standalone types: The TypeScript code below defines O Auth Credentials and Auth Config, 13 lines, from src slash types slash auth dot types dot ts. The TypeScript code below defines Db Config, 4 lines, from src slash types slash db dot types dot ts.

  23. 4:20

    As previously stated, we need each OAuth service's cliend id and client secret to authenticate. Another important credential is the callback url (also called redirect URI in some OAuth implementations) which is the URL where the OAuth service redirects users after authentication. You will supply this at the point of registering or creating a new OAuth app in GitHub (and other providers as well).

  24. 4:47

    Next, let's find a way to populate these credentials. We will use the dotenv package to retrieve them from a dot env file or environment variables: The TypeScript code below is 19 lines, from src slash config slash base dot config dot ts.

  25. 5:05

    We use getter methods in our configuration for three key benefits:

  26. 5:10

    Dynamic Values: Getters retrieve values on-demand, ensuring we always get the latest values

  27. 5:17

    Environment Variables: Particularly important for process dot env values that may change during runtime

  28. 5:25

    Lazy Evaluation: Values are only computed when accessed, improving performance

  29. 5:31

    I personally encountered a bug in production where my authentication process was failing because stale values were being read by process dot env for frontend Url.

  30. 5:43

    Here are the contents of src slash config slash internal slash auth dot config dot ts: The TypeScript code below is 20 lines, from src slash config slash internal slash auth dot config dot ts. The TypeScript code below is 10 lines, from src slash config slash internal slash db dot config dot ts. The TypeScript code below is 36 lines, from src slash config slash internal slash logger dot config dot ts. Tip: Use MongoDB Atlas

  31. 6:11

    You probably have MongoDB installed on your machine and you can just use it for development. In case you need to test in production, check up the free version of the MongoDB Atlas.

  32. 6:23

    Step 2: Connect to MongoDB database and redis

  33. 6:27

    With the configurations underway, let's create services that will connect our application to MongoDB as well as redis (for session storage). Note: Why Redis for Session Storage?

  34. 6:40

    While express session offers in-memory storage, Redis is preferred for production because:

  35. 6:46

    Persistence: Sessions survive server restarts

  36. 6:49

    Scalability: Handles high traffic and multiple server instances

  37. 6:54

    Performance: Fast read/write operations with minimal latency

  38. 7:00

    Memory Management: Automatic memory optimization and key expiration

  39. 7:05

    Using in-memory storage in production can lead to:

  40. 7:09

    Lost sessions after server restarts

  41. 7:12

    Memory leaks as sessions accumulate

  42. 7:15

    Scaling issues with multiple server instances

  43. 7:19

    Let's create a database service for them: The TypeScript code below defines connect To Redis, 73 lines, from src slash services slash db dot service dot ts.

  44. 7:32

    For the MongoDB connection, we implemented a retry logic in case some connection attempts fail. Aside from that, it's a basic way to connect to a MongoDB instance. We did something equivalent to redis. Now, we can proceed to hook all these up in src slash app dot ts.

  45. 7:51

    Step 3: Setting up an express server in src slash app dot ts

  46. 7:56

    Let's populate our src slash app dot ts with the following: The TypeScript code below defines start Server, 136 lines, from src slash app dot ts.

  47. 8:09

    It is a simple setup that also considers production environments. We started by creating an express application instance which is needed to attach. Next, we enabled the "trust proxy" which allows some features for applications behind a proxy. Then we informed Express to parse incoming requests with JSON payloads by "using" the express dot json middleware. This is a way of attaching middleware to express. We also used the CORS and session middlewares to appropriately configure our application's CORS for inter-origin resource sharing and sessions. Specifically, we are giving the backend a "go-ahead" to share resources with our front end. We also made sure our sessions were secured by providing them with an option to use our generated secret keys. In development, you can use openssl to generate a 32-bit secret key: The shell code below is 1 line.

  48. 9:02

    In production, you can opt for Cryptographically generated bytes.

  49. 9:07

    After that, we used passport 's authentication middleware and extended its feature to easily serialize and deserialize our app's User object. In the spirit of authentication, we defined our GitHub OAuth strategy next and it follows the normal anatomy of OAuth strategies supported by passport and specifically, passport-github2. Because we defined our credentials perfectly, we just passed it in, else we would have done something like: The TypeScript code below is 6 lines.

  50. 9:33

    In the callback function, we have access to the profile data returned by GitHub which was then passed into the Auth Service to create the user in the database: The TypeScript code below defines Auth Service, 48 lines, from src slash services slash auth dot service dot ts.

  51. 9:52

    We defined a user model (with its schema) already: The TypeScript code below is 17 lines, from src slash models slash user dot model dot ts.

  52. 10:03

    The types used so far for the user can be found in src slash types slash auth dot types dot ts: The TypeScript code below defines User Profile and Auth User, 23 lines, from src slash types slash auth dot types dot ts.

  53. 10:20

    To make TypeScript happy with our custom user type, we needed to modify its user type in src slash types slash passport dot d dot ts: The TypeScript code below defines User, 10 lines, from src slash types slash passport dot d dot ts.

  54. 10:39

    The rest of the src slash app dot ts are pretty basic. Before we wrap up with this article, let's see what the authentication routes are.

  55. 10:48

    Step 4: Authentication routes

  56. 10:51

    In src slash app dot ts, we used: The TypeScript code below is 8 lines, from src slash app dot ts.

  57. 11:00

    These routes are in src slash routes slash auth dot routes dot ts: The TypeScript code below is 35 lines, from src slash routes slash auth dot routes dot ts.

  58. 11:13

    The first one is where the authentication flow starts. It lets you login into your GitHub account and if successful redirects you to the callback url the developer supplied during OAuth app creation, for us, it's the second route. Tip: Supplying redirect route in the frontend

  59. 11:32

    Let's say a user wants to access slash private slash route in your app's front end but such a user wasn't authenticated. Then your frontend app redirects the user to login with GitHub (and provides a next equals slash private slash route in the URL). What the user expects is after a successful login, they want to be sent back to where they were headed initially slash private slash route. That was the logic implemented in the slash github route above. It simply "remembers" the user's previous state.

  60. 12:02

    These routes are very basic. We won't talk much about them. However, they used some "controllers" which we haven't seen yet: The TypeScript code below defines Auth Controller, 53 lines, from src slash controllers slash auth dot controller dot ts.

  61. 12:19

    We redirected responses back to our frontend app.

  62. 12:23

    With that, I will say see you in the next release! Check out the GitHub repository for the other missing pieces.

  63. 12:30

    Outro

  64. 12:32

    Enjoyed this article? I'm a Software Engineer and Technical Writer actively seeking new opportunities, particularly in areas related to web security, finance, healthcare, and education. If you think my expertise aligns with your team's needs, let's chat! You can find me on LinkedIn and X. I am also an email away.

  65. 12:53

    If you found this article valuable, consider sharing it with your network to help spread the knowledge!