Welcome to spin_auth for mod_spin from Rexursive ================================================ This application provides convenient authentication bridge for other mod_spin applications. It doesn't in itself do any authentication - instead it uses basic Apache authentication mechanisms to do that. Its role is confined to conversion of parameters supplied on an (X)HTML form into what Apache basic authentication can understand, and to manipulation of a variable inside the session state file used to communicate success/failure of authentication to the application using this provider. It goes without saying that sessions need to be enabled (i.e. SpinCookie configuration parameter needs to be set and user agent needs accept cookies) for all resources that are to be protected. IMPORTANT NOTE: =============== This authentication provider only works with resources under mod_spin applications that have been explicitly written for this authentication mechanism. Any attempt to protect other resources will be unsuccessful. You must configure mod_spin as a handler for the auth_URL location. Configuring mod_spin as a filter for this location won't work. --------------- The authentication application will look for two form parameters: spin_username and spin_password. If it finds them, it will create an internal subrequest (using GET method), to a URI specified in the configuration file (auth_URI), with basic authentication headers calculated from the above form parameters. If this subrequest is successful (i.e. the return code is 200), it will write a value of spin_username for the key auth_user into the current session state file. In all other cases, it will delete that key from the session file. It will also write auth_time into the session state file, or delete it if authentication was unsuccessuful. Please note that this subrequest never runs the handler, only the hooks that fall under ap_process_request_internal() call. If spin_username and/or spin_password aren't found, regular template processing occurs. Meaning, you get the login page, designed to your liking (that's the auth_URL page, see below). The auth_failed reference will be in the context if the authentication previously failed for this session, so it is easy to notify users on the login page (see example below). During this regular template processing, a session variable auth_return (which is the return URL) is checked to see if has been set before (either by this authenticaton application or by the application being authenticated). If it hasn't, a parameter named return will be taken as the return URL and stored in session variable auth_return. Note that it may not be practical for the application being authenticated to store auth_return, as it may not have a valid session at that point. That is the purpose of the return parameter - to facilitate return URL without the need to have an initially valid session in the application that is being authenticated. Obviously, the auth_URI has to be a real URI that has basic Apache authentication configured. For all intents and purposes, the request to this URI will come from the real client, using internal Apache request machinery. Both successful and unsuccessful authentication will redirect back to the the return URL (auth_return), via an external redirect (303: SEE OTHER), using the GET method. Keep in mind that it is the responsibility of the application that is using this mechanism to remember any parameters originally received in the GET/POST method. Without the return URL, this application will produce code 500: INTERNAL SERVER ERROR and will not authenticate at all. Applications using this authentication provider should do the following to verify user authenticity: 1. Attempt to get the value of 'auth_user' from the session state file. If it exists, the user should be considered authenticated. 2. If auth_user doesn't exisit, user should be redirected to an authentication URL (auth_URL), the one behind which authentication provider application is configured. Following the above algorithm for the authenticaton application, user will be stuck in the authentication loop until she can provide a successful username/password combination. Variables ========= Application variable auth_URL is the URL used for authentication. It is the URL that the application should redirect to unless it can find auth_user in the session store. The value should be specified in the application configuration file (XML). Application variable auth_URI is where you configured basic Apache authentication which will be used by this authentication application to verify usernames and passwords. Session variable auth_user is set to the value of authenticated user. If the user cannot be authenticated, this variable won't exist in the session store. Session variable auth_time is the timestamp (64-bit APR time, as the number of microseconds since 00:00 on 1 Jan 1970 UTC, printed using APR_TIME_T_FMT format) when the authentication occured. Application can arbitrarily enforce login timeouts based on this variable. Session variable auth_failed will be non-NULL if any authentication before the current attempt failed. It can be used in the authentication template, the (X)HTML, to notify the user that the previous authentication attempt failed. Session variable auth_return contains return URL. The place to go after this authentication application finished with its business. Encryption ========== It is highly recommended that both auth_URL and auth_URI be resources that are only available via SSL/TLS. Otherwise, a mistaken attempt to authenticate over an unecrypted line can lead to username and/or password disclosure. Even applications that do not need encryption can use auth_URL and auth_URI over SSL/TLS. That is because once the users are authenticated, their identity is confirmed through the valid session id, which is reasonably difficult to fake as it is "signed" by an MD5 checksum of the id and a secret salt. Example configuration ===================== This is what Apache configuration would look like: SpinApplication /usr/local/libexec/spinapps/spin_auth.so SpinAppConfig /usr/local/etc/spinapps/spin_someapp.xml SpinStore sqlite3:/var/tmp/someapp/store.db SpinCookie SpinSession The above is the configuration of auth_URL. What follows is the configuration of auth_URI: AuthType Basic AuthName "Restricted Files" AuthUserFile /usr/local/apache2/auth.users Require valid-user Please note that auth.sm has to be a proper (X)HTML file like this: Authentication

Login:

#if(${auth_failed})

Previous authentication attempt failed. Please try again.

#end
Username:
Password:
 
The auth_URI file only has to exist (in order to avoid 404: NOT FOUND). Otherwise, it can be an empty file. In fact, if you want to prevent logins altogether, you can simply remove that file. IMPORTANT: If you don't configure Apache basic authentication correctly for auth.html, ALL USERS WILL BE ABLE TO LOGIN, no matter what username and password they supply. TEST YOUR SETUP BEFORE GOING LIVE! Application configuration file would then contain the following parameters (among others): ]> https://www.example.com/auth.sm /auth.html Example code ============ Below is the sample code that an application using this authentication mechanism could use for any mod_spin resource it wants to protect: *************** ** IMPORTANT ** *************** For mod_spin 1.0.x branch, there is no prepare stage, so the code would simply be put in rxv_spin_service() function. *************** int rxv_spin_prepare(rxv_spin_ctx_t *ctx){ char *auth_URL,*user=NULL; request_rec *r=ctx->r; /* if there is authentication configuration, use it */ if((auth_URL=rxv_spin_app_strget(ctx,"auth_URL"))){ if(!(user=rxv_spin_ses_strget(ctx,"auth_user"))){ char *full_URL,*this_URL; /* full URL is auth_URL + return URL */ if(!((this_URL=ap_construct_url(r->pool,r->parsed_uri.path,r)) && (full_URL=apr_pstrcat(r->pool,auth_URL,"?return=",this_URL,NULL)))) return HTTP_INTERNAL_SERVER_ERROR; apr_table_add(r->err_headers_out,"Location",full_URL); return HTTP_SEE_OTHER; } } return OK; } Obviously, you may want to extend the above code with some logging or maybe even something more fancy, but the general idea remains the same. The above code is executed as the prepare function, so it will work even for resources that are not handled by mod_spin handler, but fall under the mod_spin application umbrella (this feature not available in mod_spin 1.0.x).