LPS:Java-idp-webauth-login-handler
Webauth Login Handler
WebAuth is an authentication system for web pages and web applications. If we want use Webauth as login service for our IdP realm. We want to use it like RemoteUserLoginHandler. Webauth WAS module (mod_webauth) which handles authentication of user based on cookie token webauth_at sets environment variable REMOTE_USER/WEBAUTH_USER for backend application engine (eg. IdP). But it's SSO, and by default RemoteUser cann't do force authentication by itself.
ForceAuthn [Optional] 2042 A Boolean value. If "true", the identity provider MUST authenticate the presenter directly rather than 2043 rely on a previous security context. If a value is not provided, the default is "false". However, if both 2044 ForceAuthn and IsPassive are "true", the identity provider MUST NOT freshly authenticate the 2045 presenter unless the constraints of IsPassive can be met.
Overview
Authentication tokens generated by mod_webauth and mod_webkdc are of certain properties. For normal requests, we find any valid webauth token as sufficient authentication for IdP. In case of ForceAuthn request to IdP, we need login handler to force user to get a token with a specific properties. We consider valid ForceAuthn token that is:
- based on knowledge of login/password
- not older than X seconds
- not used in IdP before (eg. not presenting any previous security context ;)
All token constraints are validated in WebauthAuthServlet.java:service(..). We followed this path:
/** Webauth Login function * * when force auth is requested we consider several use cases: * * 1) client was authenticated to IDP mod_webauth by SSO weblogin token (WEBAUTH_SESSION_FACTORS == c) * >> we need to force reauth on weblogin * * 2) client was authenticated to IDP mod_webauth by weblogin by password (WEBAUTH_SESSION_FACTORS == p) * but a long time ago, most likely that IDP is first requested resource in WebAuth SSO domain * >> we need to force reauth on weblogin if webauth_at is older than X minutes * * 3) client was authenticated to IDP mod_webauth by weblogin by password (WEBAUTH_SESSION_FACTORS == p) * short time ago, but still we "MUST NOT rely on previous security context" * http://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf * so we'll check all services the user is logged in, and insist that WEBAUTH_TOKEN_CREATION is newer * also, if idpSession not exists (but new token is presented) or list of used services is empty * >> we need to force reauth on weblogin if webauth_at is not newer or sufficient ... * * 4) client was reauthenticated to another application within same FQDN as IDP (cookie: webauth_at;domain=FQDN;path=/) * - tokens has (WEBAUTH_SESSION_FACTORS == p); * - token is new (age < X minutes) * - is newer than any other login to any service * >> we can manage that IDP doesn't not share webauth login context (eg. webauth_at cookie scope) * with any other application * * 5) client was reauthenticated to another application within WebSSO domain (not related to IDP was in any way) * so, token is new, based od password and is newer than IDP saw a last time * - tokens has (WEBAUTH_SESSION_FACTORS == p); * - token is new (age < X minutes) * - is newer than any other login to any service * >> this is not the case, since webauth_at is not shared among different FQDNs * * so we want: * 1) - WEBAUTH_SESSION_FACTORS == p; any other factor is considered not sufficient * we consider "p" and only "p" secure method of auth, we don't oxkm anyway, but that might not be fine for other sites (TODO) * * 2) - WEBAUTH_TOKEN_CREATION must be new, not older than X minutes * IDP can be first WAS authenticated in browser, so token can be P but very old ... * * 3) - WEBAUTH_TOKEN_CREATION > any login time to any service * (saml specification -- not rely on previous sec context -- webauth_at) * * * 4) - there is no other application on IDP FQDN * this is a deployment constraint * */
Theese steps should lead to situation, that for old security context Shibboleth and Webauth asks user for a login/password. Which we consider as reauthentication. We did not consider other auth factors as sufficient, as some of them might be...
For the other factors, at least with the current implementation you can treat WEBAUTH_SESSION_FACTORS of o as being equivalent to p for your purposes; those will only be expressed if the user just authenticated with a one-time password. x is a little trickier, since in theory that could mean authenticating with a certificate cached in their browser, which may not constitute forced authentication for your purposes, but I'd be inclined to allow it as well. m and k should not count as authentications for this purpose. Note that it's theoretically possible (although it won't happen in the current available code paths) for WEBAUTH_SESSION_FACTORS to be set to something like p,c,m. I think that should probably also count as p for your purposes (and the redirect helper would pass it, so it probably has to or you'll just get a loop). This can happen when the user has a single sign-on cookie that says they authenticated with OTP or some other method but then you forced password authentication. So if you're not already, you probably want to split on comma and then see if p is included, rather than checking whether the string is exactly equal to p. These are all minor bits, though. The basic idea is great. I didn't look at the source, but everything seems fine from the description. -- Russ Allbery <eagle@windlord.stanford.edu>
we will address these issues in the next release ...
Requirements
- IdP must be only application in webauth_at cookie scope (have it's own FQDN)
- IdP webcontainer must be bind behind httpd through mod_jk
- Webauth Authentication module on httpd
- Webauth >= 4.x
Installation and configuration
- get the source code and build IdP module
- install and configure handler
- configure handler/authentication servlet
- configure webauth reauth helper (session factors requester)
Download and build
Download and build the source (replace X.0 with the last stable version, e.g.: "tags/1.0"):
git clone https://home.zcu.cz/~bodik/java-idp-webauth-login-handler cd java-idp-webauth-login-handler mvn package
Install and configure handler
Copy the .jar file to the installation folder:
cp target/webauth-login-handler-X.0.jar $IDP_INSTALL_DIR/lib
handler.xml configuration
Configure the handler.xml at:
- new install: $IDP_INSTALL_DIR/src/installer/resources/conf-tmpl/handler.xml
- reinstall: $IDP_DIR/conf/handler.xml
<ph:ProfileHandlerGroup xmlns:ph="urn:mace:shibboleth:2.0:idp:profile-handler" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" (...) xmlns:webauth="http://support.zcu.cz/java-idp-webauth-login-handler" <<<<< (...) xsi:schemaLocation=" urn:mace:shibboleth:2.0:idp:profile-handler classpath:/schema/shibboleth-2.0-idp-profile-handler.xsd http://support.zcu.cz/java-idp-webauth-login-handler classpath:/schema/webauth-login-handler.xsd <<<<< (...) "> (...) <ph:LoginHandler xsi:type="webauth:Webauth"> <<<<< <ph:AuthenticationMethod>urn:oasis:names:tc:SAML:2.0:ac:classes:Webauth</ph:AuthenticationMethod> <<<<< </ph:LoginHandler> <<<<< (...) </ph:ProfileHandlerGroup>
Configure authentication servlet
In the web-application you have to enable the Webauth login servlet. You do that in $IDP_INSTALL_DIR/src/main/webapp/WEB-INF/web.xml:
<webapp> (...) <servlet> <servlet-name>WebauthAuthServlet</servlet-name> <servlet-class>cz.zcu.civ.idp.webauth.WebauthAuthServlet</servlet-class> <init-param> <param-name>reauthURL</param-name> <param-value>https://IDP-FQDN/wareauth</param-value> </init-param> <init-param> <param-name>maxTokenAge</param-name> <param-value>10</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>WebauthAuthServlet</servlet-name> <url-pattern>/Authn/Webauth</url-pattern> </servlet-mapping> (...) </webapp>
Reauth helper and mod_jk reverse proxy
- reauth url must be within the same webauth_at context, as we need to be able to delete it from IdP application/module ...
- j2ee container must be bind behind httpd through mod_jk
Following example has to be placed somewhere in httpd.confs ...
# env variables propagated thgough mod_jk JkEnvVar WEBAUTH_USER "<UNSET>" JkEnvVar REMOTE_USER "<UNSET>" JkEnvVar AUTH_TYPE "<UNSET>" JkEnvVar WEBAUTH_TOKEN_CREATION "<UNSET>" JkEnvVar WEBAUTH_TOKEN_EXPIRATION "<UNSET>" JkEnvVar WEBAUTH_FACTORS_INITIAL "<UNSET>" JkEnvVar WEBAUTH_FACTORS_SESSION "<UNSET>" JkEnvVar WEBAUTH_LOA "<UNSET>" # IdP application url binding JkMount /idp/* worker <Location /idp/> AuthType WebAuth require valid-user </Location> # reauth helper <Location /wareauth> AuthType WebAuth require valid-user # WA4 WebAuthRequireSessionFactor p RewriteEngine on RewriteRule .* https://IDP-FQDN/idp/Authn/Webauth [R,L] </Location>
Log configuration
The logging for the Handler is configured in the logging.xml file. It can be found at:
- new install: $IDP_INSTALL_DIR/src/installer/resources/conf-tmpl/logging.xml
- reinstall: $IDP_DIR/conf/logging.xml
(...) <logger name="cz.zcu.civ.idp.webauth"> <level value="DEBUG"/> </logger> (...)
Deployment
Backup the IdP configuration before re-deploying the application:
$IDP_INSTALL_DIR/install.sh
Known bugs
- Algorithm is not working if WebKDC clocks skew just behind IdP, authentication failes.
- If browser is not respecting cookie webauth_at deletion request from server, then it falls in endless redirects, with no auth.
Troubleshooting
- Project page (bugs, features): http://support.zcu.cz/java-idp-webauth-login-handler
- Contact for comments/questions: bodik@civ.zcu.cz, paja@civ.zcu.cz