FastCGI implementation in OCaml
1(** Authorizer role implementation for FastCGI. 2 3 The Authorizer role performs access control decisions for web requests. 4 An Authorizer FastCGI application receives all the information associated 5 with an HTTP request and generates an authorized/unauthorized decision. 6 7 In case of an authorized decision, the Authorizer can associate name-value 8 pairs with the HTTP request for use by subsequent processing stages. When 9 giving an unauthorized decision, the Authorizer sends a complete response 10 to the HTTP client with appropriate error information. 11 12 This role is commonly used for: 13 - Authentication and authorization checks 14 - Access control based on IP addresses, user roles, or request attributes 15 - Rate limiting and quota enforcement 16 - Custom security policies 17 18 The web server may proceed with additional access checks after a successful 19 authorization, including requests to other Authorizers, depending on its 20 configuration. *) 21 22(** {1 Authorization Types} *) 23 24(** Authorization result. 25 26 Represents the outcome of an authorization decision. The Authorizer can 27 either grant access (possibly with additional variables) or deny access 28 with a complete error response. *) 29type auth_result = 30 | Authorized of (string * string) list (** Request is authorized. The list contains 31 variable bindings that will be added to 32 the request environment for subsequent 33 processing stages. *) 34 | Unauthorized of { 35 status : int; (** HTTP status code for the error response 36 (typically 401, 403, or 429). *) 37 headers : (string * string) list; (** HTTP headers for the error response. 38 May include WWW-Authenticate, etc. *) 39 body : string; (** Error response body content sent to the client. *) 40 } (** Request is denied. The web server will send this error 41 response directly to the client without further processing. *) 42 43(** Authorization request information. 44 45 Contains the relevant information from an HTTP request needed to make 46 authorization decisions. This is extracted from the CGI environment 47 variables provided by the web server. *) 48type auth_request = { 49 method_ : string; (** HTTP method (GET, POST, etc.). *) 50 uri : string; (** Request URI being accessed. *) 51 remote_addr : string option; (** Client IP address, if available. 52 Useful for IP-based access control. *) 53 remote_user : string option; (** Authenticated username, if any. 54 Set by prior authentication stages. *) 55 auth_type : string option; (** Authentication method used (Basic, Bearer, etc.). 56 Indicates how the user was authenticated. *) 57 headers : (string * string) list; (** HTTP headers from the request. 58 May contain authorization headers, user agents, etc. *) 59} 60 61(** {1 Conversion Functions} *) 62 63(** Convert FastCGI request to authorization request. 64 65 Extracts authorization-relevant information from FastCGI 66 parameters and creates an auth request object. 67 68 @param request FastCGI request 69 @return Authorization request *) 70val request_of_fastcgi : 'a Fastcgi_types.request -> auth_request 71 72(** Convert authorization result to FastCGI response. 73 74 Writes the authorization decision to the FastCGI response 75 streams in the correct format. 76 77 @param result Authorization decision 78 @param response FastCGI response 79 @return Response result *) 80val response_of_result : auth_result -> 'a Fastcgi_types.response -> Fastcgi_types.response_result 81 82(** {1 Handler Utilities} *) 83 84(** Authorizer handler type. *) 85type 'a authorizer_handler = 'a Fastcgi_types.request -> 'a Fastcgi_types.response -> Fastcgi_types.response_result 86 87(** Convenience handler wrapper for authorization handlers. 88 89 Converts an authorization handler function into a FastCGI handler. 90 This allows writing handlers that work with auth request/result 91 types instead of raw FastCGI types. 92 93 @param handler Authorization handler function 94 @return FastCGI authorizer handler *) 95val auth_handler : 96 (auth_request -> auth_result) -> 97 'a authorizer_handler 98 99(** {1 Common Authorization Patterns} *) 100 101(** Create a simple allow/deny authorizer. 102 103 @param predicate Function that returns true for authorized requests 104 @return Authorization result *) 105val simple_authorizer : (auth_request -> bool) -> (auth_request -> auth_result) 106 107(** IP-based authorization. 108 109 @param allowed_ips List of allowed IP addresses/ranges 110 @param request Authorization request 111 @return Authorization result *) 112val ip_authorizer : string list -> auth_request -> auth_result 113 114(** User-based authorization. 115 116 @param allowed_users List of allowed usernames 117 @param request Authorization request 118 @return Authorization result *) 119val user_authorizer : string list -> auth_request -> auth_result 120 121(** Role-based authorization. 122 123 @param get_user_roles Function to get roles for a user 124 @param required_roles Roles required for access 125 @param request Authorization request 126 @return Authorization result *) 127val role_authorizer : 128 get_user_roles:(string -> string list) -> 129 required_roles:string list -> 130 auth_request -> 131 auth_result 132 133(** Time-based authorization. 134 135 @param allowed_hours List of allowed hours (0-23) 136 @param request Authorization request 137 @return Authorization result *) 138val time_authorizer : int list -> auth_request -> auth_result 139 140(** {1 Authentication Integration} *) 141 142(** Basic authentication handler. 143 144 @param realm Authentication realm 145 @param verify_credentials Function to verify username/password 146 @param request Authorization request 147 @return Authorization result *) 148val basic_auth : 149 realm:string -> 150 verify_credentials:(string -> string -> bool) -> 151 auth_request -> 152 auth_result 153 154(** Bearer token authentication. 155 156 @param verify_token Function to verify and decode token 157 @param request Authorization request 158 @return Authorization result *) 159val bearer_auth : 160 verify_token:(string -> (string * (string * string) list) option) -> 161 auth_request -> 162 auth_result 163 164(** API key authentication. 165 166 @param header_name Header containing API key 167 @param verify_key Function to verify API key 168 @param request Authorization request 169 @return Authorization result *) 170val api_key_auth : 171 header_name:string -> 172 verify_key:(string -> (string * (string * string) list) option) -> 173 auth_request -> 174 auth_result 175 176(** {1 Response Helpers} *) 177 178(** Create a standard 401 Unauthorized response. 179 180 @param realm Authentication realm 181 @param message Error message 182 @return Unauthorized result *) 183val unauthorized_response : 184 realm:string -> 185 message:string -> 186 auth_result 187 188(** Create a standard 403 Forbidden response. 189 190 @param message Error message 191 @return Unauthorized result *) 192val forbidden_response : 193 message:string -> 194 auth_result 195 196(** Create a custom error response. 197 198 @param status HTTP status code 199 @param headers Additional headers 200 @param body Response body 201 @return Unauthorized result *) 202val error_response : 203 status:int -> 204 headers:(string * string) list -> 205 body:string -> 206 auth_result 207 208(** {1 Variable Binding} *) 209 210(** Create authorized response with variables. 211 212 Variables are passed to subsequent FastCGI applications 213 as environment variables with "Variable-" prefix. 214 215 @param variables Name-value pairs to bind 216 @return Authorized result *) 217val authorized_with_variables : (string * string) list -> auth_result 218 219(** Add authentication information as variables. 220 221 @param user Authenticated username 222 @param auth_type Authentication method 223 @param additional Additional variables 224 @return Variable bindings *) 225val auth_variables : 226 user:string -> 227 auth_type:string -> 228 additional:(string * string) list -> 229 (string * string) list