From 3465e9e2321b1471348451216a0243c3430b2aa1 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Thu, 26 Feb 2026 01:41:59 -0700 Subject: [PATCH] doc(auth/csvauth): update examples --- auth/csvauth/README.md | 163 ++++++++++++++++++++++++----------------- 1 file changed, 94 insertions(+), 69 deletions(-) diff --git a/auth/csvauth/README.md b/auth/csvauth/README.md index 463d8b7..a2820d3 100644 --- a/auth/csvauth/README.md +++ b/auth/csvauth/README.md @@ -6,13 +6,13 @@ Simple, non-scalable credentials stored in a tab-separated file. \ (logical successor to [envauth](https://github.com/therootcompany/golib/tree/main/auth/envauth)) 1. Login Credentials - - Save recoverable (aes or plain) or salted hashed passwords (pbkdf2 or bcrypt) - - Great in http middleware, authorizing login or api requests - - Stored by _username_ + - Save recoverable (aes or plain) or salted hashed passwords (pbkdf2 or bcrypt) + - Great in http middleware, authorizing login or api requests + - Stored by _username_ (or _token_ hash) 2. Service Accounts - - Store API keys for services like SMTP and S3 - - Great for contacting other services - - Stored by _purpose_ + - Store API keys for services like SMTP and S3 + - Great for contacting other services + - Stored by _purpose_ Also useful for generating pbkdf2 or bcrypt hashes for manual entry in a _real_ database. @@ -22,6 +22,11 @@ Can be adapted to pull from a Google Sheets URL (CSV format). # create login credentials csvauth store 'bot@example.com' +# create login token +csvauth store --token 'bot@example.com' +``` + +```sh # store service account csvauth store --purpose 'postmark_smtp_notifier' 'admin@example.com' ``` @@ -44,7 +49,8 @@ auth, err := csvauth.Load(f) // ... -if err := auth.Verify(username, password); err != nil { +credential, err := auth.Authenticate(usernameOrEmpty, passwordOrToken) +if err != nil { return err } @@ -54,97 +60,116 @@ account := auth.LoadServiceAccount("account-mailer") req.SetBasicAuth(account.Name, account.Secret()) ``` -## Login Credentials +## Login Credentials: Basic Auth & Bearer Token 1. Use `csvauth store [options] ` to create new login credentials. - ```sh - go run ./cmd/csvauth/ store --help - ``` + ```sh + go run ./cmd/csvauth/ store --help + ``` - ```sh - go run ./cmd/csvauth/ store 'john.doe@example.com' + ```sh + go run ./cmd/csvauth/ store 'john.doe@example.com' - go run ./cmd/csvauth/ store --algorithm aes-128-gcm 'johndoe' - go run ./cmd/csvauth/ store --algorithm plain 'johndoe' - go run ./cmd/csvauth/ store --algorithm 'pbkdf2 1000 16 SHA-256' 'johndoe' - go run ./cmd/csvauth/ store --algorithm 'bcrypt 12' 'john.doe@example.com' + # choose your own algorithm + go run ./cmd/csvauth/ store --algorithm aes-128-gcm 'johndoe' + go run ./cmd/csvauth/ store --algorithm plain 'johndoe' + go run ./cmd/csvauth/ store --algorithm 'pbkdf2 1000 16 SHA-256' 'johndoe' + go run ./cmd/csvauth/ store --algorithm 'bcrypt 12' 'john.doe@example.com' - go run ./cmd/csvauth/ store --ask-password 'john.doe@example.com' - go run ./cmd/csvauth/ store --password-file ./password.txt 'johndoe' + # choose your own password + go run ./cmd/csvauth/ store --ask-password 'john.doe@example.com' + go run ./cmd/csvauth/ store --password-file ./password.txt 'johndoe' - go run ./cmd/csvauth/ store --roles 'admin' --extra '{"foo":"bar"}' 'jimbob' - ``` + # add extra credential data + go run ./cmd/csvauth/ store --roles 'admin' --extra '{"foo":"bar"}' 'jimbob' + ``` 2. Use `github.com/therootcompany/golib/auth/csvauth` to verify credentials - ```go - package main + ```go + package main - import ( - "net/http" - "os" + import ( + "net/http" + "os" - "github.com/therootcompany/golib/auth/csvauth" - ) + "github.com/therootcompany/golib/auth/csvauth" + ) - var auth csvauth.Auth + var auth csvauth.Auth - func main() { - f, _ := os.Open("./credentials.tsv") - defer func() { _ = f.Close() }() - auth, _ = csvauth.Load(f) + func main() { + f, _ := os.Open("./credentials.tsv") + defer func() { _ = f.Close() }() + auth, _ = csvauth.Load(f) - // ... - } + // ... + } - func handleRequest(w http.ResponseWriter, r *http.Request) { - username, password, ok := r.BasicAuth() - if !ok || !auth.Verify(username, password) { - http.Error(w, "Unauthorized", http.StatusUnauthorized) - return - } + // Example of checking for checking username (or token signifier) and password + // (or token) in just about every common way + func handleRequest(w http.ResponseWriter, r *http.Request) { + name, secret, ok := r.BasicAuth() + if !ok { + secret, ok = strings.CutPrefix(r.Header.Get("Authorization"), "Bearer ") + if !ok { + secret = r.Header.Get("X-API-Key") + if secret == "" { + secret = r.URL.Query().Get("access_token") + if secret == "" { + http.Error(w, "Unauthorized", http.StatusUnauthorized) + return + } + } + } + } - credential, err := auth.LoadCredential(username) - // ... - } - ``` + credential, err := auth.Authenticate(name, secret); + if err != nil { + http.Error(w, "Unauthorized", http.StatusUnauthorized) + return + } + + // ... + } + ``` ## Service Account 1. Use `csvauth store --purpose [options] ` to store API credentials - ```sh - go run ./cmd/csvauth/ store --help - ``` + ```sh + go run ./cmd/csvauth/ store --help + ``` - ```sh - go run ./cmd/csvauth/ store --purpose ntfy_sh_admins 'acme-admins-1234abcd' - ``` + ```sh + go run ./cmd/csvauth/ store --purpose ntfy_sh_admins 'acme-admins-1234abcd' + ``` 2. Use `github.com/therootcompany/golib/auth/csvauth` to verify credentials - ```go - package main + ```go + package main - import ( - "bytes" - "net/http" - "os" + import ( + "bytes" + "net/http" + "os" - "github.com/therootcompany/golib/auth/csvauth" - ) + "github.com/therootcompany/golib/auth/csvauth" + ) - func main() { - f, _ := os.Open("./credentials.tsv") - defer func() { _ = f.Close() }() - auth, _ := csvauth.Load(f) + func main() { + f, _ := os.Open("./credentials.tsv") + defer func() { _ = f.Close() }() + auth, _ := csvauth.Load(f) - // ... + // ... - credential := auth.LoadServiceAccount("ntfy_sh_admins") - req, _ := http.NewRequest("POST", "https://ntfy.sh/"+credential.Secret(), bytes.NewBuffer(message)) + credential := auth.LoadServiceAccount("ntfy_sh_admins") + req, _ := http.NewRequest("POST", "https://ntfy.sh/"+credential.Secret(), bytes.NewBuffer(message)) - // ... - } - ``` + // ... + } + ```