I have the following Jetty setup:
<New class="org.eclipse.jetty.plus.jaas.JAASLoginService">
<Set name="Name">FOO JAAS Realm</Set>
<Set name="LoginModuleName">foo</Set>
<Set name="roleClassNames">
<Array type="java.lang.String">
<Item>foo.jaas.principal.UserPrincipal</Item>
<Item>foo.jaas.principal.RolePrincipal</Item>
<Item>org.eclipse.jetty.plus.jaas.JAASRole</Item>
</Array>
</Set>
</New>
I am using an Embedded Jetty 7.6.1.v20120215 via the Maven Jetty Plugin.
When I try to login via the form that I have, the logins fields are properly sent to /j_security_check. I have written my own LoginModule which is invoked and validates the users properly. I can see their principals are properly fetched from the database.
Instead of being shown the secured page, Jetty shows me:
HTTP ERROR 403
Problem accessing /foo/auth.html. Reason:
!role
I am not quite sure what it really means by that.
I have the following in my web.xml:
<security-constraint>
<web-resource-collection>
<web-resource-name>ADMINISTRATOR</web-resource-name>
<url-pattern>/auth.html</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>ADMINISTRATOR</role-name>
</auth-constraint>
</security-constraint>
<login-config>
<auth-method>FORM</auth-method>
<realm-name>foo</realm-name>
<form-login-config>
<form-login-page>/login.html</form-login-page>
<form-error-page>/authfail.html</form-error-page>
</form-login-config>
</login-config>
<security-role>
<role-name>ADMINISTRATOR</role-name>
</security-role>
<security-role>
<role-name>USER</role-name>
</security-role>
I am logging in as the administrator.
Any help on the cryptic JAAS message displayed by Jetty would be very much appreciated.
I had the same error and above code was already there....
but after reading: http://wiki.eclipse.org/Jetty/Tutorial/JAAS
I had to also update web-jetty.xml and add
<Set name="roleClassNames">
<Array type="java.lang.String">
<Item>login.RolePrincipal</Item>
</Array>
</Set>
in this section:
<New class="org.eclipse.jetty.plus.jaas.JAASLoginService">
because I used a custom made principal for roles "login.RolePrincipal" (actually I inherited the code and was moving the app from tomcat to jetty :) )
The user that is logging in does not have the role ADMINISTRATOR that you enforce on /auth.html.
During the commit phase,your JAAS Login module is expected to add the user roles to the Subject Principals. The roles are held in a class extending Principal which you indicate to Jetty in the jetty.xml file.
You login module should have something like this in commit()
Set<Principal> subjectPrincipals = subject.getPrincipals();
//add the roles
for (String role : userRolesList) {
subjectPrincipals.add(new RolePrincipal(role));
}
RolePrincipalis your role class
Related
I'm implementing a REST-API in Java, using Jersey3 and a Tomcat10. In order to provide/restrict access to some endpoints for specific roles, I would like to use a DataSourceRealm.
The configuration in my context.xml looks like this:
<Resource type="javax.sql.DataSource"
name="jdbc/myDB"
factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
driverClassName="oracle.jdbc.OracleDriver"
url="jdbc:oracle:thin:#//localhost:1521/orcl"
username="xx"
password="xx"/>
<Realm className="org.apache.catalina.realm.DataSourceRealm" debug="99"
dataSourceName="jdbc/myDB" localDataSource="true"
userTable="USERS" userNameCol="USERNAME" userCredCol="PASSWORD"
userRoleTable="USER_ROLES" roleNameCol="ROLENAME"/>
The dataSource is also defined in my context.xml and can be accessed with JNDI.
In my web.xml I defined the following security constraint:
<security-constraint>
<web-resource-collection>
<web-resource-name>Some name</web-resource-name>
<url-pattern>/api/data</url-pattern>
<http-method>GET</http-method>
</web-resource-collection>
<auth-constraint>
<role-name>Administrator</role-name>
</auth-constraint>
</security-constraint>
So every GET request with the pattern /api/data requires the role Administrator
Table USER_ROLES has one entry with USERNAME=admin and ROLENAME=Administrator.
Also, I've added these lines:
<login-config>
<auth-method>BASIC</auth-method>
</login-config>
<security-role>
<role-name>Administrator</role-name>
</security-role>
For doing the obvious.
A corresponding endpoint is defined like this:
#GET
#Produces(MediaType.APPLICATION_JSON)
#Path("/data")
#RolesAllowed({"Administrator"})
public Response getData(...)
Added these lines to my log-config:
org.apache.catalina.realm.level = ALL
org.apache.catalina.realm.useParentHandlers = true
org.apache.catalina.authenticator.level = ALL
org.apache.catalina.authenticator.useParentHandlers = true
Calling http://localhost:8080/myapp/api/data in a GET with Authentication header Basic YWRtaW46YWRtaW4= --> admin:admin
Restricting access so far works and my DataSourceRealm seems to be taken into account. Although there are no logs from the when someone is authenticating.
What would I need to add, in order so see logs from the DataSourceRealm?
Any help/input would be much appreciated.
I have three jsf web application deployed on tomcat web server with SSL/TLS enabled. Now I want to build some kind of SSO authentication with particular roles. In tomcat conf/server.xml there is line:
<Valve className="org.apache.catalina.authenticator.SingleSignOn" />
so I got idea that tomcat maybe have his own SSO implementation. Does anyone know where to find more information about this or some code examples?
Thanks in advance
After many hours of research I found solution, so I will post it here in case someone need SSO authentication in tomcat.
First of all open conf/server.xml file in tomcat installation directory and add following line:
<Host appBase="webapps" autoDeploy="true" name="localhost" unpackWARs="true">
<Valve className="org.apache.catalina.authenticator.SingleSignOn" />
</Host>
By doing this, you have opened SSO valve. Next, you need to set up roles in tomcat. That is done by editing conf/tomcat-users.xml. Scroll to the bottom and add roles, something like this:
<role rolename="CUSTOMER"/>
<role rolename="ADMIN"/>
Now, if you want plain text authentication you can add users also by adding :
<user username="admin" password="admin" roles="ADMIN"/>
<user username="customer" password="customer" roles="CUSTOMER"/>
or, if you have database you can set up connection with database server in conf/server.xml, I'm using MySQL:
<Realm className="org.apache.catalina.realm.JDBCRealm"
driverName="com.mysql.cj.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/databaseName?user=serverUsername&password=serverPassword"
userTable="usersTable" userNameCol="usernameColumnName" userCredCol="passwordColumnName"
userRoleTable="roleTable" roleNameCol="roleColumnName"/>
Note: You need to provide connection driver in tomcat lib directory.
More info on: https://tomcat.apache.org/tomcat-7.0-doc/realm-howto.html#JDBCRealm
Finally in your web app or apps, find web.xml and add security constrains:
<security-constraint>
<web-resource-collection>
<web-resource-name>Protected Context</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
<auth-constraint>
<role-name>ADMIN</role-name>
</auth-constraint>
</security-constraint>
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>this is ignored currently</realm-name>
</login-config>
<security-role>
<role-name>ADMIN</role-name>
</security-role>
Note: if you have custom Login page you can edit <login-config> tag and change to following:
<login-config>
<auth-method>FORM</auth-method>
<realm-name>file</realm-name>
<form-login-config>
<form-login-page>/login.jsp</form-login-page>
<form-error-page>/error.jsp</form-error-page>
</form-login-config>
</login-config>
Cheers.
Apache 9 Single Sign On Valve documentation is here: https://tomcat.apache.org/tomcat-9.0-doc/config/valve.html.
Since you mentioned JSF (I'm not sure if you are using PrimeFaces & OmniFaces), maybe you are struggling also with log out/session time out. Specially if end user has open multiple windows/tabs and multiple applications (you mentioned you have three JSF apps), then
OmniFaces FacesExceptionFilter and
OmniFaces FullAjaxExceptionHandler
would be helpful for you. I can also recommend the best JSF book I've ever read
The Definitive Guide to JSF in Java EE 8 written by BalusC (JSF expert, author of OmniFaces, etc.).
I want to create a simple JSP/Servlet login page that authenticate using websphere ldap repository.
All examples I've found looks very complex, with hundreds of lines of code just to authenticate.
Is this really so complex?
Does anyone have a simple example or article that explains how to authenticate a user/pass against a ldap repository already configured as websphere federated repository?
I really appreciate any help.
Thanks
This is quit simple in reality. You need following pieces:
1) Login page with form that points to j_security_check
See this page for details Customizing web application login
Very simplified example is like this:
<form method="POST" action="j_security_check">
<input type="text" name="j_username">
<input type="text" name="j_password" autocomplete="off">
<\form>
2) Security configured in web.xml
Something like this:
<login-config>
<auth-method>FORM</auth-method>
<realm-name>Example Form-Based Authentication</realm-name>
<form-login-config>
<form-login-page>/login.jsp</form-login-page>
<form-error-page>/login.jsp</form-error-page>
</form-login-config>
</login-config>
plus security constraint:
<security-constraint>
<display-name>allResources</display-name>
<web-resource-collection>
<web-resource-name>allResources</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>users</role-name>
</auth-constraint>
</security-constraint>
3) Application security enabled on the application server and user registry configured.
That's it.
hello every one I tried to solve this issue with configuration Relam Ldap in glass fish 3.1 but I get this error
WARNING: SEC1106: Error during LDAP search with filter [uid=teuser].
WARNING: SEC1000: Caught exception.
javax.naming.NamingException: [LDAP: error code 1 - 000004DC: LdapErr: DSID-0C0906E8, comment: In order to perform this operation a successful bind must be completed on the connection., data 0, v1db1]; remaining name= 'DC=dev,DC=tcs,DC=com'
WARNING: WEB9102: Web Login Failed: com.sun.enterprise.security.auth.login.common.LoginException: Login failed: javax.security.auth.login.LoginException: User MyUserName not found.
the web.xml looks like this :
<security-constraint>
<display-name>Constraint1</display-name>
<web-resource-collection>
<web-resource-name>Simple Web Resource</web-resource-name>
<description/>
<url-pattern>*</url-pattern>
</web-resource-collection>
</security-constraint>
<login-config>
<auth-method>FORM</auth-method>
<realm-name>ldapRealm</realm-name>
<form-login-config>
<form-login-page>/index.jsp</form-login-page>
<form-error-page>/error.xhtml</form-error-page>
</form-login-config>
</login-config>
the domain.xml in glassfish directory :
<auth-realm name="ldapRealm" classname="com.sun.enterprise.security.auth.realm.ldap.LDAPRealm">
<property name="directory" value="ldap://10.0.???.???:389"></property>
<property name="base-dn" value="DC=dev,DC=tcs,DC=com"></property>
<property name="jaas-context" value="ldapRealm"></property>
</auth-realm>
I need to know what that error is it problem in configuration at glassfish or what ?
I hit this one when I was not specifying correct credentials for an Active Directory server. Specify the credentials as additional realm properties:
search-bind-dn for username
search-bind-password for a password
I have set the realm setting in server.xml host section to something like this:
<Realm className="org.apache.catalina.realm.JDBCRealm" driverName="org.gjt.mm.mysql.Driver"
connectionURL="jdbc:mysql://localhost:3306/test" connectionName="test" connectionPassword="test"
userTable="users" userNameCol="user_name" userCredCol="user_pass" userRoleTable="user_roles"
roleNameCol="user_role" />
Also in web.xml:
<security-role>
<role-name>ADMIN</role-name>
</security-role>
<security-constraint>
<web-resource-collection>
<web-resource-name>critical</web-resource-name>
<url-pattern>/admin/*</url-pattern>
<http-method>GET</http-method>
<http-method>POST</http-method>
</web-resource-collection>
<auth-constraint>
<role-name>ADMIN</role-name>
</auth-constraint>
</security-constraint>
<login-config>
<auth-method>FORM</auth-method>
<form-login-config>
<form-login-page>/login.jsp</form-login-page>
<form-error-page>/error.jsp</form-error-page>
</form-login-config>
</login-config>
And I have the databased set up. However when login.jsp is envoked, even I entered the right password I was redirected to error.jsp
I want to know if there is a way to find what's wrong during the process. Can I do it in Eclipse or any other hints that may solve the problem?
To get the debug information from the Realm authentication steps, follow this procedure.
When you define your Realm in the server.xml, add debug="9" to the definition (you can of course use a lower number for less detail).
<Realm className="org.apache.catalina.realm.JDBCRealm" driverName="org.gjt.mm.mysql.Driver"
connectionURL="jdbc:mysql://localhost:3306/test" connectionName="test" connectionPassword="test"
userTable="users" userNameCol="user_name" userCredCol="user_pass" userRoleTable="user_roles"
roleNameCol="user_role" debug="9" />
You also need to add this to your logging.properties file:
org.apache.catalina.realm.level = ALL
org.apache.catalina.realm.useParentHandlers = true
org.apache.catalina.authenticator.level = ALL
org.apache.catalina.authenticator.useParentHandlers = true
You may also need to add this, to prevent bufferring of the logs. If you do, remember to remove it after you've finished debugging.
1catalina.org.apache.juli.FileHandler.bufferSize = -1
Now, the debug logs for the realms should end up in the catalina.out file.
For others finding this issue, I found the following worked for Tomcat 8.5.40:
java.util.logging.ConsoleHandler.level = ALL
org.apache.catalina.level = FINEST
org.apache.catalina.realm.JNDIRealm.level = FINEST
org.apache.catalina.realm.JNDIRealm.useParentHandlers = true
The key fact appears to be that your logging travels through several layers of definitions and will be trimmed by the first one that has a lower level so you need to make sure that each bit it passes through is FINEST or ALL.
Hopefully this will save someone some time ;)
Ian.