Hello I recently received a demand to migrate the ldap authentication service to oauth2 from a jsf project, but I have no idea where to start, from what I've been seeing in the project I have an ldap security domain configured in wildfly where I can make use of some features that comes from FacesContext as:
.login(username, password)
.getUserPrincipal()
.isUserInRole(rule)
.logout()
.invalidateSession()
What I would like to know is if there is a possibility to make my own security domain the same as the configured ldap, where I would implement the methods above, any content where I can start is welcome
I made an implementation of org.jboss.security.auth.spi.UsernamePasswordLoginModule;
Related
A current application running in Wildfly (Jboss) uses its own Authentication system that internally verifies passwords and credentials on its Database.
This system is no longer viable for the future as we migrate to a microservices pattern, therefore requiring a distributed login system using OpenId Connect protocol for Authentication initially, authorization will come later.
This has been implemented fine with a new Spring boot microservice using Spring security and Spring OAuth2 client, however integrating those libraries with the old Jakarta EE application is proving a challenge.
Implementation
Spring version - 5.3.13
Spring Security version - 5.5.3
Omnifaces version - 3.11.2
Jakarta EE version - 8
Wildfly application container - 23
There is an existing Authentication system using Java EE HttpAuthenticationMechanism with a AuthenticatedUser bean which acts like a principal.
I added Spring security and OAuth2 client to the Java EE application. It works fine and redirects people to an AWS Cognito SSO page and redirects back with authorization code after they login.
Here is a diagram summarizing what is currently hacked together
Testing
I created two basic JSF pages with backing beans, one secured with old Javax Security rules defined in web.xml and the other defined in Spring security configuration bean.
With the Spring secured page, I can get the Security context in the bean (I think this uses ThreadLocal)
e.g.
Helloworld Backing Bean
#Named
#ViewScoped
public class HelloWorldBacking implements Serializable
{
private static final long serialVersionUID = 1L;
public String getAuthDetails() {
SecurityContext context = SecurityContextHolder.getContext();
Authentication authentication = context.getAuthentication();
return authentication.getName();
}
}
Spring Security Config
#Configuration
#EnableWebSecurity
#PropertySource("classpath:application.properties")
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
private final String clientSecret;
private final String clientId;
private final String issuerUri;
#Autowired
public SecurityConfiguration(#Value("${oauth.issuer-uri}") String issuerUri,
#Value("${oauth.client-id}") String clientId,
#Value("${oauth.client-secret}") String clientSecret) {
this.issuerUri = issuerUri;
this.clientId = clientId;
this.clientSecret = clientSecret;
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.ALWAYS)
.and()
.csrf()
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
.and()
.cors()
.and()
.authorizeRequests()
.antMatchers("/helloworld-spring").hasAuthority("Admin")
.and()
.oauth2Login()
.and()
.oauth2ResourceServer()
.jwt();
}
...
However if I don't protect that JSF page with Spring security I cannot get any context.
Problem
When a JSF page has been secured with the old security way, it seems to go down a different path with contexts that are all managed by CDI.
I want to integrate Spring security principal into all parts of the JSF app. So that JSF is aware of it in its context.
Debugging
When debugging some existing pages, it appears that both Auth systems are activated but are divergent and not aware of each other.
Solutions?
As someone who has been spoiled by the luxury of spring boot auto configuration, I am a bit stuck on what to do.
Potentially its an easy fix with just overriding a class, or:
Do I need to just rip out the old Authentication system that uses Java EE spec?
Do I override some part of Spring security so that it is aware of Java EE and JSF?
Does JSF need to be configured to talk to Spring security?
Is there something higher level abstracted away in the Wildfly application server that needs to be configured?
tl;dr
How do I get Spring security to pass its security context to JSF in a Jakarta EE application?
Thanks
A current application running in Wildfly (Jboss) uses its own Authentication system that internally verifies passwords and credentials on its Database.
From your diagram, it looks like it's not "its own Authentication system", but it uses Java EE Security. There's no need to replace this with anything Spring.
The best way to make this work is to keep it as is. Java EE Security was specifically designed to work with JSF, and the two integrate together quite well. Bringing your own security system into the mix here is probably asking for problems later.
p.s.
OpenId Connect is currently being included in what's now called Jakarta EE Security, see https://github.com/jakartaee/security/pull/185
Java EE Security on WildFly works really well with the MicroProfile APIs, which includes a JWT Authentication Mechanism. See for example
https://github.com/wildfly/quickstart/blob/main/microprofile-jwt/README.adoc
I am building a web application using an AngularJS front-end and a Spring Boot REST back-end (they are running on separate servers i.e. port 3000 and port 8443). The back-end is supposed to connect to multiple external services (with separate authentications) and provide endpoints for the front-end to use.
For security, I decided to use Apache Shiro. For simplicity, I will pretend there are just 2 external services (ES1 and ES2).
I have created 2 x AuthorizingRealm which connect to the respective external services and attempt authentication using the provided tokens.
In the doGetAuthenticationInfo method, if the login is successful, I return a SimpleAuthenticationInfo with the principal, credentials and the name of the realm.
In the doGetAuthorizationInfo method, I check the realm name of the principal and, if it checks out, I return a SimpleAuthorizationInfo with the role "USER" and a permission (e.g. ES1_permitted).
I also extended the UsernamePasswordToken class for each realm to separate usage even more (through the supports method).
In a configuration class, I create a bean for a DefaultWebSecurityManager that uses my two realms and a bean for the Shiro filter.
I added 4 filters:
anon AnonymousFilter
perm PermissionsAuthorizationFilter
es1 ES1Filter
es2 ES2Filter
My filter chain looks something like:
/api/es1/login -> anon
/api/es1/** -> es1, perms[ES1_permitted]
/api/es2/login -> anon
/api/es2/** -> es2, perms[ES2_permitted]
/** -> anon
Somehow, when I served front-end and back-end from the same server (no CORS), it seemed to work. However, now that CORS is an issue, I can't seem to get this to work as expected.
Is there a simpler way to achieve this complete separation of authentication/authorization? I am willing to switch to Spring Security if it can be done there as well.
PS: I am using the Java API, not configuration files (spring xml or shiro.ini).
I am using Spring4 with Spring Security 3.2.4.
I have some http configurations in my security configuration in order to host form based authentication and REST services (with authentication) together.
For the pages and REST services which require app-authentication everything works fine with my current configuration but for the pages which does not require authentication, such as login and register, the anonymous authentication is not initialised somehow. Speaking in Java:
SecurityContextHolder.getContext().getAuthentication() returns null.
I expect that anonymous authentication is initialised as the documentation (http://docs.spring.io/spring-security/site/docs/3.2.4.RELEASE/reference/htmlsingle/#introduction) refers:
Anonymous authentication support is provided automatically when using the HTTP configuration Spring Security 3.0 and can be customized (or disabled) using the element. You don’t need to configure the beans described here unless you are using traditional bean configuration.
Does anyone have an idea why does it not happen although the documentation refers? (Beside the fact, that the documentation for 3.2.4 refers to 3.0 version and some of the given configuration suggestions refer deprecated implementation)
I am searching for a security framework that allows role based security for OSGi services as well as CXF webservices.
Some time ago I already used spring security but as we now switched to blueprint it is not an option anymore as far as I understood. To configure the access rules I would like to mainly use the standard #RolesAllowed annotation. So what are my best starting points? I also thought about implementing this myself as a blueprint extension but I would prefer an existing solution.
I would suggest you go with Apache Shiro instead, http://shiro.apache.org/ .
It provides easy API's for authentication, authorization, cryptography, and session management. It can also be easily deployed inside a OSGI container. Some pros of Apache Shiro are listed here Apache Shiro vs Java EE native APIs
In the mean time I created a blueprint extension for authorization based on JAAS and Java EE annoations (#RolesAllowed, #PermitAll, #DenyAll). You can add the extension to any blueprint file. It will then scan all beans for these annoations and intercept calls if they are found. It uses an existing JAAS context to get the roles of the user.
So prerequisite for this is doing a JAAS login. I have also created a CXF JAASAuthentication feature that logs in a user based on basic auth or ws security username principal. The module works together with the Apache Karaf JAAS support. So all karaf users and roles apply.
I will create a tutorial to show how to use all of this once the aries blueprint release that includes the authorization module is out. In the mean time I would be happy if you try it out and report any problems you have.
Btw. another approach for karaf is the role based access control for OSGi services that is built into karaf 3+. It does not work with annotations but is also easy to use. See
http://coderthoughts.blogspot.de/2013/10/role-based-access-control-for-karaf.html
I tried using Basic Authentication by changing the server.xml config of Tomcat 6.0 but it did not worked: BASIC authentication in jersey JAX-RS service and Tomcat 6.0 getting failed
Hence I am opting a way where no server specific config is needed and I can add up the roles directly in my code (either client or server; not sure about theavailable options).
Please provide me some ideas about the possible options for setting the user roles so that I can authenticate my Web Service methods using the #RolesAllowed annotation.
You need to go back and figure out why your security constraints weren't working. Maybe start with the default file realm before moving on to JDBC realms. #RolesAllowed in an annotation that triggers behavior in the container.
If you really want to do it yourself (a bad idea) they you'd probably start by creating a custom servlet filter that implemented the entire basic http challenge mechanism. Next you'd have to replace the SecurityContext provider in Jersey.
They "thing" that enables #RolesAllowed in jersey is this: http://java.net/projects/jersey/sources/svn/content/trunk/jersey/jersey-server/src/main/java/com/sun/jersey/api/container/filter/RolesAllowedResourceFilterFactory.java Which, by the way, don't forget to add as an init-param to your jersey servlet. The RolesAllowedResourceFilterFactory gets its security info from an injected SecurityContext which I'm sure at some point just delegates off to the Servlet API for credential info.
So basically if you don't want to take the time to get security constraints working you are going to end up replacing most of the chain...like I said, a bad idea.
The features on application servers are there to keep you from having to spend time creating infrastructure code, if you write your own infrastructure code you're going to have a bad time.