Handle multiple SP metadata generators in SAML - saml-2.0

I have SP initiated SAML 2.0 + SPRING boot application working behind the Load balancer. The load balancer end point (http://myserver.biz) is configured as entityBaseUrl for the application as
metadataGenerator.setEntityBaseURL(http://myserver.biz);
We added reverse proxy over the LB now which customer will be connecting to over internet. The proxy end point is https://myserverproxy.com. Now I configured entitybase url to something like
metadataGenerator.setEntityBaseURL(https://myserverproxy.com);
The trouble is internal customer will be using application url as http://myserver.biz while external customers coming over internet will use https://myserverproxy.com.
I am unable to configure two entityBaseUrls for the application, SAML MetadataGenerator class support only one entity base url at a time.
public class MetadataGenerator {
private String id;
private String entityId;
private String entityBaseURL;
...
}
How can this be achieved? Any solution on this?
#Bean
public MetadataGenerator metadataGenerator() {
MetadataGenerator metadataGenerator = new MetadataGenerator();
metadataGenerator.setEntityId(entityId);
metadataGenerator.setExtendedMetadata(extendedMetadata());
metadataGenerator.setIncludeDiscoveryExtension(false);
metadataGenerator.setKeyManager(keyManager());
metadataGenerator.setEntityBaseURL(entityBaseUrl);
return metadataGenerator;
}

Related

How to connect to MongoDB using Spring Data

The official tutorial seems to be missing on how to connect to MongoDB cluster?
Here are my requirements:
Using Spring Data MongoDB
Using Spring MVC (not Spring Boot)
Prefer using Spring Repositories
I am able to figure out how to create my repositories and the queries. But not able to wire the repository as a bean.
org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.my.TestRepository] found
Here is my Java based config:
#EnableMongoRepositories
public class RepositoryConfig extends AbstractMongoConfiguration {
#Override
protected String getDatabaseName() {
return "test";
}
#Override
#Bean
public Mongo mongo() throws Exception {
List<MongoCredential> credentials = new LinkedList<>();
MongoCredential credential = MongoCredential.createCredential("test", getDatabaseName(), "test".toCharArray());
credentials.add(credential);
Mongo mongo = new MongoClient(new ServerAddress("localhost", 27017), credentials);
return mongo;
}
}
And here is the way I am looping in my repositories:
#Autowired
TestRepository testRepository;
I have put the Java config file (above) and my Repository class in the same package.
Do I need to provide any additional configuration to be able to autowire the Repository classes?

Restful API becomes 404 when using the CXF at the same time

I have a project starts up with Spring Boot.
It has some restful API via Spring Integration inbound gateway.
Afterward, some webservice endpoint added to the project with CXF.
When I setup the CXFServlet mapping, all the restful API became 404.
Only I suspend the CXF config the restful API available again.
May I know if there is anything block the restful API or the spring integration inbound gateway during using CXF?
CXFServlet and Bus
#Configuration
#ComponentScan("com.kennie")
#ImportResource("classpath:cxf-services.xml")
public class SimbaAdapterApplicationConfiguration {
#Bean
public ServletRegistrationBean dispatcherServlet() {
return new ServletRegistrationBean(new CXFServlet(), "/ws/*");
}
#Bean(name=Bus.DEFAULT_BUS_ID)
public SpringBus springBus() {
SpringBus bus = new SpringBus();
bus.getInInterceptors().add(new LoggingInInterceptor());
bus.getOutInterceptors().add(new LoggingOutInterceptor());
return bus;
}
XML configuration
<import resource="classpath:META-INF/cxf/cxf.xml"/>
<import resource="classpath:META-INF/cxf/cxf-servlet.xml"/>
<jaxws:server id="MyService" address="/ws/MyService"
serviceClass="com.kennie.IMyService" >
<jaxws:serviceBean>
<ref bean="myServiceImpl" />
</jaxws:serviceBean>
</jaxws:server>
Service Interface
#WebService
public interface IMyService{
#WebMethod
public #WebResult(name = "Response") Response doRequest(
#WebParam(name = "Request", mode = WebParam.Mode.IN)
Request request
);
}
I'm not familiar with CXF, but I know that Spring Integration HTTP is fully based on Spring MVC. So, if you can configure Spring MVC over CXF, all those Spring Integration HTTP Inbound Gateways will be available there as well.
I think your problem is somewhere with distinguishing Servlet mapping.
Looks like your REST API is routed through the CXF Servlet and that one doesn't like it, hence rejecting.
When you add CXF to your code, all the RESTful APIs will be routed through it.
I see two contradictory settings with the way you have configured CXF -
The url-mapping . You are injecting CXF with this code:
#Bean
public ServletRegistrationBean dispatcherServlet() {
return new ServletRegistrationBean(new CXFServlet(), "/ws/*");
}
Meaning the url at which CXF is listening is /ws/*.
The jax-ws server! Firstly, you need to change it to jax-rs . WS is for SOAP. RS is for Restful. You have defined its address as:
<jaxws:server id="MyService" address="/ws/MyService"
Meaning the server is listening at /ws/MyService
CXF and the jax-rs server are both listening at ws/ something. Now, this is not really a problem. You just need to add this to the URL you are hitting so that the complete URL is something like this:
http:<server>:<port>/<context-root>/<CXF Endpoint>/<jax-rs server address>/<REST API endpoint>
I am guessing you don't want ws appearing twice in the URL. Remove it from the jax-rs address.
Hope this helps.
You can register more one servlet for http rest api, this method is tested and OK:
#SpringBootApplication(
//scanBasePackages = {"com.huawei.manage"}
)
public class Application {
#Bean
public ServletRegistrationBean dispatcherServlet() {
AnnotationConfigWebApplicationContext applicationContext = new AnnotationConfigWebApplicationContext();
applicationContext.scan("com.huawei.manage.hsf.controller");
DispatcherServlet rest_dispatcherServlet = new DispatcherServlet(applicationContext);
ServletRegistrationBean registrationBean = new ServletRegistrationBean(rest_dispatcherServlet);
registrationBean.setLoadOnStartup(1);
registrationBean.addUrlMappings("/*");
return registrationBean;

Spring boot + mvc (rest) + angularJS: add security

I have a web application with separate front and back:
/project
+--- /back
+--- /front
The back is developped using Spring boot + Spring MVC, while the front is using AngularJS.
I am trying to set up the security for the communication between the back/front. What I did:
- create a ConfigSecurity class which extends from WebSecurityConfigurerAdapter
- create a SpringWebMvcInitializer which extends from AbstractAnnotationConfigDispatcherServletInitializer and call ConfigSecurity
- create a SecurityWebInitializer class which extends AbstractSecurityWebApplicationInitializer
My ConfigSecurity looks like this:
#Configuration
#EnableWebMvcSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class ConfigSecurity extends WebSecurityConfigurerAdapter {
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/demo/**","/home").permitAll()
.anyRequest().fullyAuthenticated()
.and()
.formLogin().loginPage("...")
.and()
.httpBasic();
}
}
My problems:
In configureGlobal(), I can set the username and password to access my protected urls, but how can I do when there is not only one single user? I mean, I want to grant access to all the users that are registered in my database.
Since the back and the front are only communicating with REST (through JSON files), what should be done with formLogin() in ConfigSecurity? By default, Spring Security generates a default login form. I don't need a it in the back of the application since it is the front which is responsible for displaying the loginPage. How can I skip the login page in the back? Maybe by putting the username and password in JSON file the front is sending to the back? Does someone know how it can be done?
I am using Java Configuration for Spring (not XML configuration).
You have many options, all of them require quite a lot of code, but most of it is already well implemented around the internet so you just would have to make it fit your needs. You can either go with simplest way which would be http sessions, JSON token or JWT (JSON web token) or anything else.
Spring blog has a very long post about how to implement different
solutions here:
https://spring.io/guides/tutorials/spring-security-and-angular-js/
JHipster also has different authentication methods which you can take a look at. They have very well implemented role security in front-end which I like a lot and would really suggest looking into: https://github.com/jhipster/jhipster-sample-app
Here's also a JWT which is requires the most code: http://blog.jdriven.com/2014/10/stateless-spring-security-part-2-stateless-authentication/
HTTP Sessions would definitely be the easiest to set up and is well supported by Spring Security out of the box already.
Found great help on this baeldung website (even though it is using XML configuration) and this website (using Java configuration).
For global explanation of how Spring security works, this link helps me a lot.

Integrate Apache Shiro with RestEasy

I have a REST provider implemented using RestEasy. Currently the API uses method level security but we prefer URL-based security of Shiro. Our application uses CDI for dependency injection and it would be really great if currently logged in users can be injected into the beans since that would allow us to alter our responses based on user roles.
Are there any tutorials or examples that show how this can be done?
You can inject the SecurityContext to obtain the UserPrincipal:
#Context
private SecurityContext securityContext;
...
Principal principal = securityContext.getUserPrincipal();
If you need more information about the user you can use a CDI producer which fetches the User from e.g. a database:
public class UserProducer {
#Inject
private HttpServletRequest request;
#Produces
public User getUser() {
Principal principal = request.getUserPrincipal();
User user = db.fetchUser(principal.getName());
return user;
}
}
Then inject the User like this:
#Inject
private User user;

How to Secure Spring Rest Services with Spring Sercurity and Angularjs?

I have a Spring MVC Server Backend with Rest-Services and an AngularJS WebFrontend.
i want to secure my spring mvc rest services but i want use java config.. and i have no idea how the configuration mus look like. Can someone help me with this ?
The only good implementation i have found is this : https://github.com/philipsorst/angular-rest-springsecurity
I use a postgrsDB and i wand store username and password and roles there, is the session token in the example from https://github.com/philipsorst/angular-rest-springsecurity only stored in cache and not in the db ?
At the moment i have a simple form login security, this was only for testing, but i did not use jsp i use only the spring mvc rest services and angularjs as webfrontend.. How can i modify my spring security code that it works with oauth2 like in the example from https://github.com/philipsorst/angular-rest-springsecurity ? I have at the moment only this two classes from spring security..
#Configuration
#EnableWebMvcSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter{
#Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("username").password("test").roles("User");
}
}
and then i register the securityConfig in my WebInitializer.
public class WebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
#Override
protected Class<?>[] getRootConfigClasses() {
return new Class<?>[]{ PersistenceContext.class,AppConfig.class,SecurityConfig.class };
} ....
But the roles and username/password should stored in a database.. must i use a special databse schema for spring security to store username,password and roles in my db ?
And can i implement it so that i can only add the #Secured Annotation(or any other Annotation) over one of my rest services with the role in it ? Like #Secured("UserRole")
Or ist Basic Authentification easier ? can i secure my rest services with basic authentification with rolemanagement !? if so we can use basic authentification..
Best regards
In order to load users you have to create an authentication manager and wire a UserDetailsService into that authentication manager. The following doc link gives a good overview of authentication manager, and the core components associated.
http://docs.spring.io/spring-security/site/docs/3.2.x/reference/htmlsingle/#core-services
So, to answer your first question...
But the roles and username/password should stored in a database.. must i use a special
databse schema for spring security to store username,password and roles in my db ?
You can do either. If you want, spring security can handle all the database side for you, you just have to supply a reference to a JDBC datasource which has Spring's schema design.
http://docs.spring.io/spring-security/site/docs/3.2.x/reference/htmlsingle/#core-services-jdbc-user-service
and
http://docs.spring.io/spring-security/site/docs/3.2.x/reference/htmlsingle/#appendix-schema
-or-
You can utilize your own schema by providing a UserDetailsService implementation of your own that will load from your own database schema. Here's some samples that can get you started with that approach.
<context:component-scan base-package="com.example.security" />
<security:global-method-security secured-annotations="enabled" pre-post-annotations="enabled"/>
<bean id="dao-provider" class="org.springframework.security.authentication.dao.DaoAuthenticationProvider"
p:userDetailsService-ref="myUserDetailsService"
p:passwordEncoder-ref="sha-pw-encoder"
p:saltSource-ref="my-salt-source" />
<bean id="sha-pw-encoder" class="org.springframework.security.authentication.encoding.ShaPasswordEncoder"
p:encodeHashAsBase64="true" />
<bean id="my-salt-source" class="org.springframework.security.authentication.dao.ReflectionSaltSource"
p:userPropertyToUse="salt" />
<security:authentication-manager>
<security:authentication-provider ref="dao-provider"/>
</security:authentication-manager>
Finally, provide an implementation of the UserDetailsService like so:
#Component("myUserDetailsService")
public class MyUserDetailsServiceImpl implements UserDetailsService {
//Reference to the spring JPA repository for loading users
private final UserRepository userRepository;
#Autowired
public MyUserDetailsServiceImpl(UserRepository userRepository) {
this.userRepository = userRepository;
}
#Override
#Transactional
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userRepository.findByName(username);
if (user != null) {
return new UserDetails() {
... //create the user details from the user object
}
} else {
String err = String.format("Failed to find username: %s in local database. Trying other auth mechanisms.", username);
throw new UsernameNotFoundException(err);
}
}
}
... for your second question:
And can i implement it so that i can only add the #Secured Annotation(or any other
Annotation) over one of my rest services with the role in it ? Like #Secured("UserRole")
Yes, the above configuration will allow you to use #Secured annotation by configuring the global-method-security.
And finally, yes all of this will still utilize basic authentication by default, but can be reconfigured to use digest authentication if necessary. I recommend giving a full read to the docs at http://docs.spring.io/spring-security/site/docs/3.2.x/reference/htmlsingle/ in order to really grasp what you're trying to do. But, this should get you on your way.

Resources