I'm currently checking keycloak example: servlet-authz. And learned that it secured a web resource via web.xml:
<security-constraint>
<web-resource-collection>
<web-resource-name>All Resources</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>user</role-name>
<role-name>admin</role-name>
<role-name>user_premium</role-name>
</auth-constraint>
</security-constraint>
<login-config>
<auth-method>KEYCLOAK</auth-method>
<realm-name>servlet-authz</realm-name>
</login-config>
<security-role>
<role-name>admin</role-name>
</security-role>
<security-role>
<role-name>user</role-name>
</security-role>
<security-role>
<role-name>user_premium</role-name>
</security-role>
My question is, can it be achieved dynamically? Without using web.xml? For example I have a new role role_guest, with only access to /guest/* url. How to configure that? I checked all the examples but none does so far.
If you want to load all roles dynamically you have to include web.xml (unluckily) with wildcard (*) in both auth-constraint and security-role.
All roles allowed web.xml fragment:
...
<security-constraint>
<web-resource-collection>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>*</role-name>
</auth-constraint>
</security-constraint>
<login-config>
<auth-method>KEYCLOAK</auth-method>
<realm-name>servlet-authz</realm-name>
</login-config>
<security-role>
<role-name>*</role-name>
</security-role>
...
I don't know if there's a way to automatically attach to every role a url-pattern, which contains role name.
Flow tested on Wildfly 11 with Keycloak adapter version 4.4.0.Final.
Related
I want to secure my web app such that only the "admin" user can access all of the pages, but a special "test" user can access the status page.
Here is what I've tried:
In web.xml:
<security-constraint>
<web-resource-collection>
<web-resource-name>Everything else</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>admin</role-name>
</auth-constraint>
</security-constraint>
<security-constraint>
<web-resource-collection>
<web-resource-name>Status page</web-resource-name>
<url-pattern>/status/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>test</role-name>
<role-name>admin</role-name>
</auth-constraint>
</security-constraint>
<login-config>
<auth-method>BASIC</auth-method> <!-- Use http basic authentication -->
<realm-name>MyApp Realm</realm-name> <!-- users are defined in this realm -->
</login-config>
Unfortunately, when I tried to access the status page (https://localhost:444/app-0.0.1-SNAPSHOT/hbr/status) with the test user I get the following:
Problem accessing /app-0.0.1-SNAPSHOT/hbr/status. Reason:
!role
Any idea how I can fix this?
It turns out that the "status" page is not at the root of the app, but part of a subservice called "hbr" ("hbr" the only subservice, which is why I didn't notice). The following change to the second security-constraint causes the app to work as expected:
<security-constraint>
<web-resource-collection>
<web-resource-name>Status page</web-resource-name>
<url-pattern>hbr/status/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>test</role-name>
<role-name>admin</role-name>
</auth-constraint>
</security-constraint>
I have a small web application that use jdbcRealm for authentification/authorisation.
The authorisation works only if I put the user name in the glassfish-web.xml
<glassfish-web-app error-url="">
<class-loader delegate="true"/>
<jsp-config>
<property name="keepgenerated" value="true">
<description>Keep a copy of the generated servlet class' java code.</description>
</property>
</jsp-config>
<security-role-mapping>
<role-name>connexion</role-name>
<principal-name>test</principal-name>
<group-name>connexion</group-name>
</security-role-mapping>
</glassfish-web-app>
web.xml
<!--other stuff-->
<security-constraint>
<web-resource-collection>
<web-resource-name>secure</web-resource-name>
<url-pattern>/Downloader</url-pattern>
<url-pattern>/start.html</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>connexion</role-name>
</auth-constraint>
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
<login-config>
<auth-method>FORM</auth-method>
<realm-name>my_realm</realm-name>
<form-login-config>
<form-login-page>/login.html</form-login-page>
<form-error-page>/error.html</form-error-page>
</form-login-config>
</login-config>
<security-role>
<role-name>connexion</role-name>
</security-role>
<!--other stuff-->
If I remove the principal from the glassfish-web I get a 403 error acces denied .
Is there any solution to avoid adding principals in xml file ?
Thanks.
Yes, there is. In your security realm (from the content of web.xml, that is my_realm) associate the username you are logging in with the appropriate group - in your case that is connexion. In other words, every user that belongs to the group connexion will have the access to the protected resource and therefore you don't have to enumerate the principals - that's the purpose of groups.
Reference & further reading: Java EE 6 tutorial
I have GWT application deploy on AppEngine. I would like to limit access to the application to administrators only.
I would like to use the built-in security-constraint settings in web.xml but I can't figure how to make my app respond in /myapp/admin url instead of /myapp
I am using RequestFactory to communicate with the server, I would like the /gwtRequest to be under the same constraint.
Thank you,
Ido.
I don't know if I understand your question correcty.
If you want only access with admin, you can configure you Application like following:
<security-constraint>
<web-resource-collection>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>admin</role-name>
</auth-constraint>
</security-constraint>
<security-constraint>
<web-resource-collection>
<url-pattern>/loginpage</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>*</role-name>
</auth-constraint>
</security-constraint>
Now you have only Admin-Access to every Page, but you still need to have public access to the login-page. (you must replace "loginpage" with the url to your login page)
If you only want to make you gwtRequest under admin-access make it like this:
<security-constraint>
<web-resource-collection>
<url-pattern>/gwtRequest/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>admin</role-name>
</auth-constraint>
</security-constraint>
I'm sorry I'm not sure if its /gwtRequest/ or /gwtRequest
I'm developing a Web Project with Java EE and I want that some JSP are accessible only by some kind of users. I've read that using the web.xml descriptor I can set the visibility of some resources only to a 'role-name'. But how do I set this role-name in the http session?
For instance, my descriptor has:
<security-constraint>
<web-resource-collection>
<web-resource-name>Access to Student pages</web-resource-name>
<url-pattern>/Student/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>Student</role-name>
</auth-constraint>
</security-constraint>
Where/How do I define the 'Student' role-name?
That is the job of your application server. The server will store the roles in the session after authentication (if authentication is done by the server).
web.xml -- in your app
<security-constraint>
<web-resource-collection>
<url-pattern>/Student/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>Student</role-name>
</auth-constraint>
</security-constraint>
<login-config>
<auth-method>BASIC</auth-method>
</login-config>
How to assign users/logins to rolles is Server dependent, here a very basic example for tomcat:
tomcat-users.xml -- This file is in your Server, you have to extend it!
<?xml version='1.0' encoding='utf-8'?>
<tomcat-users>
<role rolename="tomcat"/>
<role rolename="Student"/> <!-- you have to define all roles -->
<user username="tomcat" password="tomcat" roles="tomcat"/>
<user username="myname" password="mypassword" roles="Student"/> <!-- you have to assign login and roles -->
</tomcat-users>
I have two Web Services (MyService and MyProtectedService). I want both going under the same port HTTPS but only the protected one to have client authentication (clientAuth=true).
All the security is working fine, but the problem is that the client auth is ON for both services, not only for the protected one. What I would like is remove the client auth for one of them, or apply the client auth to the other only.
Does anyone have any hint? Thanks
In the web.xml:
<security-constraint>
<web-resource-collection>
<web-resource-name>protected element</web-resource-name>
<description/>
<url-pattern>/MyProtectedService</url-pattern>
</web-resource-collection>
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
UPDATE:
I tried to divide the service in two constrains:
<security-constraint>
<web-resource-collection>
<web-resource-name>OpenService</web-resource-name>
<description/>
<url-pattern>/OpenService</url-pattern>
</web-resource-collection>
</security-constraint>
<security-constraint>
<web-resource-collection>
<web-resource-name>protected</web-resource-name>
<description/>
<url-pattern>/MyProtectedService</url-pattern>
</web-resource-collection>
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
<login-config>
<auth-metod>CLIENT-CERT</auth-metod>
</login-config>
</security-constraint>
And have ClientAuth=false in server.xml.
But then I can access this without any client authentication:
https://MACHINE/MyProtectedService/MyProtectedService?wsdl
The approach is to have two separate security constraints even though the one for the public service has no constraint at all (neither a auth-constraint nor a user-data-constraint). It assumes that the two service have different URLs which is most likely the case:
<security-role>
<role-name>ProtectedServiceRole</role-name>
</security-role>
<security-constraint>
<web-resource-collection>
<web-resource-name>Public Service</web-resource-name>
<url-pattern>/PublicService/*</url-pattern>
</web-resource-collection>
</security-constraint>
<security-constraint>
<web-resource-collection>
<web-resource-name>Protected Service</web-resource-name>
<url-pattern>/ProtectedService/*</url-pattern>
</web-resource-collection>
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
<auth-constraint>
<role-name>ProtectedServiceRole</role-name>
</auth-constraint>
</security-constraint>
The role name specified in the auth-constraint will trigger an authentication.
Update:
I'm afraid I haven't properly read your question and overlooked the certificate authentication part. Though I have used it in the past, I never had the mixed setup you require so I can only give some options what you could try next:
Currently you require the authentication on the transport level. That's to low-level and too early. Have you tried setting clientAuth to false and instead add the following lines to your web.xml:
<login-config>
<auth-method>CLIENT-CERT</auth-method>
</login-config>
Another approach would be to use two differnt ports for the two services. For that, you define two different connectors in the server.xml.