Skip to content
Xavi Subirà edited this page Oct 15, 2024 · 1 revision

Welcome to the "Astro-SSR" wiki!

About

This repo contains the Frontend and Frontend to Backend parts of a multi-tier demo project.

Purpose

Because this is a demo project, its features have been limited to just fit the management of user authentication basic operations (see "Main Use Cases" down below); So this project allows users to get registered by providing their email address and giving an account password, or by using Google as an OAuth 2.0 account provider. Once users got registered, they are be able to login and to visit their private area, even logout their initiated session.

Contents

First of all, it might be said that this project has been written and developed using the Astro framework, with the help of Dev Containers for creating its development environment.

The full project contents can be inspected in the FOLDERS PAGE

Astro skeleton

Because of using astro for bootstrapping the project, folders scaffolding follows the structure explained in the Astro Official Documentation.

Additional folders

Some other folders have been added to that initial scaffolding, and them are:

├── private/                   // Contains files deserving private files used primary for 
|                              // data persistence or settings storage
|
└── src
    ├── classes/               // ¡¡AGNOSTIC!! Where interfaces, types, classes and other declarations 
    │   │                      // are grouped into files named by their context domain
    │   │
    │   ├── auth.js            // Contains the definition of types, classes and interfaces whose 
    │   │                      // collaborate in the user Authentication operations, 
    │   │                      // such "Credentials", "Session" or "SessionManager"
    │   │
    │   ├── middleware/        // Where classes that are thought as a part of middleware are defined
    │   │   ├── Behaviour.ts   // Declares the interface and root classes for any kind of behaviour
    │   │   └── behaviours/    // Where different behaviours are placed
    │   │
    │   └── server.ts          // Contains the definition of types, classes and interfaces used 
    │                          // by the Astro server application logic
    │ 
    └── services/              // Where application services and their implementations are declared 
        └── auth/              // Groups application services attending authentication and session tasks
            └── session/       // Contains service implementations

Acknowledgements

An AGNOSTIC FOLDER, neither its files and subfolders, do not contain any import other than the built-in Node.js classes, types and objects

Applications

This project consists, as stated initially, in a Frontend application what interacts against a Frontend to Backend side. Both are served by just one system: An astro application "Server-Side Rendered".

While the Frontend consists in a set of Pages offering Authentication interfaces (see Main Use Cases), the logic of the Authentication management is leveraged in its counterpart via a set of Endpoints.

Context

This project contains 2 applications in just one project, but involves two external services, that can be consumed in some of the available operational modes (see "Operational Modes" down below), as known BACKEND, OAUTH and AUTH.

First service is a backend that supports stateless user authentication mechanism, providing a very reduced API, consisting in a suite of endpoints for managing users sign-up, as long as the issuing and the revoking of Java Web Tokens.

When working in OAUTH or AUTH modes, the Google external service is used as a user provider, instead of the backend. Nevertheless the backend will be responsible of Account authentication, separating account user data (managed by google) from user accounts (managed by the backend).

C4Context
   title "Astro-SSR demo project ecosystem"

   Person(user,"User","Person who gets registered<br/>by sign-up form or by Google,<br/> and can sign-in and sign-out")
   System(browser, "Web browser", "Desktop or Mobile web browser<br/>used by the user to visit astro.dev<br/> and perform sign-up,<br/> sign-in and sign-out operations")

   Enterprise_Boundary(ecosystem, "Astro.dev ecosystem"){
     System_Ext(backend, "Auth Backend",$descr="Provides user management and<br/>authentication for modes<br/>BACKEND, OAUTH and AUTH")
     System(frontend, "Astro SSR", "Astro SSR application<br/>served over http")
     
     Rel_Back(backend,frontend, "Calls API<br/><br/>")
   }
   System_Ext(google, "Google API")

   Rel(user, browser, "Uses<br/><br/>")
   Rel(browser, frontend, "Signs up, signs in and<br/> sign out the user")
   Rel(browser, google, "Loads OAuth UI")
   Rel(backend, google, "Queries user data<br/> and validates tokens")

   UpdateRelStyle(browser, google, $offsetX="-100")
   UpdateRelStyle(backend, google, $offsetY="-50")
   UpdateRelStyle(backend, frontend, $offsetX="-10")
   UpdateLayoutConfig($c4ShapeInRow="2", $c4BoundaryInRow="1")
Loading

Architecture

Application uses Astro as the engine for Server Side Rendering (SSR) in order to provide the operational set of pages providing the end-user interfaces that allow running a set of authentication uses cases (see "Main use cases" down below).

This paradigm (SSR) produces an UI which runs in the Web Browser, what we call the Client Side, or the "Frontend".
While on the other hand, the logic that renders the UI and attends Action Endpoint calls, is a Server Side, named the "Frontend to Backend".

    C4Container
    title "Astro-SSR demo project architecture"

    Person(user,"User")

    Container_Boundary(browser,"Browser") {
        Container_Ext(oauth,"OAuth UI")
        Container(frontend,"Frontend")
    }

    Rel_D(user, oauth, "Authenticates and grants Frontend")
    Rel_D(user, frontend, "Performs auth actions")
 
    UpdateRelStyle(user, oauth, $offsetX="10", $offsetY="-40")
    UpdateRelStyle(user, frontend, $offsetX="-110" $offsetY="140")

    System_Boundary(google.oauth,"Google"){
        System_Ext(google, "Google API")
    }

    BiRel(frontend, google, "Loads OAuth UI")
    UpdateRelStyle(frontend, google, $offsetX="-30" $offsetY="20")
    Rel(oauth, google, "Sends User<br/>Authorization")  
    UpdateRelStyle(oauth, google, $offsetX="-30" $offsetY="-20")

    Container_Boundary(astro.dev,"Astro.SSR"){
        Container(astro, "Frontend to Backend")
        ContainerDb(sqlite,"Local Auth<br/> Database")
        Rel_R(astro, sqlite, "Fetch/store users<br/>and sessions")
        UpdateRelStyle(astro, sqlite, $offsetX="10")
    }

    Rel_D(frontend, astro, "Calls action endpoints")
    UpdateRelStyle(frontend, astro, $offsetX="10")

    Container_Boundary(backend, "Auth Backend"){    
        Container_Ext(api,"Auth API")
        ContainerDb_Ext(mariadb,"Auth Persistence")
        Rel(api,mariadb,"Stores users<br/>and JWTs")
        UpdateRelStyle(api,mariadb, $offsetX="10")
    }

    Rel(astro,api,"Sign up users<br/>fetches and<br/>revokes JWTs")
    UpdateRelStyle(astro,api,$offsetX="-20",$offsetY="-25")
    Rel(api,google,"Fetch user data<br/>and token")
    UpdateRelStyle(api,google,$offsetX="10")

    UpdateLayoutConfig($c4ShapeInRow="1", $c4BoundaryInRow="2")
Loading

Client-Side Part: "The Frontend"

This part consists in the pure Frontend of the Project, and interacts with the Server-Side part.
This interaction is performed via GET and POST requests, that are send by the web browser itself or via Fetch API.

While the first one occurs for all use cases, this last occurs once an "Auth" Use Case UI Page has been loaded and end-user requests the Use Case action to be performed.
In other words, the Frontend uses Browser document GET Requests to fully perform "Visit" use cases, and also to perform partially "Auth" use cases, obtaining in both cases an HTML that loads a Page, that has been rendered in the Server-Side part; on the other hand, Frontend sends POST Requests via Fetch API to call an action endpoint on the Server-Side Part.

Server-Side Part: "The Frontend to Backend"

Is the one managed by Astro when working in server mode. In our case we call it "Frontend to Backend", because acts as a Backend Proxy for the Client-Side in the vast majority of Operational Modes, and when there is no participation of the Backend (because of the Operational Mode), it acts as the Backend itself.

Its responsibilities include producing the web pages that the end-user may request when browsing and giving a response to Action Endpoint calls from the Frontend.
In order to attend those calls, the Frontend to Backend uses "Middleware", "Service classes" and "Action Endpoints" the following way:

Features

Main Use Cases

Main Use cases can be divided right in 2 categories:

  1. Visit Use Cases: involving just the renderization of a Page
  2. Auth Use Cases: involving the renderization of a Page providing the necessary UI that allows end-user call an action endpoint, and involving that call

Use Case Logic

Behind each Use case a single or a couple of .astro generate the necessary User Interface and the Authentication Logic.
While the User Interface manouvers its logic "client-side", by making requests to the Authentication Logic, this last runs in SSR mode.

This collaboration diagram summarizes how Main Use Cases are performed by project architectural parts:

Operational Modes

Because there are many ways to manage a user session, this Project has a main setting called OPERATIONAL_MODE which is ruled by the environment variable APP_MODE.
This variable may vary between one of the following values:

  • EPHIMERAL: Accounts are managed server-side by the Frontend to Backend part, and sessions are ephimeral (are not persisted)
  • LOCAL: Accounts are managed server-side too, issuing sessions that are persisted in a SQLite database
  • LUCIA: Accounts are managed server-side using the Lucia library
  • BACKEND: Accounts are managed by a stateless backend which issues JWT to manage sessions, and which is proxied by the server-side
  • OAUTH: Works like the BACKEND operational mode except that the accounts are managed by an external service which implements the OAuth 2.0 protocol
  • AUTH: An hybrid of BACKEND and OAUTH operational modes, that uses Auth.js framework

Visit the Operational Modes section in the Application page for more details.

Clone this wiki locally