Authentication
FundlyHub uses AWS Cognito for identity management with httpOnly cookie-based session handling. Authentication supports email/password sign-up and Google SSO via OAuth 2.0 federation.
Session Management
After signing in, the API sets httpOnly cookies automatically. All subsequent requests are authenticated via these cookies — no need to manage tokens manually. Always include credentials: 'include' in your fetch calls.
Base URLs
| Environment | URL |
|---|---|
| Production | https://api.fundlyhub.org/api/v1 |
| Staging | https://api.staging.fundlyhub.org/api/v1 |
Sign Up (Email/Password)
POST /api/v1/cognito/signup
Register a new account. A verification code is sent to the provided email address.
Password Requirements
- Minimum 8 characters
- At least one uppercase letter
- At least one lowercase letter
- At least one number
const API_BASE = 'https://api.fundlyhub.org/api/v1';
const response = await fetch(`${API_BASE}/cognito/signup`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
body: JSON.stringify({
email: 'user@example.com',
password: 'SecureP@ssw0rd!',
name: 'John Doe'
})
});
const result = await response.json();
// { message: "Confirmation code sent to email" }Confirm Registration
POST /api/v1/cognito/confirm
Confirm account using the 6-digit verification code sent to the user's email.
const response = await fetch(`${API_BASE}/cognito/confirm`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
body: JSON.stringify({
email: 'user@example.com',
code: '123456'
})
});
// Account is now verified and ready for sign-inSign In (Email/Password)
POST /api/v1/cognito/signin
Authenticate with email and password. On success, httpOnly cookies are set automatically.
const response = await fetch(`${API_BASE}/cognito/signin`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
body: JSON.stringify({
email: 'user@example.com',
password: 'SecureP@ssw0rd!'
})
});
if (!response.ok) {
const error = await response.json();
console.error('Sign-in failed:', error.message);
throw new Error('Authentication failed');
}
const { user } = await response.json();
console.log('Signed in as:', user.name);
// Session cookies are set automatically — no manual token storage neededGoogle SSO (OAuth 2.0)
GET /api/v1/cognito/oauth/google
Initiate Google sign-in via OAuth 2.0 federation through Cognito's hosted UI at auth.fundlyhub.org.
How It Works
- Redirect the user to the Google SSO endpoint
- User authenticates with Google via
auth.fundlyhub.org - Cognito handles the OAuth callback
- Cookies are set automatically and user is redirected back to the app
// Redirect user to Google SSO
window.location.href = `${API_BASE}/cognito/oauth/google`;
// After successful auth, the user is redirected back with session cookies setINFO
Google SSO uses Cognito Federation with the branded domain auth.fundlyhub.org. No token handling is required — cookies are set during the redirect flow.
Get Current User
GET /api/v1/cognito/me 🔒 Requires Authentication
Retrieve the authenticated user's profile information.
const response = await fetch(`${API_BASE}/cognito/me`, {
credentials: 'include'
});
if (response.status === 401) {
console.log('Not authenticated');
} else {
const user = await response.json();
console.log('Current user:', user.name);
console.log('Email:', user.email);
}Refresh Session
POST /api/v1/cognito/refresh
Refresh the session tokens. This is handled automatically by the httpOnly cookies but can be called explicitly when needed.
const response = await fetch(`${API_BASE}/cognito/refresh`, {
method: 'POST',
credentials: 'include'
});
if (response.ok) {
console.log('Session refreshed');
}Sign Out
POST /api/v1/cognito/logout
Invalidate the current session and clear cookies.
const response = await fetch(`${API_BASE}/cognito/logout`, {
method: 'POST',
credentials: 'include'
});
// Session cookies are cleared — user is signed out
window.location.href = '/';Forgot Password
POST /api/v1/cognito/forgot-password
Request a password reset code sent to the user's email.
const response = await fetch(`${API_BASE}/cognito/forgot-password`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
email: 'user@example.com'
})
});
// Reset code sent to emailReset Password
POST /api/v1/cognito/reset-password
Complete the password reset using the code sent via email.
const response = await fetch(`${API_BASE}/cognito/reset-password`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
email: 'user@example.com',
code: '123456',
newPassword: 'NewSecureP@ss1!'
})
});
if (response.ok) {
console.log('Password reset successful — you can now sign in');
}Making Authenticated Requests
After signing in, include credentials: 'include' in all fetch calls. No Authorization header is needed.
// ✅ Correct — cookies handle authentication
const response = await fetch(`${API_BASE}/fundraisers/me`, {
credentials: 'include'
});
const myFundraisers = await response.json();// ✅ Correct — POST with authentication
const response = await fetch(`${API_BASE}/fundraisers`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
body: JSON.stringify({
title: 'Help Local Food Bank',
goal: 50000
})
});Security Features
| Feature | Description |
|---|---|
| httpOnly Cookies | Tokens stored in httpOnly cookies, not accessible via JavaScript |
| reCAPTCHA v3 | Bot protection on sign-up and sign-in |
| Email Verification | Required before account is fully activated (Trust Gate) |
| Rate Limiting | Brute-force protection on authentication endpoints |
| CORS | Origin-restricted requests for cross-site protection |
Response Codes
200- Success400- Validation error (missing fields, weak password)401- Invalid credentials or expired session403- Account not confirmed / Email not verified409- Email already registered429- Rate limit exceeded (too many attempts)500- Server error