I need to implement HTTP digest authentication for my Springboot Application. I have tried configuring this from Tomcat setup (How to use digest authentication in Tomcat 8.5? ut since Springboot doesn't generate any web.xml, I couldn't configure this. Can someone, please, give a piece of advice as for is there any alternative?
Steps Followed
1.generated sha -256 password
digest.bat -s 0 -a sha-256 tomcat
2. updated tomcat user file
<role rolename="admin-gui"/>
<user username="tomcat" password="ce066452368a3498047a43323cff46a00222945691d728747a2283273506a0a7"
roles="manager-gui,manager,admin"></user>
3. updated tomcat conf/server.xml
<Realm className="org.apache.catalina.realm.LockOutRealm">
<Realm className="org.apache.catalina.realm.UserDatabaseRealm" resourceName="UserDatabase">
<CredentialHandler className="org.apache.catalina.realm.MessageDigestCredentialHandler" algorithm="SHA-256" />
</Realm>
</Realm>
4. updated tomcat conf/web.xml
<security-constraint>
<web-resource-collection>
<web-resource-name>MySecureResource</web-resource-name>
<url-pattern>/*</url-pattern>
<http-method>GET</http-method>
<http-method>POST</http-method>
</web-resource-collection>
<auth-constraint>
<role-name>admin-gui</role-name>
</auth-constraint>
</security-constraint>
<security-role>
<role-name>admin-gui</role-name>
</security-role>
<login-config>
<auth-method>DIGEST</auth-method>
<realm-name>UserDatabase</realm-name>
</login-config>
Related
I am trying to deploy my spring boot application in external tomcat and configure the tomcat 9 with keycloak.
i am following this official doc https://www.keycloak.org/docs/latest/securing_apps/#_tomcat_adapter .
My context.xml looks like this
<Context>
<Valve className="org.keycloak.adapters.tomcat.KeycloakAuthenticatorValve"/>
</Context>
keycloak config
{
"realm": "Project-DEV",
"auth-server-url": "http://192.168.99.100:9002/auth",
"ssl-required": "none",
"resource": "ProjectAuthentication",
"verify-token-audience": true,
"credentials": {
"secret": "0e69d505-1e62-49d3-a086-9234504658e1"
},
"confidential-port": 0,
"policy-enforcer": {}
}
here is my web.xml
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<module-name>myprojectl</module-name>
<security-constraint>
<web-resource-collection>
<web-resource-name>Project</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>uma_protection</role-name>
</auth-constraint>
</security-constraint>
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>this is ignored currently</realm-name>
</login-config>
</web-app>
and this is how my keycloak config looks like
For every API call i am getting 403 . But during debugging i see that token was successfully authentication.
My understanding was for every request Tomcat will call the keycloakAuthenticatorValue first which in result checks the web.xml and then calls the keycloak for authentication and if user is verified then request will be forwarded to my endpoint.
Please correct me if i have understood the whole concept wrong and any pointers here would be highly appreciated. Thanks.
You are missing tag in web.xml which contains security roles that Application adhere to. You will have to add uma-protection inside this tag.
Refer https://www.keycloak.org/docs/latest/securing_apps/#_tomcat_adapter
I have new problem with container security . On the server i have two ears first call service from second. On service there is #RolesAllowed("Authenticated"). My configuration in server.xml looks like this:
<featureManager>
<feature>jndi-1.0</feature>
<feature>distributedMap-1.0</feature>
<feature>localConnector-1.0</feature>
<feature>wasJmsClient-2.0</feature>
<feature>jdbc-4.1</feature-->
<feature>javaMail-1.5</feature>
<feature>json-1.0</feature>
<feature>adminCenter-1.0</feature>
<feature>appSecurity-2.0</feature>
<feature>beanValidation-2.0</feature>
<feature>cdi-2.0</feature>
<feature>jsf-2.3</feature>
<feature>mdb-3.2</feature>
<feature>ejbHome-3.2</feature>
<feature>ejbLite-3.2</feature>
<feature>ejbRemote-3.2</feature>
<feature>jca-1.7</feature>
<feature>concurrent-1.0</feature>
<feature>jms-2.0</feature>
<feature>appClientSupport-1.0</feature>
<feature>ldapRegistry-3.0</feature>
</featureManager>
<basicRegistry id="basic" realm="customRealm">
<user password="{xor}Ozo5Kiw6LQ==" name="defuser" />
</basicRegistry>
Both ears contains identical configuration
<application-bnd>
<security-role name="All Role">
<special-subject type="ALL_AUTHENTICATED_USERS" />
</security-role>
</application-bnd>
The second ear contains ibm-application-ibd.xml file but i can not edit it. Best would be to override it.
When i call service from second ear i still get exception :
Caused by: javax.ejb.EJBAccessException: CWWKS9400A: Authorization failed for user UNAUTHENTICATED while invoking
Eny ideas ?
Liberty allows you to override application binding files using the server config element application-bnd, see IBM KnowledgeCenter topic https://www.ibm.com/support/knowledgecenter/en/SSEQTP_liberty/com.ibm.websphere.liberty.autogen.base.doc/ae/rwlp_config_enterpriseApplication.html#application-bnd and https://www.ibm.com/support/knowledgecenter/en/SSEQTP_liberty/com.ibm.websphere.wlp.doc/ae/twlp_sec_rolebased.html for details.
According to my experience configuring the authentication with Websphere Liberty, the login showed up only for restricted pages only, so the app needs to definen some security constraint in the web.xml like this example:
<security-constraint>
<web-resource-collection>
<web-resource-name>Secured API</web-resource-name>
<url-pattern>/s/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>user</role-name>
</auth-constraint>
</security-constraint>
<security-role>
<role-name>user</role-name>
</security-role>
I am attempting to redirect traffic on insecure port to secure port as described here:
https://www.ibm.com/support/knowledgecenter/en/SSD28V_9.0.0/com.ibm.websphere.liberty.autogen.core.doc/ae/rwlp_config_httpProxyRedirect.html
Instead both ports are available and I see nothing in the logs. It's as if the httpProxyRedirect isn't being configured at all.
<?xml version="1.0" encoding="UTF-8"?>
<server description="CAST Liberty Server">
<!-- Enable features -->
<featureManager>
<feature>webProfile-7.0</feature>
</featureManager>
<application id="app" context-root="/" type="war" location="${war.name}">
<classloader apiTypeVisibility="spec, ibm-api, api, third-party" />
</application>
<httpProxyRedirect id="defaultHttpProxyRedirect" httpPort="${http.port}" httpsPort="${https.port}" />
<keyStore id="defaultKeyStore" password="pass" />
<httpEndpoint host="*" httpPort="${http.port}" httpsPort="${https.port}" id="defaultHttpEndpoint" />
<applicationMonitor updateTrigger="mbean" />
</server>
Most likely, you are missing the security-constraints in the web.xml. This configuration tells the server which URLs need to be accessed over a secure transport and then re-directs qualifying requests from the non-secure port to the secure port. This tutorial may help: https://docs.oracle.com/cd/E19798-01/821-1841/bncbk/index.html
Also, keep in mind that the httpProxyRedirect configuration in the server.xml is intended for redirecting when you have a proxy server in front of your application server. For example, you may have your proxy server on the main "www.ibm.com" host - listening on HTTP port 80 and HTTPS port 443. But that host may route some requests to your Liberty application server on some other host (like "app1host.internal.ibm.com") that listens on different ports (i.e. HTTP port 9080 and HTTPS port 9443). In that case, just using the security-constraints in the web.xml would attempt to redirect the client request on the Liberty server from 9080 to 9443 but on the www.ibm.com host - where nothing is listening on those ports. In this case, you should configure httpProxyRedirect like this:
<httpProxyRedirect httpPort="80" httpsPort="443" host="www.ibm.com" />
With the configuration, a client HTTP request to a secured URL will get redirected to www.ibm.com on port 443, where the proxy server will forward the request to app1host.internal.ibm.com port 9443.
Hope this helps,
Andy
This is the security constraint that i am using in my web.xml and it works well for both Tomcat and IBM Websphere 8.5.5.15:
<security-constraint>
<web-resource-collection>
<web-resource-name>Entire Application</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
Note: make sure that you put it after your <servlet-mapping>.
I am using apache http,mod-jk and two tomcat servers for load balancing of my application which uses spring security. When application is launched, I get below error
Error code: ERR_TOO_MANY_REDIRECTS
Has anyone seen this issue before?Is there any configuration to get load balancer work.
If I remove spring security from my application, load balancer works fine.
Web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- The definition of the Root Spring Container shared by all Servlets
and Filters -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring-security.xml,/WEB-INF/spring/root-context.xml</param-value>
</context-param>
<!-- Creates the Spring Container shared by all Servlets and Filters -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>oAuth</servlet-name>
<servlet-class>org.springframework.web.context.support.HttpRequestHandlerServlet</servlet-class>
</servlet>
<!-- Processes application requests -->
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/servlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>oAuth</servlet-name>
<url-pattern>/oAuth</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>60</session-timeout>
</session-config>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>/index.html</welcome-file>
</welcome-file-list>
Spring-Security.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security.xsd">
<!--HTTP Interceptors for authentication -->
<http pattern="/templates/**" security="none"></http>
<http pattern="/css/**" security="none"></http>
<http pattern="/js/**" security="none"></http>
<http pattern="/lib/**" security="none"></http>
<http pattern="/lib/css/**" security="none"></http>
<http pattern="/lib/js/**" security="none"></http>
<http pattern="/lib/fonts/**" security="none"></http>
<http pattern="/img/**" security="none"></http>
<http pattern="/rest/**" security="none"></http>
<http pattern="/oAuth" security="none"></http>
<http entry-point-ref="entryPoint"
auto-config="true" use-expressions="true">
<anonymous enabled="false"></anonymous>
<custom-filter ref="oAuthFilter" after="SECURITY_CONTEXT_FILTER"></custom-filter>
<intercept-url pattern="/**" access="hasRole('ROLE_USER')"></intercept-url>
</http>
<authentication-manager alias="upmAuthenticationManager"></authentication-manager>
<beans:bean id="entryPoint" class="auth.EntryPoint">
<beans:constructor-arg value="/index.html"></beans:constructor-arg>
</beans:bean>
<beans:bean id="oAuthEnd" name="auth.oAuthEnd"
class="oAuth.OAuthServlet">
<beans:property name="oAuthFilter" ref="oAuthFilter"></beans:property>
</beans:bean>
<beans:bean id="oAuthFilter" class="auth.filter">
<beans:property name="id"
value=""></beans:property>
<beans:property name="secret"
value=""></beans:property>
<beans:property name="url"
value=""></beans:property>
</beans:bean>
mod-jk configuration
worker.server1.port=8009
worker.server1.host=localhost
worker.server1.type=ajp13
worker.server2.port=9009
worker.server2.host=localhost
worker.server2.type=ajp13
worker.server1.lbfactor=1
worker.server2.lbfactor=1
worker.loadbalancer.type=lb
worker.loadbalancer.balance_workers=server1,server2
worker.status.type=status
<VirtualHost *:80>
JkMount /status status
JkMount /* loadbalancer
ServerAdmin webmaster#localhost
DocumentRoot /data/www/
<location />
Require all granted
</location>
ErrorLog ${APACHE_LOG_DIR}/www_error.log
CustomLog ${APACHE_LOG_DIR}/www_access.log combined
</VirtualHost>
Apache httpd and mod_jk don't make the trouble I'm afraid.
Hard to say without seeing your config, but I bet that your Spring security config has configured a login page that is secured, so it's allways redirecting to a page you cannot reach.
Could you post your web.xml and security config? And maybe the mod_jk mappings to Tomcat would be helpfull too.
EDIT:
I think that setting sticky_session to true could solve the problem. Try adding this to your mod_jk config:
worker.loadbalancer.sticky_session=1
EDIT2: Setting jvmRoute property to values configured in worker.loadbalancer.members solved the problem.
What was happening is that mod_jk uses the value which comes as a suffix in the session cookie to check it against the loadbalancer member names to find out on which has the client the session opened. As the jvmRoute had no value, the JSESSIONID had no suffix so the mod_jk did not know which worker to send the request, so the balancer chooses one worker according to the lbfactor.
As this value is configured with same value to both workers, each incoming request was redirected to the worker that was not chosen in the previous request, so there was no chance to reach the login form neither perform the login (or whatever login mechanism is being used).
I have added security-constraint to protect some folders of the app.
<security-constraint>
<web-resource-collection>
<web-resource-name>panel</web-resource-name>
<url-pattern>/secured/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>super</role-name>
</auth-constraint>
</security-constraint>
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>Panel</realm-name>
</login-config>
I added proper user SUPER to tomcat-users, this is all seems to be working fine when I deploy the app. However when I run it locally from exclipse via maven, using tomcat7:run, my local setup does not have tomcat-users.xml file, so basically I am not sure how to configure users locally. Security works but no users defined.
Can u please tell me how to pass or specify custom tomcat-sers.xml file for the mavens tomcat plugn
I got it, if anybody ever needs it.
In pom.xml find your plugin block for tomcat7-maven-plugin and specify in configuration custom tomcat-users.xml path.
<configuration>
<tomcatUsers>path/tomcat-users.xml</tomcatUsers>
</configuration>