Authentication
JWT Implementation
The API uses JSON Web Tokens (HS256) for authentication. The JWT library is vendored at api/libs/php-jwt-master/ (Firebase PHP-JWT).
Token Structure
{
"iat": 1700000000,
"iss": "https://api.myhousr.com/api/",
"data": {
"id": "123"
}
}iat- Issued at (Unix timestamp)iss- Issuer (alwayshttps://api.myhousr.com/api/)data.id- The user’s database ID
Note: Tokens have no expiry (exp) claim. They remain valid indefinitely unless the signing key changes.
Signing Key
The signing key is defined in api/include/core.php:
$key = "example_key";This is a global variable available to all endpoint files via the bootstrap chain.
Token Generation
Tokens are created during login, signup, and social auth flows:
$token = array(
"iat" => $issued_at,
"iss" => $issuer,
"data" => array(
"id" => $userId,
)
);
$jwt = JWT::encode($token, $key);Token Validation
Endpoints validate tokens in two ways:
1. Direct Decode (most endpoints)
The endpoint manually decodes the JWT from $_POST["jwt"]:
$jwt = isset($_POST["jwt"]) ? $_POST["jwt"] : "";
$decoded = JWT::decode($jwt, $key, array('HS256'));
$userId = $decoded->data->id;If the token is invalid, JWT::decode() throws an exception. Endpoints typically catch this and return 401.
2. Utility Functions (newer endpoints)
api/utils/jwtUtils.php provides helper functions:
// Required auth - returns user ID or dies with 401
$userId = getUserId($jwt);
// Optional auth - returns user ID or null
$userId = getOptionalUserId($jwt);Token Delivery
The JWT is passed to the API in two ways:
-
POST body field (legacy pattern, most endpoints):
POST /api/houses.php Content-Type: application/x-www-form-urlencoded jwt=eyJ... -
Authorization header (newer endpoints like
viewings.php,getBillsData.php):GET /api/viewings.php Authorization: eyJ...Note: No
Bearerprefix is used. The raw JWT is sent directly in the Authorization header.
Auth Patterns by Endpoint Type
| Pattern | Example | Description |
|---|---|---|
| Required POST | chatRooms.php | JWT in POST body, 401 if missing/invalid |
| Required Header | viewings.php | JWT in Authorization header, 401 if missing |
| Optional | getHouse.php | Works without JWT; shows extra data (likes, friends) when authenticated |
| Public | featureFlags.php, cities.php | No auth required |
| API Key | External endpoints | Uses apiKeyChecker.php to validate API keys from api_keys table |
SSO Authentication (US)
US university users authenticate via SAML SSO using SimpleSAMLphp:
api/sso_login.php- Initiates SAML auth flow, redirects to university IdP- After IdP callback, a temporary JWT is created containing SAML attributes
api/sso_auth.php- Receives the temporary JWT, extractscollegeUID, looks up or creates the user, returns a standard app JWT
The SAML configuration lives in the saml/ directory and SimpleSAMLphp is installed at /var/www/simplesamlphp in the container.
Social Authentication
- Apple Sign-In (
appleSignin.php) - Receives AppleuserID, looks up user byappleIDcolumn - Google Sign-In (
googleSignin.php) - Receives Google credentials, verifies via Google API client - Facebook Sign-In (
facebookSignin.php) - Receives Facebook credentials
All social auth endpoints follow the same pattern: look up existing user by provider ID, create if not found, return JWT.
OTP (One-Time Password)
Used for password reset and phone verification:
send_otp.php- Generates a 6-digit OTP, stores it in theuserstable (otp,otp_create_at,otp_is_expiredcolumns), sends via Twilio SMSverify_otp.php- Validates the OTPsignUpOtp.php- OTP during signup flow