{"id":234,"date":"2012-11-18T08:34:30","date_gmt":"2012-11-18T08:34:30","guid":{"rendered":"http:\/\/www.softwareeverydayblog.com\/?p=234"},"modified":"2014-04-27T21:03:32","modified_gmt":"2014-04-27T21:03:32","slug":"playing-with-jaas-and-apache","status":"publish","type":"post","link":"https:\/\/www.softwareeverydayblog.com\/?p=234","title":{"rendered":"Playing with Jaas and Apache."},"content":{"rendered":"<p>If you havent read my blog post &#8220;<a href=\"https:\/\/www.softwareeverydayblog.com\/?p=139\" title=\"Playing with JAAS\">Playing with JAAS<\/a>&#8221; i wouldd suggest you read that before reading this one. Here is a quick primer on configuring Jaas with apache.<\/p>\n<ul>\n<li>In this case our jaas.config will have just one LoginContext called ApacheExample\n<pre lang=\"text\">\r\nApacheExample {\r\n\tcom.module.DummyLoginModule required username=\"user\" password=\"pass\" role=\"admin\";\r\n};\r\n<\/pre>\n<\/li>\n<li>As part of the login process, JAASRealm registers its own CallbackHandler, called (unsurprisingly) <a href=\"http:\/\/tomcat.apache.org\/tomcat-5.5-doc\/catalina\/docs\/api\/org\/apache\/catalina\/realm\/JAASCallbackHandler.html\">JAASCallbackHandler<\/a>. This handler supplies the HTTP requests&#8217;s username and credentials to the user-supplied LoginModule. At present, JAASCallbackHandler knows how to handle callbacks of type <a href=\"http:\/\/docs.oracle.com\/javase\/7\/docs\/api\/javax\/security\/auth\/callback\/NameCallback.html\" title=\"NameCallback\" target=\"_blank\">NameCallback<\/a> and <a href=\"http:\/\/docs.oracle.com\/javase\/7\/docs\/api\/javax\/security\/auth\/callback\/PasswordCallback.html\" title=\"PasswordCallback\" target=\"_blank\">PasswordCallback<\/a>.<br \/>\n&nbsp;<br \/>\nHere is the login method of our DummyLoginModule. As soon as the user would click on &#8216;Login&#8217; button on the UI, the login method of this DummyLoginModule is called. Within the login method we call the callbackhandler&#8217;s handle method (callbackHandler.handle(&#8230;)) which would expect JAASCallbackHandler to populate NameCallback and PasswordCallback objects.<\/p>\n<p>On success we create the HelloWorldUser and HelloWorldRole which we will use later. Both implement <a href=\"http:\/\/docs.oracle.com\/javase\/1.4.2\/docs\/api\/java\/security\/Principal.html\">Principal<\/a>.<\/p>\n<pre lang=\"java\" line=\"1\">\r\npublic boolean login() throws LoginException {\r\n\r\n\tif ( callbackHandler == null ) {\r\n\t\tthrow new LoginException(\"no handler\");\r\n\t}\r\n\t\t\r\n\t\/\/ Callback is just like a VO object, that the handler will populate!\r\n\tNameCallback nameCallback=new NameCallback(\"username\");\r\n\tPasswordCallback passwordCallback=new PasswordCallback(\"password\", false);\r\n\tCallback[] callbacks = new Callback[] { nameCallback, passwordCallback };\r\n\t\t\r\n\ttry {\r\n\t\tcallbackHandler.handle(callbacks);\t\t\r\n\t} catch (IOException e) {\t\t\t\r\n\t\tthrow new LoginException(\"handler io error\");\r\n\t} catch (UnsupportedCallbackException e) {\t\t\r\n\t\tthrow new LoginException(\"unsupported callback error\");\r\n\t}\r\n\t\t\r\n\tString username = nameCallback.getName();\r\n\tString password = new String(passwordCallback.getPassword());\r\n\t\t\r\n\tif ( options.get(\"username\").equals(username) && options.get(\"password\").equals(password) ) {\t\t\t\r\n\t\t\/\/ add these if commit was called!\r\n\t\tmyUser=new HelloWorldUser(username);\r\n\t\tmyRole=new HelloWorldRole(String.valueOf(options.get(\"role\")));\t\t\t\r\n\t\tsuccess = true;\t\t\t\t\r\n\t} else {\t\t\t\r\n\t\tthrow new LoginException(\"incorrect username\/password\");\r\n\t}\r\n\t\t\r\n\treturn true;\r\n}\r\n<\/pre>\n<\/li>\n<li>You can download the whole JAAS implementation from here [<a href=\"https:\/\/www.softwareeverydayblog.com\/wp-content\/uploads\/2012\/11\/MyHelloWorldApacheJaas.zip\">Source<\/a>] or the [<a href=\"https:\/\/www.softwareeverydayblog.com\/wp-content\/uploads\/2012\/11\/MyTestRealm.zip\">binary which is jar+jaas.config<\/a>]. Place the jar and jaas.config into your lib folder.<\/li>\n<li>Apache uses <a href=\"http:\/\/tomcat.apache.org\/tomcat-7.0-doc\/realm-howto.html\">realms<\/a> to authenticate users. By default its set to <a href=\"http:\/\/tomcat.apache.org\/tomcat-7.0-doc\/realm-howto.html#UserDatabaseRealm\">UserDatabaseRealm<\/a> which authenticates users from the conf\/tomcat-users.xml. We need to switch that to <a href=\"http:\/\/tomcat.apache.org\/tomcat-7.0-doc\/realm-howto.html#JAASRealm\">JAASRealm<\/a> in the conf\/server.xml. Locate Realm element with class=org.apache.catalina.realm.UserDatabaseRealm, comment it out and add the following realm code.\n<pre lang=\"xml\" line=\"1\">\r\n<Realm className=\"org.apache.catalina.realm.JAASRealm\"\r\n                appName=\"ApacheExample\"\r\n\t\t\t\t\tuserClassNames=\"com.principal.HelloWorldUser\"\r\n\t\t\t\t\t\troleClassNames=\"com.principal.HelloWorldRole\"\/>\r\n<\/pre>\n<\/li>\n<li>You need to make changes in your webapps web.xml to specify &#8220;login-config&#8221; and &#8220;security-constraint&#8221; elements (which are out of scope of this article). Here is a good article explaining <a href=\"http:\/\/www.cafesoft.com\/products\/cams\/tomcat-security.html\">Tomcat Security Overview and Analysis<\/a>. Here is a sample web.xml for our helloworld webapp. You can download the <a href=\"https:\/\/www.softwareeverydayblog.com\/wp-content\/uploads\/2012\/11\/helloworld.zip\">sample helloworld apache jaas webapp<\/a> from here. Notice how we have added the &#8220;role-name&#8221; element with value &#8220;admin&#8221; under the &#8220;auth-constraint&#8221; element. This means that the subject who was authenticated has to have a admin role. We are taking care of that in our jaas implementation by adding HelloWorldRole as one of our Principals in our Subject.\n<pre lang=\"xml\" line=\"1\">\r\n<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\r\n<web-app xmlns=\"http:\/\/java.sun.com\/xml\/ns\/j2ee\"\r\n    xmlns:xsi=\"http:\/\/www.w3.or<a href='https:\/\/www.softwareeverydayblog.com\/wp-content\/uploads\/2012\/11\/helloworld.zip'>Apache+Jaas helloworld app<\/a>g\/2001\/XMLSchema-instance\"\r\n    xsi:schemaLocation=\"http:\/\/java.sun.com\/xml\/ns\/j2ee http:\/\/java.sun.com\/xml\/ns\/j2ee\/web-app_2_5.xsd\"\r\n    version=\"2.5\">\r\n    <description>Hello World<\/description>\r\n    <display-name>Hello World<\/display-name>\r\n\r\n\t<context-param>\r\n\t\t<param-name>Name<\/param-name>\r\n\t\t<param-value>Hello World<\/param-value>\r\n\t<\/context-param>\r\n\r\n\t<security-constraint>\r\n\t\t<web-resource-collection>\r\n\t\t\t<web-resource-name>Wildcard means whole app requires authentication<\/web-resource-name>\r\n\t\t\t<url-pattern>\/*<\/url-pattern>\r\n\t\t\t<http-method>GET<\/http-method>\r\n\t\t\t<http-method>POST<\/http-method>\r\n\t\t<\/web-resource-collection>\r\n\t\t\r\n\t\t<auth-constraint>\r\n\t\t\t<role-name>admin<\/role-name>\r\n\t\t<\/auth-constraint>\r\n\r\n\t\t<user-data-constraint>\r\n\t\t\t<!-- transport-guarantee can be CONFIDENTIAL, INTEGRAL, or NONE -->\r\n\t\t\t<transport-guarantee>NONE<\/transport-guarantee>\r\n\t\t<\/user-data-constraint>\r\n\t<\/security-constraint>\r\n\r\n\t<login-config>\r\n\t\t<auth-method>FORM<\/auth-method>\r\n\t\t<form-login-config>\r\n\t\t<form-login-page>\/login.jsp<\/form-login-page>\r\n\t\t<form-error-page>\/fail_login.html<\/form-error-page>\r\n\t\t<\/form-login-config>\r\n\t<\/login-config>\r\n\r\n<\/web-app>\r\n<\/pre>\n<\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>If you havent read my blog post &#8220;Playing with JAAS&#8221; i wouldd suggest you read that before reading this one. Here is a quick primer on configuring Jaas with apache. In this case our jaas.config will have just one LoginContext called ApacheExample ApacheExample { com.module.DummyLoginModule required username=&#8221;user&#8221; password=&#8221;pass&#8221; role=&#8221;admin&#8221;; }; As part of the login [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-234","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/www.softwareeverydayblog.com\/index.php?rest_route=\/wp\/v2\/posts\/234","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.softwareeverydayblog.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.softwareeverydayblog.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.softwareeverydayblog.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.softwareeverydayblog.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=234"}],"version-history":[{"count":29,"href":"https:\/\/www.softwareeverydayblog.com\/index.php?rest_route=\/wp\/v2\/posts\/234\/revisions"}],"predecessor-version":[{"id":3095,"href":"https:\/\/www.softwareeverydayblog.com\/index.php?rest_route=\/wp\/v2\/posts\/234\/revisions\/3095"}],"wp:attachment":[{"href":"https:\/\/www.softwareeverydayblog.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=234"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.softwareeverydayblog.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=234"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.softwareeverydayblog.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=234"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}