### Access Token Response Example Source: https://github.com/pilcrowonpaper/copenhagen/blob/main/pages/oauth.md Example JSON response from the token endpoint containing the access token and potentially other fields like refresh token and expiration time. ```APIDOC { "access_token": "" } ``` -------------------------------- ### Authorization URL with PKCE Parameters Source: https://github.com/pilcrowonpaper/copenhagen/blob/main/pages/oauth.md Example authorization URL including PKCE parameters `code_challenge_method` and `code_challenge`. ```APIDOC https://accounts.google.com/o/oauth2/v2/auth? response_type=code &client_id=<...> &redirect_uri=<...> &state=<...> &code_challenge_method=S256 &code_challenge= ``` -------------------------------- ### OpenID Connect Token Response Source: https://github.com/pilcrowonpaper/copenhagen/blob/main/pages/oauth.md Example response from an OIDC provider including both `access_token` and `id_token`. ```APIDOC { "access_token": "", "id_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwiaXNzIjoiZXhhbXBsZS5jb20ifQ.uMMQPfp7LwcLiBbfZdoHdIPjKgS2HUfOr5vlY71el8A" } ``` -------------------------------- ### OpenID Connect Discovery Endpoint Example Source: https://github.com/pilcrowonpaper/copenhagen/blob/main/pages/oauth.md Demonstrates the well-known URL for OpenID Connect Discovery and the structure of the JSON response containing provider configuration. ```APIDOC OpenID Connect Discovery Endpoint: URL: /.well-known/openid-configuration Example: https://accounts.google.com/.well-known/openid-configuration Provider Configuration JSON: { "issuer": "https://example.com", "authorization_endpoint": "https://example.com/oauth2/authorize", "token_endpoint": "https://example.com/oauth2/token", "userinfo_endpoint": "https://example.com/oauth2/userinfo", "code_challenge_methods_supported": ["S256"], "grant_types_supported": ["authorization_code", "refresh_token"], "scopes_supported": ["openid", "email", "profile"] } Description: The OpenID Connect Discovery mechanism allows clients to dynamically fetch the OpenID Provider's configuration. This JSON object contains essential endpoint URLs and supported features, enabling applications to adapt without hardcoding values. Note that not all OAuth providers support this feature. ``` ```json { "issuer": "https://example.com", "authorization_endpoint": "https://example.com/oauth2/authorize", "token_endpoint": "https://example.com/oauth2/token", "userinfo_endpoint": "https://example.com/oauth2/userinfo", "code_challenge_methods_supported": ["S256"], "grant_types_supported": ["authorization_code", "refresh_token"], "scopes_supported": ["openid", "email", "profile"] } ``` -------------------------------- ### Legitimate Redirect Example Source: https://github.com/pilcrowonpaper/copenhagen/blob/main/pages/open-redirect.md Shows a typical use case for a redirect parameter, where a user is directed to a safe internal page after an action. ```text https://example.com/login?redirect_to=%2Fhome ``` -------------------------------- ### Example of Open Redirect Vulnerability Source: https://github.com/pilcrowonpaper/copenhagen/blob/main/pages/open-redirect.md Demonstrates a URL that exploits an open redirect vulnerability by specifying an external malicious domain in the 'redirect_to' parameter. ```text https://example.com/login?redirect_to=https%3A%2F%2Fscam.com ``` -------------------------------- ### ECDSA Signing Example Source: https://github.com/pilcrowonpaper/copenhagen/blob/main/pages/cryptography/ecdsa.md Demonstrates how to sign a message using ECDSA in Go. It involves hashing the message with SHA-256 and then using the private key to generate the signature. ```go import ( "crypto/ecdsa" "crypto/rand" "crypto/sha256" ) msg := "Hello world!" hash := sha256.Sum256([]byte(msg)) signature, err := ecdsa.SignASN1(rand.Reader, privateKey, hash[:]) ``` -------------------------------- ### OAuth Scope Parameter Source: https://github.com/pilcrowonpaper/copenhagen/blob/main/pages/oauth.md Example of how to specify requested scopes for additional resource access in the authorization URL. Multiple scopes are space-separated and URL-encoded. ```APIDOC &scope=email%20identity ``` -------------------------------- ### CSRF Attack Example (Fetch API) Source: https://github.com/pilcrowonpaper/copenhagen/blob/main/pages/csrf.md Illustrates a CSRF attack using the Fetch API. This example shows how a malicious site can programmatically send a POST request to a sensitive endpoint on another domain, leveraging the user's existing session cookies. ```typescript const body = new URLSearchParams(); body.set("recipient", "attacker"); body.set("value", "$100"); await fetch("https://bank.com/send-money", { method: "POST", body }); ``` -------------------------------- ### Get Public Key Credential Source: https://github.com/pilcrowonpaper/copenhagen/blob/main/pages/webauthn.md Retrieves a public key credential from the user's authenticator. This is the initial step in the Web Authentication process. ```ts const credential = await navigator.credentials.get({ publicKey: { challenge, userVerification: "required", }, }); if (!(credential instanceof PublicKeyCredential)) { throw new Error("Failed to create credential"); } const response = credential.response; if (!(response instanceof AuthenticatorAssertionResponse)) { throw new Error("Unexpected"); } const clientDataJSON: ArrayBuffer = response.clientDataJSON); const authenticatorData: ArrayBuffer = response.authenticatorData const signature: ArrayBuffer = response.signature); const credentialId: ArrayBuffer = publicKeyCredential.rawId; ``` -------------------------------- ### Get Public Key Credential with Allow Credentials Source: https://github.com/pilcrowonpaper/copenhagen/blob/main/pages/webauthn.md Retrieves a public key credential, specifying a list of allowed credentials to support non-resident keys for 2FA. ```ts const credential = await navigator.credentials.get({ publicKey: { challenge, userVerification: "required", // list of user credentials allowCredentials: [ { id: new Uint8Array(/*...*/), type: "public-key", }, ], }, }); ``` -------------------------------- ### Modulo Bias Example Source: https://github.com/pilcrowonpaper/copenhagen/blob/main/pages/random-values.md Demonstrates modulo bias where certain numbers appear more frequently than others when a random integer is taken modulo a number. This occurs when the range of the random integer is not an exact multiple of the modulus. ```python RANDOM_INT % 4 ``` -------------------------------- ### CSRF Attack Example (HTML Form) Source: https://github.com/pilcrowonpaper/copenhagen/blob/main/pages/csrf.md Demonstrates a basic HTML form submission that can be exploited in a CSRF attack. The form targets a sensitive endpoint on another domain, and if the user is authenticated on that domain, their session cookie will be automatically sent with the request. ```html
``` -------------------------------- ### Generate PKCE Code Challenge Source: https://github.com/pilcrowonpaper/copenhagen/blob/main/pages/oauth.md Generates a code challenge from a code verifier using SHA256 hashing and Base64URL encoding (no padding). ```go var codeVerifier string codeChallengeBuf := sha256.Sum256([]byte(codeVerifier)) codeChallenge := base64.URLEncoding.WithPadding(base64.NoPadding).EncodeToString(codeChallengeBuf) ``` -------------------------------- ### Sign in with GitHub Link Source: https://github.com/pilcrowonpaper/copenhagen/blob/main/pages/oauth.md An HTML link that initiates the OAuth flow by directing the user to the GitHub login endpoint. ```html Sign in with GitHub ``` -------------------------------- ### Base64 Encode Client Credentials Source: https://github.com/pilcrowonpaper/copenhagen/blob/main/pages/oauth.md Encodes client ID and client secret using Base64 for inclusion in the Authorization header. ```go var clientId, clientSecret string credentials := base64.StdEncoding.EncodeToString([]byte(clientId + ":" + clientSecret)) ``` -------------------------------- ### Create Public Key Credential (Client-side) Source: https://github.com/pilcrowonpaper/copenhagen/blob/main/pages/webauthn.md This snippet demonstrates how to create a new public key credential using the Web Authentication API on the client-side. It includes essential parameters for registration, such as attestation type, relying party information, user details, public key credentials parameters, challenge, and authenticator selection. It also shows how to exclude existing credentials. ```ts const credential = await navigator.credentials.create({ publicKey: { attestation: "none", rp: { name: "My app" }, user: { id: crypto.getRandomValues(new Uint8Array(32)), name: username, displayName: name, }, pubKeyCredParams: [ { type: "public-key", // ECDSA with SHA-256 alg: -7, }, ], challenge, authenticatorSelection: { // See note below. userVerification: "required", residentKey: "required", requireResidentKey: true, }, // list of existing credentials excludeCredentials: [ { id: new Uint8Array(/*...*/), type: "public-key", }, ], }, }); if (!(credential instanceof PublicKeyCredential)) { throw new Error("Failed to create credential"); } const response = credential.response; if (!(response instanceof AuthenticatorAttestationResponse)) { throw new Error("Unexpected"); } const clientDataJSON: ArrayBuffer = response.clientDataJSON; const attestationObject: ArrayBuffer = response.attestationObject; ``` -------------------------------- ### Check for compromised passwords API Source: https://github.com/pilcrowonpaper/copenhagen/blob/main/pages/password-authentication.md This API endpoint allows checking if a password has been compromised by comparing its SHA-1 hash against a known database of leaked passwords. The API requires a GET request with the first 5 characters of the SHA-1 hash as a parameter. ```APIDOC GET https://api.pwnedpasswords.com/range/12345 Response: A list of hashed password suffixes beginning with the provided 5 characters. Example: ec68dea7966a1ea2ba9408be4dcc409884f 248b2dddf14a111b9d08b906d06224a0a79 f10a49ecd2ada17a120dc359f162b84e12c ``` -------------------------------- ### Constant time password comparison in Go Source: https://github.com/pilcrowonpaper/copenhagen/blob/main/pages/password-authentication.md Demonstrates how to securely compare a user-provided password hash with a stored hash using constant time comparison to prevent timing attacks. It utilizes the `crypto/subtle` package and the `golang.org/x/crypto/argon2` library. ```go import ( "crypto/subtle" "golang.org/x/crypto/argon2" ) var storedHash []byte var password []byte hash := argon2.IDKey(password, salt, 2, 19*1024, 1, 32) if subtle.ConstantTimeCompare(hash, storedHash) == 1 { // Valid password. } ``` -------------------------------- ### GitHub OAuth Callback URL Source: https://github.com/pilcrowonpaper/copenhagen/blob/main/pages/oauth.md The user is redirected to this callback endpoint with an authorization code and state parameter after successful authentication. ```APIDOC https://example.com/login/github/callback?code=&state= ``` -------------------------------- ### Session Hijacking Detection and Mitigation Source: https://github.com/pilcrowonpaper/copenhagen/blob/main/pages/sessions.md Discusses techniques to detect and mitigate session hijacking, such as tracking user agents and IP addresses, and implementing sudo mode for critical applications. ```APIDOC Session Hijacking Mitigation: Detection: - Track user agent (device) and IP address linked to the session. - Consider general area (country) instead of specific IP for mobile users. Safeguards: - Limit the number of sessions per user based on device and IP information. Recommendations: - Implement sudo mode for security-critical applications due to IP/header spoofing risks. ``` -------------------------------- ### SameSite Cookie Attribute Source: https://github.com/pilcrowonpaper/copenhagen/blob/main/pages/csrf.md This documentation entry explains the 'SameSite' cookie attribute, a crucial security measure against CSRF attacks. It details the 'Lax' and 'Strict' modes and their implications for cross-site requests. 'Lax' is recommended as a default, allowing cookies on same-site requests and cross-site GET requests, while 'Strict' prevents cookies on all cross-site requests. ```APIDOC SameSite Cookie Attribute: Purpose: Controls when cookies are sent with cross-site requests, mitigating CSRF attacks. Modes: - SameSite=Lax: - Cookies are sent on same-site requests. - Cookies are sent on cross-site requests only if the request method is safe (e.g., GET). - Recommended as a default. - SameSite=Strict: - Cookies are sent only on same-site requests. - Cookies are NOT sent on any cross-site requests. - Can impact user experience when accessing via external links. Considerations: - If using 'Lax', ensure that GET requests are not used for modifying resources. - Protects against cross-site request forgery, not cross-origin request forgery. - Browser support is high (around 96% of web users). - Should not be the sole layer of defense. ``` -------------------------------- ### Scrypt Parameters Source: https://github.com/pilcrowonpaper/copenhagen/blob/main/pages/password-authentication.md Recommended minimum parameters for the Scrypt password hashing algorithm. These parameters are crucial for effective password security. ```APIDOC Scrypt Parameters: N: 16384 r: 16 p: 1 dkLen: 64 ``` -------------------------------- ### Token Exchange with PKCE Code Verifier Source: https://github.com/pilcrowonpaper/copenhagen/blob/main/pages/oauth.md POST request to the token endpoint including the `code_verifier` parameter for PKCE flow. ```APIDOC POST https://oauth2.googleapis.com/token Accept: application/json Authorization: Basic Content-Type: application/x-www-form-urlencoded grant_type=authorization_code &client_id=<...> &redirect_uri=<...> &code=<...> &code_verifier= ``` -------------------------------- ### Bcrypt Work Factor Source: https://github.com/pilcrowonpaper/copenhagen/blob/main/pages/password-authentication.md Guidance on the work factor for Bcrypt, a widely used password hashing algorithm. It also notes input length limitations and recommendations against certain implementation practices. ```APIDOC Bcrypt: Work Factor: Minimum 10 Input Length Limit: Max 72 bytes (some implementations 50 bytes) Recommendations: - Avoid pre-hashing with SHA-256/512. - Do not use HMAC for peppering. - Consider Argon2id or Scrypt for longer passwords. ``` -------------------------------- ### Parse Attestation Object (Server-side) Source: https://github.com/pilcrowonpaper/copenhagen/blob/main/pages/webauthn.md This Go snippet demonstrates parsing a CBOR-encoded attestation object on the server-side. It includes a struct definition for the AttestationObject and checks for the 'none' attestation statement format, which is crucial for verifying the authenticity of the authenticator. ```go var attestationObject AttestationObject // Parse attestation object if attestationObject.Fmt != "none" { return errors.New("invalid attestation statement format") } type AttestationObject struct { Fmt string // "fmt" AttestationStatement AttestationStatement // "attStmt" AuthenticatorData []byte // "authData" } type AttestationStatement struct { // see spec } ``` -------------------------------- ### Other Security Considerations Source: https://github.com/pilcrowonpaper/copenhagen/blob/main/pages/password-authentication.md Additional security recommendations including password management, password change policies, and handling of open redirects. ```APIDOC Other Security Considerations: Password Copy-Pasting: Do not prevent users from copy-pasting passwords to encourage password manager use. Password Expiration: Do not require periodic password changes. Password Change: Always ask for the current password when changing. Open Redirect: Be mindful of open redirect vulnerabilities. ``` -------------------------------- ### Password Reset Entry URL Source: https://github.com/pilcrowonpaper/copenhagen/blob/main/pages/password-reset.md The initial page where users enter their email address to initiate the password reset process. ```url https://example.com/reset-password ``` -------------------------------- ### Error Handling Best Practices Source: https://github.com/pilcrowonpaper/copenhagen/blob/main/pages/password-authentication.md Guidelines for handling errors in user authentication forms to balance security and user experience. Emphasizes vague error messages for security but notes user-friendliness considerations. ```APIDOC Error Handling: General Rule: Use vague and generic error messages (e.g., "Incorrect username or password"). User Experience Consideration: - For public usernames (social media) or non-critical validity, direct messages (e.g., "Incorrect username") are acceptable. - Be aware this can aid brute-force attacks; implement proper measures. Privacy Considerations: - Avoid leaking username/email existence via registration/reset forms. - Use generic messages like "We've sent an email to your inbox..." - Include account existence info in the email itself. Timing Attacks: - Be cautious of response time differences that might reveal user existence. - Validate password only when username is valid if strictly required. ``` -------------------------------- ### Exchange Authorization Code for Access Token (GitHub) Source: https://github.com/pilcrowonpaper/copenhagen/blob/main/pages/oauth.md POST request to the token endpoint to exchange the authorization code for an access token. Requires client credentials for authentication. ```APIDOC POST https://github.com/login/oauth/access_token Accept: application/json Authorization: Basic Content-Type: application/x-www-form-urlencoded grant_type=authorization_code &client_id= &redirect_uri= &code= ``` -------------------------------- ### Verify Client Data Type Source: https://github.com/pilcrowonpaper/copenhagen/blob/main/pages/webauthn.md Verifies that the client data type is 'webauthn.get' on the server-side. ```go if clientData.Type != "webauthn.get" { return errors.New("invalid type") } ``` -------------------------------- ### Generate Random Integer (Rejection Sampling) Source: https://github.com/pilcrowonpaper/copenhagen/blob/main/pages/random-values.md Generates a random uint64 within a custom range [0, max) using rejection sampling. This is the safest approach as it avoids modulo bias by repeatedly generating values until one falls within the desired range. ```go import ( "crypto/rand" "math/big" ) func generateRandomUint64(max *big.Int) uint64 { randVal := new(big.Int) shift := max.BitLen() % 8 bytes := make([]byte, (max.BitLen() / 8) + 1) rand.Read(bytes) if shift != 0 { bytes[0] &= (1 << shift) - 1 } randVal.SetBytes(bytes) for randVal.Cmp(max) >= 0 { rand.Read(bytes) if shift != 0 { bytes[0] &= (1 << shift) - 1 } randVal.SetBytes(bytes) } return randVal.Uint64() } ``` -------------------------------- ### GitHub Authorization URL Source: https://github.com/pilcrowonpaper/copenhagen/blob/main/pages/oauth.md Constructs the authorization URL for GitHub OAuth, including client ID, redirect URI, and state parameters. The state parameter is crucial for security and session management. ```APIDOC GET https://github.com/login/oauth/authorize Parameters: response_type: code client_id: (Your application's client ID) redirect_uri: (The URI to redirect to after authorization) state: (A unique, cryptographically secure random string for session verification) ``` -------------------------------- ### Generate Server-Side Token Source: https://github.com/pilcrowonpaper/copenhagen/blob/main/pages/server-side-tokens.md Generates a server-side token using Go's crypto/rand package for cryptographically secure random bytes and encodes them using base32. This ensures sufficient entropy for token security. ```Go import ( "crypto/rand" "encoding/base32" ) bytes := make([]byte, 15) rand.Read(bytes) sessionId := base32.StdEncoding.EncodeToString(bytes) ``` -------------------------------- ### CSRF Prevention with Origin Header Source: https://github.com/pilcrowonpaper/copenhagen/blob/main/pages/csrf.md This Go code snippet demonstrates how to prevent CSRF attacks by checking the 'Origin' header of incoming requests. It ensures that non-GET requests originate from a trusted domain ('https://example.com'). If the header is missing or does not match, the request is rejected with a 403 Forbidden status. ```go func handleRequest(w http.ResponseWriter, request *http.Request) { if request.Method != "GET" { originHeader := request.Header.Get("Origin") // You can also compare it against the Host or X-Forwarded-Host header. if originHeader != "https://example.com" { // Invalid request origin w.WriteHeader(403) return } } // ... } ``` -------------------------------- ### Authenticator Selection for Passkeys Source: https://github.com/pilcrowonpaper/copenhagen/blob/main/pages/webauthn.md This snippet configures the authenticator selection for passkeys, requiring user verification and a resident key. This ensures a secure and user-friendly authentication experience for passkey-based logins. ```ts const credential = await navigator.credentials.create({ publicKey: { // ... authenticatorSelection: { userVerification: "required", residentKey: "required", requireResidentKey: true, }, }, }); ``` -------------------------------- ### Session Invalidation Strategies Source: https://github.com/pilcrowonpaper/copenhagen/blob/main/pages/sessions.md Outlines best practices for invalidating user sessions, including actions upon sign-out, permission changes, or password updates. ```APIDOC Session Invalidation: On Sign-out: Invalidate the current session on both server and client. Security-Critical Apps: Invalidate all sessions belonging to a user upon sign-out. Permission/Password Changes: Invalidate all user sessions when permissions change (e.g., email verification, new role) or when the password is changed. ``` -------------------------------- ### Brute-Force Attack Mitigation Source: https://github.com/pilcrowonpaper/copenhagen/blob/main/pages/password-authentication.md Strategies to mitigate brute-force attacks on user accounts, including Multi-Factor Authentication (MFA), IP-based throttling, identifier-based throttling, and bot detection. ```APIDOC Brute-Force Mitigation: Multi-Factor Authentication (MFA): Recommended for all applications. IP-Based Throttling: - Block IP for 10 minutes after 10 consecutive failed attempts. - Increase lockout period on each lockout. - Gradually allow new attempts at intervals. Identifier-Based Throttling: Can be used with IP-based throttling (beware of DoS). Bot Detection: Implement tests like Captchas. Password Strength: Enforce strong passwords and check against leaks. ``` -------------------------------- ### Email Verification Link Format Source: https://github.com/pilcrowonpaper/copenhagen/blob/main/pages/email-verification.md Demonstrates the standard format for an email verification link, which includes a unique, single-use token. ```APIDOC https://example.com/verify-email/ - TOKEN: A long, random, single-use token tied to a single user and email. ``` -------------------------------- ### WebAuthn Authenticator Data Parsing (Go) Source: https://github.com/pilcrowonpaper/copenhagen/blob/main/pages/webauthn.md Parses authenticator data to extract relying party ID hash, user presence, user verification flags, credential ID size, credential ID, and the COSE public key. Includes error handling for invalid data lengths and checks for specific flags. ```go import ( "bytes" "crypto/sha256" "encoding/binary" "encoding/json" "errors" ) if len(authenticatorData) < 37 { return errors.New("invalid authenticator data") } rpIdHash := authenticatorData[0:32] expectedRpIdHash := sha256.Sum256([]byte("example.com")) if bytes.Equal(rpIdHash, expectedRpIdHash[:]) { return errors.New("invalid relying party ID") } // Check for the "user present" flag. if (authenticatorData[32] & 1) != 1 { return errors.New("user not present") } // Check for the "user verified" flag if you need user verification. if ((authenticatorData[32] >> 2) & 1) != 1 { return errors.New("user not verified") } if ((authenticatorData[32] >> 6) & 1) != 1 { return errors.New("missing credentials") } if (len(authenticatorData) < 55) { return errors.New("invalid authenticator data") } credentialIdSize:= binary.BigEndian.Uint16(authenticatorData[53 : 55]) if (len(authenticatorData) < 55 + credentialIdSize) { return errors.New("invalid authenticator data") } credentialId := authenticatorData[55 : 55+credentialIdSize] coseKey := authenticatorData[55+credentialIdSize:] // Parse COSE public key ``` -------------------------------- ### Generate Random Float64 (Integer Division) Source: https://github.com/pilcrowonpaper/copenhagen/blob/main/pages/random-values.md Generates a random float64 between 0 and 1 by dividing a random integer by a large power of 2. The denominator must be large enough and a power of 2 for accurate representation. ```go func generateRandomFloat64() float64 { return float64(generateRandomInteger(1<<53)) / (1 << 53) } ``` -------------------------------- ### Verify Signature with ECDSA Source: https://github.com/pilcrowonpaper/copenhagen/blob/main/pages/webauthn.md Verifies the signature of the authenticator data and the SHA-256 hash of the client data JSON using ECDSA. ```go import ( "crypto/ecdsa" "crypto/sha256" ) clientDataJSONHash := sha256.Sum256(clientDataJSON) // Concatenate the authenticator data with the hashed client data JSON. data := append(authenticatorData, clientDataJSONHash[:]...) hash := sha256.Sum256(data) validSignature := ecdsa.VerifyASN1(publicKey, hash[:], signature) ``` -------------------------------- ### Web Storage API Security Considerations Source: https://github.com/pilcrowonpaper/copenhagen/blob/main/pages/sessions.md Highlights the risks associated with storing session IDs in Web Storage (localStorage, sessionStorage), particularly concerning XSS and supply chain attacks. ```APIDOC Web Storage API Security: Vulnerability: Storing session IDs in localStorage or sessionStorage makes them vulnerable to XSS attacks, allowing direct reading and theft. Supply Chain Attacks: Tokens can be stolen by reading entire local storage without application-specific exploits. Transmission: Session tokens can be sent via the Authorization header. Avoid sending tokens in URLs or form data. ``` -------------------------------- ### Generate TOTP Secret Key URI Source: https://github.com/pilcrowonpaper/copenhagen/blob/main/pages/mfa.md Generates a key URI for TOTP authentication, which is then encoded into a QR code. This URI contains the secret key, issuer, and other parameters required by authenticator apps. The secret key must be base32 encoded and cryptographically secure. ```text otpauth://totp/example%20app:John%20Doe?secret=JBSWY3DPEHPK3PXP&issuer=Example%20App&digits=6&period=30 ``` -------------------------------- ### Create Token Table Source: https://github.com/pilcrowonpaper/copenhagen/blob/main/pages/server-side-tokens.md SQL schema for storing tokens, including the token itself, expiration time, and associated user ID. It enforces uniqueness for tokens and a foreign key constraint for user association. ```SQL CREATE TABLE token ( token STRING NOT NULL UNIQUE, expires_at INTEGER NOT NULL, user_id INTEGER NOT NULL, FOREIGN KEY (user_id) REFERENCES user(id) ) ``` -------------------------------- ### Exchange Authorization Code for Access Token (Alternative) Source: https://github.com/pilcrowonpaper/copenhagen/blob/main/pages/oauth.md Alternative POST request to the token endpoint where client secret is included in the request body instead of the Authorization header. ```APIDOC POST https://github.com/login/oauth/access_token Accept: application/json Content-Type: application/x-www-form-urlencoded grant_type=authorization_code &client_id= &client_secret= &redirect_uri= &code= ``` -------------------------------- ### Generate Random String (Base32) Source: https://github.com/pilcrowonpaper/copenhagen/blob/main/pages/random-values.md Generates a random string by creating 12 random bytes and encoding them using Base32 standard encoding. This is a safe and easy method for generating random strings. ```go import ( "crypto/rand" "encoding/base32" ) func generateRandomString() string { bytes := make([]byte, 12) rand.Read(bytes) return base32.StdEncoding.EncodeToString(bytes) } ``` -------------------------------- ### WebAuthn Client Data Validation (Go) Source: https://github.com/pilcrowonpaper/copenhagen/blob/main/pages/webauthn.md Validates the client data JSON, checking the type, challenge, and origin against expected values. Assumes client data is base64url encoded without padding. ```go import ( "bytes" "crypto/sha256" "encoding/base64" "encoding/json" "errors" ) var expectedChallenge []byte // Verify the challenge and delete it from storage. var credentialId string var clientData ClientData // Parse JSON if clientData.Type != "webauthn.create" { return errors.New("invalid type") } if !verifyChallenge(clientData.Challenge) { return errors.New("invalid challenge") } if clientData.Origin != "https://example.com" { return errors.New("invalid origin") } type ClientData struct { Type string // "type" Challenge string // "challenge" Origin string // "origin" } ``` -------------------------------- ### Generate Random Float64 (Bit Manipulation) Source: https://github.com/pilcrowonpaper/copenhagen/blob/main/pages/random-values.md Generates a random float64 between 0 and 1 by manipulating the bits of a float64. This method generates 52 random bits for the mantissa and sets the exponent appropriately, avoiding division. ```go import ( "crypto/rand" "math" ) func generateRandomFloat64() float64 { bytes := make([]byte, 7) rand.Read(bytes) bytes = append(make([]byte, 1), bytes...) // set exponent part to 0b01111111111 bytes[0] = 0x3f bytes[1] |= 0xf0 return math.Float64frombits(binary.BigEndian.Uint64(bytes)) - 1 } ``` -------------------------------- ### Generate Random Integer (Power of 2 Range) Source: https://github.com/pilcrowonpaper/copenhagen/blob/main/pages/random-values.md Generates a random integer within a range that is a power of 2 using bit masking. This is a simple and efficient method for such ranges. ```go bytes := make([]byte, 1) rand.Read(bytes) value := bytes[0] & 0x03 // random value between [0, 3] ``` -------------------------------- ### Generate Random String (Custom Base32) Source: https://github.com/pilcrowonpaper/copenhagen/blob/main/pages/random-values.md Generates a random string using a custom Base32 encoding alphabet. This allows for more control over the characters used in the generated string. ```go import ( "crypto/rand" "encoding/base32" ) var customEncoding = base32.NewEncoding("0123456789ABCDEFGHJKMNPQRSTVWXYZ") func generateRandomString() string { bytes := make([]byte, 12) rand.Read(bytes) return customEncoding.EncodeToString(bytes) } ``` -------------------------------- ### Password Reset Link URL Source: https://github.com/pilcrowonpaper/copenhagen/blob/main/pages/password-reset.md The URL for the password reset form, which includes a password reset token in the URL path. Tokens should be valid for around an hour, and at most 24 hours. The token must be single-use. ```url https://example.com/reset-password/ ``` -------------------------------- ### Validate TOTP in Go Source: https://github.com/pilcrowonpaper/copenhagen/blob/main/pages/mfa.md Validates a Time-based One-time Password (TOTP) using the user's secret key and the current time. It implements the HOTP algorithm with HMAC SHA-1 and calculates the OTP based on the current time interval. Throttling and rate limiting are recommended for security. ```go import ( "crypto/hmac" "crypto/sha1" "encoding/binary" "fmt" "math" ) func generateTOTP(secret []byte) string { digits := 6 counter := time.Now().Unix() / 30 // HOTP mac := hmac.New(sha1.New, secret) buf := make([]byte, 8) binary.BigEndian.PutUint64(buf, uint64(counter)) mac.Write(buf) HS := mac.Sum(nil) offset := HS[19] & 0x0f Snum := binary.BigEndian.Uint32(HS[offset:offset+4]) & 0x7fffffff D := Snum % uint32(math.Pow(10, float64(digits))) // Pad "0" to make it 6 digits. return fmt.Sprintf("%06d", D) } ``` -------------------------------- ### Validate and Extend Session Lifetime Source: https://github.com/pilcrowonpaper/copenhagen/blob/main/pages/sessions.md This Go function validates a session ID, checks for expiration, and extends the session's expiry time if it's nearing its half-life. It retrieves session data from storage, checks if the session is valid and not expired, and updates the expiration if necessary. Assumes the existence of `getSessionFromStorage`, `updateSessionExpiration`, and a `Session` struct with an `ExpiresAt` field. ```go const sessionExpiresIn = 30 * 24 * time.Hour func validateSession(sessionId string) (*Session, error) { session, ok := getSessionFromStorage(sessionId) if !ok { return nil, errors.New("invalid session id") } if time.Now().After(session.ExpiresAt) { return nil, errors.New("expired session") } if time.Now().After(session.expiresAt.Sub(sessionExpiresIn / 2)) { session.ExpiresAt = time.Now().Add(sessionExpiresIn) updateSessionExpiration(session.Id, session.ExpiresAt) } return session, nil } ``` -------------------------------- ### ECDSA Public Key Formats Source: https://github.com/pilcrowonpaper/copenhagen/blob/main/pages/cryptography/ecdsa.md Details the representation of ECDSA public keys. SEC1 defines uncompressed (0x04 || x || y) and compressed (0x02 || x or 0x03 || x) formats. PKIX uses SubjectPublicKeyInfo with ASN.1 encoding. ```APIDOC ECDSA Public Key Representation: SEC1 Format: Uncompressed: Leading 0x04 byte followed by x and y encoded as big-endian bytes. Format: 0x04 || x || y Compressed: Leading 0x02 (if x is even) or 0x03 (if x is odd) byte followed by x encoded as big-endian bytes. Format: 0x02 || x or 0x03 || x PKIX Format (RFC 5480): SubjectPublicKeyInfo structure containing AlgorithmIdentifier and subjectPublicKey (SEC1 encoded). Format: SubjectPublicKeyInfo := SEQUENCE { algorithm AlgorithmIdentifier, subjectPublicKey BIT STRING } AlgorithmIdentifier for ECDSA: SEQUENCE { algorithm OBJECT IDENTIFIER (1.2.840.10045.2.1), namedCurve OBJECT IDENTIFIER (e.g., 1.2.840.10045.3.1.7 for P-256) } ``` -------------------------------- ### Generate Random Integer (Float Multiplication Bias) Source: https://github.com/pilcrowonpaper/copenhagen/blob/main/pages/random-values.md Generates a random uint32 by multiplying the maximum value by a random float. This method can also introduce bias, but it might be acceptable for small maximum values. ```go func generateRandomUint32(max uint32): uint32 { var max uint32 = 10 return uint32(max * generateRandomFloat32()) } ``` -------------------------------- ### Generate Random String (Custom Alphabet) Source: https://github.com/pilcrowonpaper/copenhagen/blob/main/pages/random-values.md Generates a random string using a custom alphabet by repeatedly selecting characters from the alphabet based on random integers. Requires a random integer generator. ```go const alphabet = "abcdefg" func generateRandomString() string { var result string for i := 0; i < 12; i ++ { result += string(alphabet[generateRandomInt(0, len(alphabet))]) } return result } ``` -------------------------------- ### Authenticator Selection for Security Tokens Source: https://github.com/pilcrowonpaper/copenhagen/blob/main/pages/webauthn.md This snippet configures the authenticator selection for security tokens, disabling user verification and resident key requirements, and specifying 'cross-platform' attachment. This is suitable for scenarios where security tokens are used and user interaction for verification is not necessary. ```ts const credential = await navigator.credentials.create({ publicKey: { // ... authenticatorSelection: { userVerification: "discouraged", residentKey: "discouraged", requireResidentKey: false, authenticatorAttachment: "cross-platform", }, }, }); ``` -------------------------------- ### COSE Public Key Structure (ECDSA) Source: https://github.com/pilcrowonpaper/copenhagen/blob/main/pages/webauthn.md Illustrates the structure of a CBOR-encoded COSE public key for ECDSA, specifying key type, algorithm, curve, and coordinates (x, y). ```json { 1: 2 // EC2 key type 3: -7 // Algorithm ID for ECDSA P-256 with SHA-256 -1: 1 // Curve ID for P-256 -2: 0x00...00 // x coordinate in bit string -3: 0x00...00 // y coordinate in bit string } ```