Adding Global Mediation extension in WSO2 APIM 3.2.0 - wso2-api-manager

I have configured a global mediation extension as per the document. The file global_ext.xml is placed under wso2am-3.2.0\repository\deployment\server\synapse-configs\default\sequences.
<sequence xmlns="http://ws.apache.org/ns/synapse" name="WSO2AM--Ext--In">
<property name="token" expression="get-property('transport', 'Authorization')"/>
</sequence>
public boolean handleRequest(MessageContext messageContext) {
String accessToken = (String) messageContext.getProperty("token");
However, the token property is not available in the MessageContext properties. Any idea what went wrong here? Or how to fetch the value of token in handler?

If the handleRequest(MessageContext messageContext) method is some CustomHandler class which extends AbstractHandler (Writing Custom handlers), then it won't work as you expect.
It is because the Handlers are running before sequence. The message flow is described in WSO2 documentation: Message flow in the API Manager Gateway and looks like that:
So you can set some property in handler and read in sequence, the other way doesn't work.

Related

Spring-Security-OAuth2 - how to add fields to access token request?

I have a Spring Boot application, that is using Spring Security with OAuth 2.0. Currently, it is operating against an Authentication Server based on Spring Example code. However, running our own Auth Server has always been a short-term target to facilitate development, not a long-term goal. We have been using the authorization_code grant type and would like to continue using that, irrespective of the Auth Server implementation.
I am attempting to make changes to use OAuth 2.0 Endpoints in Azure Active Directory, to behave as our Authentication Server. So far, I have a successful call to the /authorize endpoint. But the call to get the /token fails with an invalid request error. I can see the requests going out.
It appears that parameters that Azure states as mandatory are not being populated in the POST request. Looking at the Azure doco, it expects the client_id to be defined in the body of the message posted to the endpoint, and that is not added, by default, by Spring.
Can anyone point me in the right direction for how I can add fields to the Form Map that is used when constructing the Access Token request? I can see where the AccessTokenRequest object is being setup in OAuth2ClientConfiguration....
#Bean
#Scope(value = "request", proxyMode = ScopedProxyMode.INTERFACES)
protected AccessTokenRequest accessTokenRequest(#Value("#{request.parameterMap}")
Map<String, String[]> parameters, #Value("#{request.getAttribute('currentUri')}")
String currentUri) {
DefaultAccessTokenRequest request = new DefaultAccessTokenRequest(parameters);
request.setCurrentUri(currentUri);
return request;
}
Should I be trying to define the map in a request.parameterMap spring property? If so, I'm not too sure how that works.
Or should I be using one of the interfaces defined in the AuthorizationServerConfigurerAdapter class?
I have the information to include when sending the AccessTokenRequest, I just don't know the best way to configure Spring to include it? Thanks for any help.
Actually, I found this out. I needed to change the client authentication scheme. Simply adding the following to my application properties added the client_id to the form....
security.oauth2.client.clientAuthenticationScheme=form
If you're using yaml, then yaml-ize it. Thank you Spring!

Spring MVC Security Token based Authentication

Can anyone please help me in this.
I have been assigned to secure an existing web application.
Issue:
when a user already logs into the application (that means the session is active), at that time an attacker can guess the input fields and save url and create a similar page and send a hyper link. If the user clicks on that link, it will not go through javascript, rather it will hit the spring controller. Since the session is active, it will save the attackers data into the database.
Here is what we are using now.
1) Spring Security
<http auto-config="true">
<intercept-url pattern="/**" access="ROLE_ADMIN, ROLE_HR" />
<custom-filter position="PRE_AUTH_FILTER" ref="siteminderFilter" />
</http>
<beans:bean id="siteminderFilter" class="com.mywbsite.security.UserFilter">
<beans:property name="authenticationManager" ref="authenticationManager" />
<beans:property name="continueFilterChainOnUnsuccessfulAuthentication" value="false"/>
</beans:bean>
This method is called when user logs into the application first time
protected Object getPreAuthenticatedPrincipal(HttpServletRequest request) {
String userId = request.getHeader("uid");
logger.info("<<<<<<<<<<<<<<<<<<<<<userId>>>>>>>>>>>>>>>>>>>>>>> : "+userId);
return userId;
}
This method is called when user does anything which calls any controller/java
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
System.out.println(request.getParameter(BaseConstants.DV_USER_SESSION_IDENTIFIER));
logger.info(request.getParameter(BaseConstants.DV_USER_SESSION_IDENTIFIER));
logger.info("Existing the UserFilter.doFilter method...");
}
Solution:
In controller/filter I have to identify if the request is coming from my application or from anywhere else.
Here is what I am thinking to implement.
Create a random token inside getPreAuthenticatedPrincipal() method and store that in session.
Get the variable from session and put in a hidden variable in jsp
When user does any action, pass the hidden variable with value and pass to controller as request parameter.
In Controller/Filter get the random value from session and get the hidden value from request parameter. Now compare. If it matches, then do normal operation, else throw error page.
Now my concern is if I implement the above solution, I have to write hidden variable code in every jsp and pass to controller in each request and request parameter.
Can you please help me how to make it easy. Thanks in advance
I resolved the above issue by using Spring CSRF. I faced an issue while implementing CSRF. The issue was CSRF was creating 2 tokens. It took long time (at least 1 day) to find the root cause. The root cases was I was trying to get the csrf token value in my Fiter and print it using below code. So once I wrtie the request.getAttribute("_csrf"), it creats a new token. So I just delted the below lines from my csrf and just did what it was described in above spring csrf link. It worked
// CsrfToken token = (CsrfToken) request.getAttribute("_csrf");
// System.out.println(">>>>>>>>>>UserFilter.getPreAuthenticatedPrincipal() CSRF Token: " + token.getToken());

Cannot register a filter to the CXF bundle in my bundle

I am having trouble using the Pax Web Whiteboard service to register a javax.servlet.Filter to a running JaxRS endpoint registered through CXF. I have tried a few different approaches, namely registering the Filter as a service, and using the org.ops4j.pax.web.service.WebContainer to register the filter directly.
For my test, i booted karaf, and installed pax-web, webconsole, cxf and the pax-web whiteboard service.
I the registered a bundle with a blueprint:
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jaxrs="http://cxf.apache.org/blueprint/jaxrs"
xmlns:cxf="http://cxf.apache.org/blueprint/core"
xsi:schemaLocation="
http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd
http://cxf.apache.org/blueprint/jaxrs http://cxf.apache.org/schemas/blueprint/jaxrs.xsd
http://cxf.apache.org/blueprint/core http://cxf.apache.org/schemas/blueprint/core.xsd
">
<cxf:bus>
<cxf:features>
<cxf:logging/>
</cxf:features>
</cxf:bus>
<jaxrs:server id="webfiltersample" address="/webfilter">
<jaxrs:serviceBeans>
<ref component-id="serviceBean" />
</jaxrs:serviceBeans>
</jaxrs:server>
<service id="servletFilterService" interface="javax.servlet.Filter">
<service-properties>
<entry key="filter-name" value="BasicWebFilter"/>
<entry key="urlPatterns" value="/*"/>
<entry key="initParams" value=""/>
</service-properties>
<bean class="test.webfilter.BasicWebFilter"/>
</service>
<bean id="serviceBean" class="test.webfilter.WebFilterSample" init-method="init" destroy-method="destroy">
<property name="bundleContext" ref="blueprintBundleContext"/>
</bean>
</blueprint>
However, this filter is never called. I have tried both using servlet names and urlpatterns, going so far as to attempt the urlpattern /*
I then tried a slightly different approach, removing the service declaration from the blueprint, and adding the filter directly though the init method of the blueprint instead:
public void init(){
logger.info("Starting Sample");
filter = new WebFilter();
ServiceReference<WebContainer> ref = bundleContext.getServiceReference(BasicWebFilter.class);
WebContainer container = bundleContext.getService(ref);
logger.info("Registering "+ filter + " with "+ container);
container.registerFilter(filter, new String[]{"/cxf/*"}, new String[]{""}, null, null);
bundleContext.ungetService(ref);
}
The method is indeed called, as reflected by the log statements, but the filter is still not executed.
So am i completely wrong in how this works? My "Application" is really just an endpoint registered to the CXF servlet. This part is working, and i can call the REST services defined therein. But no matter what i do, the filter is not executing. I am working with a few libraries here that i don't really know that well (Servlets/Filters, Pax-Web and the Writeboard extender) do i have no idea why exactly this isn't working? My guess is that there are different httpcontexts for each bundle, and that i can't simply register a filter for another bundle (CXF) in my own test bundle.
If this is true, can someone tell me how to properly go about this problem? I could get the CXF bundles bundlecontext and register the filter to that, but that seems like a terrible horrible hack.
If that is NOT the case, can someone tell me why this is not working?
You are right, every bundle should have it's own httpContext. With Pax-Web it's possible to have shared httpContextes. For this you need to enable it for the bundle initially registering the httpContext. Though in this case it's the cxf bundle that does take care of it. As the shared context is a pax-web only feature (till v6 where OSGi R6 is implemented), this won't be added to cxf as cxf tends to rely on the smallest possible solution, which is the HttpService.
Basically even though it's possible to share httpContextes with different bundles, it's not possible for you with this scenario.
I propose to use JAAS instead of shiro as a way to login and store the authentication information. You can then use this in shiro as well as in other security implementations to do the authorization.
For CXF there is a JAASLoginFeature. It can receive basic auth as well as UserNameToken. See https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=42568988
This also has the advantage that it works the same way as the standard karaf authentication. So by default you can define users and groups in etc/users.properties but you can also for example attach karaf to ldap.
If you use blueprint then you can use blueprint-authz do role based authorization using annotations. See https://github.com/apache/aries/tree/trunk/blueprint/blueprint-authz and https://github.com/apache/aries/blob/trunk/blueprint/blueprint-itests/src/test/java/org/apache/aries/blueprint/itests/authz/testbundle/impl/SecuredServiceImpl.java

How do you create CouchDB Views using Spring Bean Deployment with LightCouch

I am using Spring-MVC LightCouch and CouchDB and I have custom Views that need to be inserted into the DB on deployment. I have found the LightCouch has a method for pulling documents "from desk" as noted on their website:
DesignDocument designDoc = dbClient.design().getFromDesk("example");
Response response = dbClient.design().synchronizeWithDb(designDoc);
This Works good from within JAVA code, however I need to be able to do it in the Spring ApplicationContext.xml I have more than one so I would like to mimick the call of:
dbClient.dessign().synchronizeAllWithDB()
How would I do this in the bean definition of the ApplicationContext I already have this:
<bean id="dbClient" class="org.lightcouch.CouchDbClient" lazy-init="false" destroy- method="shutdown">
<constructor-arg value="couchdb.properties" />
</bean>
It seems you can't do it with Spring xml config, as the init method falls under a different instance; that is returned by the call to design() factory method. Maybe you can try Java code equivalence, i.e. #PostConstruct.
I ended up having to make a bean that synchronized the database on init and created that when the app starts

How to obtain OSGi service references from a Servlet that is registered in OSGi HttpService?

It seems natural that a HttpServlet running in OSGi environment (i.e. registered in OSGi HttpService) would want to call some OSGi services to accomplish it's tasks. The question is how to obtain references to these OSGi service inside the servlet.
One way would be to inject dependencies into the HttpServlet instance that is being registered to the OSGi HttpService like this:
MyServlet servlet = new MyServlet();
servlet.setFooService(fooService);
httpService.registerServlet("/myservlet", servlet, initparams, context);
I'm not sure if this is a valid approach since in non-OSGi environment the servlet life-cycle is managed by the Web Container and hence the service reference would not be injected for the servlet instances created later on.
There is another way to solve this when using PAX Web as an implementation of the OSGi HttpService. PAX Web exports the OSGi BundleContext into the ServletContext as a special attribute "osgi-bundlecontext". The BundleContext can then be used to obtain necessary service references:
public void init(ServletConfig servletConfig) throws ServletException {
ServletContext context = servletConfig.getServletContext()
BundleContext bundleContext =
(BundleContext) context.getAttribute("osgi-bundlecontext");
ServiceReference serviceRef =
bundleContext.getServiceReference("com.foo.FooService")
}
However this approach is rather ugly and ties you to a concrete implementation of the OSGi HttpService. Do you know any other (and possibly better) solution to this problem?
If you use a setter for the dependency on the service, as you have shown, it can work outside of OSGi as well. You just need to use some other dependency injection mechanism. If there is none, you could provide a subclass that initializes the servlet using JNDI lookups or from the servlet context.
public class MyServlet_AdapterForMissingDI extends MyServlet{
public void init(ServletConfig config){
setFooService(getItFromSomewhere());
}
}
The point being that if you have DI capabilities that can inject setFooService, you can just use the same servlet in OSGi and elsewhere, if you do not (and still want to support this case), you provide an adapter.
On a related note, check out Felix SCR to configure your object's dependencies, and Pax Web Extender Whiteboard, which takes care of hooking your servlet up with the HttpService.
Specifically, without SCR and Whiteboard, you need to think about the case when the fooService becomes unavailable later, or the HttpService gets started after your servlet.
In these cases your servlet would have a reference to a dead service that prevents the bundle from being garbage-collected, or your servlet would not be registered with the HttpService.
Update: Here is the SCR descriptor I use for one of my servlets. SCR handles servlet instantiation, life-cycle, registration (via Whiteboard), and dependencies. There is no OSGi-specific code in the servlet. There is not even the need for a BundleActivator anymore (SCR registers all services):
<component name="oracle.statusServlet" >
<implementation class="mypackage.DataSourceStatusServlet"/>
<property name="service.description" value="Oracle DataSource status servlet" />
<property name="alias" value="/OracleDataSourceStatus" />
<property name="servlet-name" value="Oracle DataSource status servlet" />
<service>
<provide interface="javax.servlet.Servlet" />
</service>
<reference name="DATASOURCES"
interface="javax.sql.DataSource"
cardinality="0..n" policy="dynamic"
bind="bindDataSource" unbind="unbindDataSource"/>
</component>
The dependencies for the servlet are specified in the reference tag. SCR will do the service lookup and binding.
May be an old post and you already might have got the answer..
Are you launching felix or whatever OSGi container yourself. If that is the case you can set the bundle context as an attribute to the servlet context.
Whats wrong in using an http service by PAX. ultimately the thread management and other aspects are taken care of by the servlet container in which you run this http service.
You could inject the services into some object, which is then queried by the servlets.

Resources