gobsg 3.2.2

A secure OIDC Backend-for-Frontend gateway providing cookie-based session management for web clients
# GOBSG
**G** -> Gistyr     
**O** -> OpenID Connect     
**B** -> Backend for Frontend      
**S** -> Session     
**G** -> Gateway   
#### A secure OIDC Backend-for-Frontend gateway providing cookie-based session management for web clients
## Licensing Summary
This project is licensed under the [PolyForm Small Business License 1.0.0](https://polyformproject.org/licenses/small-business/1.0.0/)
### What this means
- **If you are a solo developer, sole proprietorship, nonprofit, or any organization with fewer than 100 workers and under $1M annual revenue** --> You may use, modify, and distribute this software **for free** under PolyForm Small Business terms.
- **If your company is over 100 workers or over $1M annual revenue** --> You must obtain a **commercial license**. 
  - Request a commercial license by contacting: `contact@gistyr.dev`
#### For full license text: 
See `LICENSES/LICENSE-POLYFORM-SMALL-BUSINESS.md` or visit <https://polyformproject.org/licenses/small-business/1.0.0>.
### Learn
> The best way to understand this code is to read it.          
> The codebase is not very large, and there are descriptive comments.            
> Or have an LLM summarize it for you.               
# Intended Architecture  
**Three components are needed:** `web client`, `GOBSG`, `OpenID Provider` 
### Login Flow:
`web client` -> `GOBSG` -> `OpenID Provider` -> `GOBSG` -> `web client`
- Web client sends the user’s browser to GOBSG’s `/login` route.
- GOBSG creates a new session, adds security parameters to the session, and sends the user to the OpenID Provider's login page.
- The OpenID Provider will show the user a login screen, the user will login.
- OpenID Provider redirects back to GOBSG's /callback route, simultaneously passing user data to GOBSG in the form of a JSON Web Token.
- GOBSG will validate the security parameters, check for errors, parse, and validate the JWT. If all is well, user data will be added to the session.
- GOBSG sends the browser back to the web client. The browser now carries a session cookie that identifies the server-side session.
### Session Status Flow:
`web client` -> `GOBSG` -> `web client`
- Web client calls on GOBSG’s `/sessionstatus` route.
- GOBSG reads the session cookie, verifies that a valid session exists, and checks if the access token is still valid.
  - If the access token is close to expiring, GOBSG refreshes it automatically in the background.
- GOBSG responds with either `"logged_in"` or `"not_logged_in"`, allowing the web client to update its UI accordingly.
### User Details Flow:
`web client` -> `GOBSG` -> `web client`
- Web client calls on GOBSG’s `/details` route.
- GOBSG reads the session cookie and retrieves the user's `username` and `user_id` stored in the session.
  - If the user is logged in, GOBSG returns that information.
  - If the user is not logged in, GOBSG either returns a default `username` and `user_id` or an error, depending on your configuration.
### Logout Flow:
`web client` -> `GOBSG` -> `OpenID Provider` -> `GOBSG` -> `web client`
- Web client sends the user’s browser to GOBSG’s `/logout` route.
- GOBSG clears the user’s session and redirects the browser to the OpenID Provider’s logout endpoint.
- After completing its logout process, the OpenID Provider redirects the browser back to GOBSG.
- GOBSG then redirects the browser back to the web client.
# Settings
## main-config.toml
**Must be named `main-config.toml`**             
**Must be located in the same directory as the executable**             
**Read `Mandatory Settings` and `Optional Settings` below**          
**Do not change the order of any values in this file, because of serialization**              
```toml
# --- MANDATORY --- #
# --- See Mandatory Settings in README --- #

this_server_url = "" 
cookie_name = ""
cookie_domain = ""
secret_cookie_hex_key = ""
requesting_client_url = ""
issuer_url = ""
logout_url = ""
client = ""
client_secret = ""

# --- OPTIONAL --- #
# --- See Optional Settings in README --- #
# The values below above are the default values
# Leave commented out to use the default, uncomment to set your own

#listen_address = "0.0.0.0"  
#listen_port = 3090
#workers = 1 #default is: num_cpus::get() aka number of logical cores on the system
#redis_address = "redis://127.0.0.1:6379"

#heartbeat_logging = false
#heartbeat_interval_hours = 12
#machine_name = "machine"  
#container_name = "container"
#provider = "provider"

#keep_alive_time_secs = 75
#client_request_timeout_secs = 30
#client_disconnect_timeout_secs = 5
#max_connections = 25000

#early_refresh_skew_secs = 120

#user_details_fail_when_not_authenticated = true
#default_username = "0"
#default_user_id = "0"
```
### Mandatory Settings
- `this_server_url`: The URL for this server
    - "https://secure.mysite.com"
- `cookie_name`: The name of the cookie stored on the user's device
    - "mysite_bff_sid"
- `cookie_domain`: The domain for this server
    - "secure.mysite.com"
- `secret_cookie_hex_key`: Cryptographic key used to encrypt and sign session cookies
    - generate a 128-character hexadecimal string
- `requesting_client_url`: The URL of your client side application
    - "https://mysite.com"
- `issuer_url`: Your OpenID Connect provider’s “issuer”
    - This is unique to each provider
- `logout_url`: Your OpenID Connect provider's logout url
    - Also unique to each provider
- `client`: Your client ID
    - Given by your provider
- `client_secret`: Your client secret
    - Also given by your provider
### Optional Settings
- `listen_address`: IP/interface the server binds to
- `listen_port`: TCP port the server listens on
- `workers`: Number of Actix workers
    - Each worker runs its own event loop on a dedicated OS thread, adds concurrency
- `redis_address`: User sessions are stored in Redis
    - You must have Redis installed and running
- `heartbeat_logging`: Periodically emits a heartbeat log message
    - `heartbeat_interval_hours`: Interval between heartbeat logs, in hours
    - `machine_name`: The name of your machine 
    - `container_name`: The name of your container
    - `provider`: The name of your provider
- `keep_alive_time_secs`: HTTP keep-alive timeout for idle connections
- `client_request_timeout_secs`: Max time to wait for a full request from a client before timing out
- `client_disconnect_timeout_secs`: Grace period to finish work after a client disconnects
- `max_connections`: Upper limit on concurrent TCP connections accepted by the server
- `early_refresh_skew_secs`: grace period to refresh the access token slightly before it actually expires
    - Your access token validity must be longer than this time, by a few minutes ideally
- `user_details_fail_when_not_authenticated`: By default `/details` will fail if there is no session for the user
    - Set to `true` to return default values
    - `default_username`: Return this username for unauthenticated users
    - `default_user_id`: Return this user id for unauthenticated users
## logging-config.toml
**Must be named `logging-config.toml`**             
**Must be located in the same directory as the executable**                  
**Do not change the order of any values in this file, because of serialization**        
#### GOBSG uses the `better-logger` crate: [GitHub Link]https://github.com/Gistyr/better-logger - [crates.io Link]https://crates.io/crates/better-logger 
**Read the `better-logger` README for more information**           
- All the logging settings are the same as the `better-logger` documentation, except in `TOML` format
- `wasm_logging` and `async_logging` are purposely not a configurable option in `GOBSG`
  - Because `wasm_logging` must be `false` and `async_logging` must be `true`
  - All the other settings are the same, as seen in the `better-logger` documentation
```toml
terminal_logs = true 
terminal_log_lvl = ""
file_logs = false
file_log_lvl = ""
log_file_path = ""
network_logs = false
network_log_lvl = ""
network_endpoint_url = ""
debug_extra = true
[network_format]
type = "JsonText"
field = "text"
```
# Notes
- Your client-side application, this server, and your provider generally need to have the same domain name
  - Typically these 3 services would each have their own subdomain
- Your provider must issue JWT's that are compatible with the [openidconnect]https://crates.io/crates/openidconnect crate
    - This generally is not an issue, but if you are using custom or non-standard JWTs then validation will fail
- This application is fairly specific in its use case
    - There is still work to be done to make it more general purpose
- You can see the documentation on `concat.sh` here: [LINK]https://github.com/Lozlof/concat.sh
## Notice about the committed executable
#### Does not apply to crates.io, only applies to GitHub 
`cargo build --release --target x86_64-unknown-linux-gnu`                   
`/target/x86_64-unknown-linux-gnu/release/gobsg` is committed:                                 
**I do this so I don't have to build on the production VM.**          
**You should clean and rebuild your own executable.**                          
## Contributing
Contributions are welcome if you want to.