Skip to content

Commit cd4f390

Browse files
committed
Updated to beginnings of real dev env, including github pipeline
1 parent 1c3d184 commit cd4f390

File tree

30 files changed

+1579
-135
lines changed

30 files changed

+1579
-135
lines changed

.env.example

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# -----------------------------------------------------------------------------
2+
# BIOCBOT Environment Configuration
3+
#
4+
# Copy this file to .env and fill in the appropriate values for your
5+
# development environment.
6+
# -----------------------------------------------------------------------------
7+
8+
# --- Core Application Settings ---
9+
# The port the Node.js server will run on.
10+
# IMPORTANT: This MUST match the port used in the SAML_CALLBACK_URL and the
11+
# `saml20-sp-remote.php` configuration in the docker-simple-saml project.
12+
PORT=8050
13+
14+
# --- TLEF Server Integration (Optional) ---
15+
# If you are connecting this bot to a TLEF-SERVER instance, provide its URL.
16+
TLEF_SERVER_URL=http://localhost:8000
17+
BIOCBOT_API_KEY=your-tlef-server-api-key
18+
19+
# --- Session Management ---
20+
# A long, random string used to sign the session ID cookie.
21+
SESSION_SECRET=a-very-secret-string-for-sessions
22+
23+
# Session timeout in milliseconds (Default: 7200000 = 2 hours)
24+
SESSION_TIMEOUT_MS=7200000
25+
26+
# --- SAML (Single Sign-On / Single Log-Out) Configuration ---
27+
# These values MUST correspond to the configuration of your SAML Identity Provider (IdP).
28+
# For local development, this is likely the `docker-simple-saml` project.
29+
30+
# The entry point for SAML login requests at your IdP.
31+
SAML_ENTRY_POINT=http://localhost:8080/simplesaml/saml2/idp/SSOService.php
32+
33+
# The URL for SAML Single Log-Out (SLO) requests at your IdP.
34+
SAML_LOGOUT_URL=http://localhost:8080/simplesaml/saml2/idp/SingleLogoutService.php
35+
36+
# The unique identifier for this application (the "Service Provider" or "SP").
37+
# IMPORTANT: This MUST exactly match the `entityid` configured for this SP
38+
# in your IdP's `saml20-sp-remote.php` file.
39+
SAML_ISSUER=https://tlef-biocbot
40+
41+
# The full URL where the IdP will send the SAML response after a user logs in.
42+
# The port number here MUST match the PORT variable above.
43+
SAML_CALLBACK_URL=http://localhost:8050/auth/saml/callback
44+
45+
# The full URL where the IdP will redirect the user after they have logged out.
46+
# The port number here MUST match the PORT variable above.
47+
SAML_LOGOUT_CALLBACK_URL=http://localhost:8050/auth/logout/callback
48+
49+
# The path to the IdP's public certificate, used to verify SAML response signatures.
50+
# IMPORTANT: For `docker-simple-saml`, this `server.crt` file is generated when the
51+
# SAML container starts. You must copy it from the `docker-simple-saml` project
52+
# into the `./certs/` directory of this project.
53+
SAML_CERT_PATH=./certs/server.crt

.github/workflows/deploy.yml

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# .github/workflows/deploy.yml
2+
3+
name: Deploy to Staging
4+
5+
on:
6+
push:
7+
branches:
8+
- main
9+
10+
jobs:
11+
deploy:
12+
runs-on: ubuntu-latest
13+
14+
steps:
15+
- name: Checkout code
16+
uses: actions/checkout@v4
17+
18+
- name: Setup SSH
19+
uses: webfactory/[email protected]
20+
with:
21+
ssh-private-key: ${{ secrets.DEPLOY_PRIVATE_KEY }}
22+
23+
- name: Deploy to server
24+
run: |
25+
# Add the server's host key using the secret
26+
ssh-keyscan -H ${{ secrets.STAGING_SERVER_IP }} >> ~/.ssh/known_hosts
27+
28+
# SSH into the server using the secret
29+
ssh deployer@${{ secrets.STAGING_SERVER_IP }} << 'EOF'
30+
# Navigate to the application directory
31+
cd /var/www/biocbot-staging
32+
33+
# Pull the latest code from the main branch
34+
git pull origin main
35+
36+
# Install/update npm dependencies
37+
npm install --production
38+
39+
# Restart the application service
40+
sudo systemctl restart biocbot-staging
41+
EOF

.gitignore

Lines changed: 4 additions & 134 deletions
Original file line numberDiff line numberDiff line change
@@ -1,136 +1,6 @@
1-
# Logs
2-
logs
3-
*.log
4-
npm-debug.log*
5-
yarn-debug.log*
6-
yarn-error.log*
7-
lerna-debug.log*
8-
.pnpm-debug.log*
9-
10-
# Diagnostic reports (https://nodejs.org/api/report.html)
11-
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
12-
13-
# Runtime data
14-
pids
15-
*.pid
16-
*.seed
17-
*.pid.lock
18-
19-
# Directory for instrumented libs generated by jscoverage/JSCover
20-
lib-cov
21-
22-
# Coverage directory used by tools like istanbul
23-
coverage
24-
*.lcov
25-
26-
# nyc test coverage
27-
.nyc_output
28-
29-
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
30-
.grunt
31-
32-
# Bower dependency directory (https://bower.io/)
33-
bower_components
34-
35-
# node-waf configuration
36-
.lock-wscript
37-
38-
# Compiled binary addons (https://nodejs.org/api/addons.html)
39-
build/Release
40-
41-
# Dependency directories
421
node_modules/
43-
jspm_packages/
44-
45-
# Snowpack dependency directory (https://snowpack.dev/)
46-
web_modules/
47-
48-
# TypeScript cache
49-
*.tsbuildinfo
50-
51-
# Optional npm cache directory
52-
.npm
53-
54-
# Optional eslint cache
55-
.eslintcache
56-
57-
# Optional stylelint cache
58-
.stylelintcache
59-
60-
# Microbundle cache
61-
.rpt2_cache/
62-
.rts2_cache_cjs/
63-
.rts2_cache_es/
64-
.rts2_cache_umd/
65-
66-
# Optional REPL history
67-
.node_repl_history
68-
69-
# Output of 'npm pack'
70-
*.tgz
71-
72-
# Yarn Integrity file
73-
.yarn-integrity
74-
75-
# dotenv environment variable files
762
.env
77-
.env.development.local
78-
.env.test.local
79-
.env.production.local
80-
.env.local
81-
82-
# parcel-bundler cache (https://parceljs.org/)
83-
.cache
84-
.parcel-cache
85-
86-
# Next.js build output
87-
.next
88-
out
89-
90-
# Nuxt.js build / generate output
91-
.nuxt
92-
dist
93-
94-
# Gatsby files
95-
.cache/
96-
# Comment in the public line in if your project uses Gatsby and not Next.js
97-
# https://nextjs.org/blog/next-9-1#public-directory-support
98-
# public
99-
100-
# vuepress build output
101-
.vuepress/dist
102-
103-
# vuepress v2.x temp and cache directory
104-
.temp
105-
.cache
106-
107-
# vitepress build output
108-
**/.vitepress/dist
109-
110-
# vitepress cache directory
111-
**/.vitepress/cache
112-
113-
# Docusaurus cache and generated files
114-
.docusaurus
115-
116-
# Serverless directories
117-
.serverless/
118-
119-
# FuseBox cache
120-
.fusebox/
121-
122-
# DynamoDB Local files
123-
.dynamodb/
124-
125-
# TernJS port file
126-
.tern-port
127-
128-
# Stores VSCode versions used for testing VSCode extensions
129-
.vscode-test
130-
131-
# yarn v2
132-
.yarn/cache
133-
.yarn/unplugged
134-
.yarn/build-state.yml
135-
.yarn/install-state.gz
136-
.pnp.*
3+
.DS_Store
4+
certs/
5+
*.crt
6+
*.pem

README.md

Lines changed: 79 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,79 @@
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`).

package.json

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
{
2+
"name": "tlef-biocbot",
3+
"version": "1.0.0",
4+
"description": "",
5+
"main": "index.js",
6+
"scripts": {
7+
"start": "node src/server.js",
8+
"dev": "nodemon src/server.js"
9+
},
10+
"keywords": [],
11+
"author": "",
12+
"license": "ISC",
13+
"type": "commonjs",
14+
"dependencies": {
15+
"axios": "^1.10.0",
16+
"dotenv": "^16.5.0",
17+
"express": "^5.1.0",
18+
"express-session": "^1.18.1",
19+
"passport": "^0.7.0",
20+
"passport-saml": "^3.2.4"
21+
},
22+
"devDependencies": {
23+
"nodemon": "^3.1.10"
24+
}
25+
}

public/app.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/**
2+
* BIOCBOT Frontend Component Registrar
3+
*
4+
* This file is the main entry point for the frontend application. Its primary
5+
* responsibility is to define all the custom elements (Web Components) used in
6+
* the application, effectively telling the browser what class to instantiate
7+
* for a given HTML tag (e.g., `<biocbot-app>`).
8+
*
9+
* The actual application logic (like checking auth status) is not triggered
10+
* from this file. Instead, it's initiated by the `connectedCallback` lifecycle
11+
* method within the components themselves (e.g., in BiocbotApp.js), which is
12+
* the standard and best practice for component-based architectures.
13+
*/
14+
15+
// Import the JavaScript class for each component.
16+
// The paths are relative to this file's location.
17+
import BiocbotApp from './components/BiocbotApp/BiocbotApp.js';
18+
import LoginPrompt from './components/LoginPrompt/LoginPrompt.js';
19+
import AuthenticatedView from './components/AuthenticatedView/AuthenticatedView.js';
20+
import ResponseDisplay from './components/ResponseDisplay/ResponseDisplay.js';
21+
import SettingsView from './components/SettingsView/SettingsView.js';
22+
23+
// The `customElements.define()` method registers a new custom element with the browser.
24+
// The first argument is the HTML tag name for the element (which must contain a hyphen).
25+
// The second argument is the JavaScript class that controls its behavior.
26+
customElements.define('biocbot-app', BiocbotApp);
27+
customElements.define('login-prompt', LoginPrompt);
28+
customElements.define('authenticated-view', AuthenticatedView);
29+
customElements.define('response-display', ResponseDisplay);
30+
customElements.define('settings-view', SettingsView);

0 commit comments

Comments
 (0)