|
1 | | -# tlef-biocbot |
| 1 | +# BIOCBOT SAML Example Application |
| 2 | + |
| 3 | +This project serves as an example of a Node.js web application that uses SAML for user authentication. It demonstrates how to integrate with a SAML Identity Provider (IdP) for both login (SSO) and logout (SLO), and how to manage application state based on authentication status. |
| 4 | + |
| 5 | +See https://github.com/ubc/docker-simple-saml for the SAML provider you can run locally. |
| 6 | + |
| 7 | +The backend is built with Express.js and Passport.js, using the `passport-saml` strategy. The frontend is built with vanilla JavaScript using Web Components. |
| 8 | + |
| 9 | +## Project Structure |
| 10 | + |
| 11 | +The repository is organized into two main parts: |
| 12 | + |
| 13 | +- `public/`: Contains all client-side code, including HTML, CSS, and JavaScript for the frontend application. |
| 14 | +- `src/`: Contains all server-side Node.js code, including the Express server, API routes, and authentication middleware. |
| 15 | + |
| 16 | +--- |
| 17 | + |
| 18 | +## Backend (`src/`) |
| 19 | + |
| 20 | +The backend is responsible for serving the frontend application, handling API requests, and managing the SAML authentication lifecycle. |
| 21 | + |
| 22 | +### Core Files |
| 23 | + |
| 24 | +- **`src/server.js`**: The main entry point for the backend. It sets up the Express server, configures all middleware (including sessions and Passport), mounts the API and authentication routes, and starts the server. |
| 25 | + |
| 26 | +### Middleware (`src/middleware/`) |
| 27 | + |
| 28 | +Middleware functions are the backbone of the Express application, handling requests sequentially. |
| 29 | + |
| 30 | +- **`session.js`**: Configures `express-session` to manage user sessions. It sets up session secrets, cookie properties, and timeouts. In a production environment, the default `MemoryStore` should be replaced with a more robust session store like Redis. |
| 31 | +- **`passport.js`**: Configures the `passport-saml` strategy. It loads the IdP's signing certificate and defines the SAML configuration options, including the entry point (for login), logout URL, and callback URLs. It also maps the attributes from the SAML profile to a user object that is stored in the session. |
| 32 | +- **`requireAuth.js`**: A simple middleware that protects routes by checking if a user is authenticated (`req.isAuthenticated()`). If the user is not logged in, it returns a 401 Unauthorized error for API requests or redirects to the login page for browser requests. |
| 33 | + |
| 34 | +### Routes (`src/routes/`) |
| 35 | + |
| 36 | +- **`auth.js`**: Handles all authentication-related routes. |
| 37 | + - `/auth/login`: Initiates the SAML login flow by redirecting the user to the IdP. |
| 38 | + - `/auth/saml/callback`: The endpoint where the IdP posts the SAML assertion after a successful login. Passport processes the assertion and creates a user session. |
| 39 | + - `/auth/logout`: Initiates the SAML Single Log-Out (SLO) flow. |
| 40 | + - `/auth/logout/callback`: The endpoint where the IdP redirects the user after a successful logout. |
| 41 | + - `/auth/me`: An API endpoint for the frontend to check if the current user is authenticated and to get their user information. |
| 42 | +- **`pages.js`**: Handles serving the main `index.html` file for different client-side URLs (e.g., `/` and `/settings`). This enables the single-page application to handle routing on the client side while still allowing users to directly navigate to or refresh pages. Routes in this file are protected by the `requireAuth` middleware where necessary. |
| 43 | +- **`index.js`**: The main **API router**. It assembles all other API-related route files (like `timestamp.js` and `echo.js`) and is mounted under the `/api` prefix in `server.js`. |
| 44 | +- **`timestamp.js`**, **`echo.js`**, etc.: Example API routes that demonstrate how to create authenticated endpoints that might communicate with other backend services. |
| 45 | + |
| 46 | +--- |
| 47 | + |
| 48 | +## Frontend (`public/`) |
| 49 | + |
| 50 | +The frontend is a single-page application (SPA) built with modern, framework-less JavaScript. It uses Web Components to create encapsulated and reusable UI elements. |
| 51 | + |
| 52 | +### Core Files |
| 53 | + |
| 54 | +- **`public/index.html`**: The main HTML file. It contains the basic page structure and a single custom element, `<biocbot-app>`, which is the root of the application. |
| 55 | +- **`public/app.js`**: The main entry point for the frontend JavaScript. It imports all the Web Component classes and registers them with the browser using `customElements.define()`. |
| 56 | + |
| 57 | +### Components (`public/components/`) |
| 58 | + |
| 59 | +- **`BiocbotApp/`**: The root component. It manages the application's core state, including the user's authentication status and which view (`<authenticated-view>` or `<settings-view>`) is currently active. It uses the browser's History API to handle client-side routing, updating the URL as the user navigates through the application. |
| 60 | +- **`LoginPrompt/`**: A simple component shown to unauthenticated users. It displays a "Login" button that redirects the user to the `/auth/login` route to start the SAML flow. |
| 61 | +- **`AuthenticatedView/`**: The main view for logged-in users. It displays user details, provides buttons to make authenticated API calls, and includes a link to the settings page. |
| 62 | +- **`SettingsView/`**: A component that displays different content based on the user's affiliation (e.g., 'student' or 'faculty'). It demonstrates how to implement simple role-based access control on the frontend and includes a "Back" button to return to the main view. |
| 63 | +- **`ResponseDisplay/`**: A utility component used to format and display the JSON responses from the backend API calls. |
| 64 | + |
| 65 | +## Getting Started |
| 66 | + |
| 67 | +1. **Clone the repository.** |
| 68 | +2. **Install dependencies:** |
| 69 | + ```bash |
| 70 | + npm install |
| 71 | + ``` |
| 72 | +3. **Set up your environment:** |
| 73 | + - Copy the `.env.example` file to a new file named `.env`. |
| 74 | + - Update the variables in `.env` to match your local development environment. |
| 75 | +4. **Run the application:** |
| 76 | + ```bash |
| 77 | + npm start |
| 78 | + ``` |
| 79 | +5. Open your browser and navigate to the URL specified by the `PORT` in your `.env` file (e.g., `http://localhost:8050`). |
0 commit comments