Spring 4 REST web-services not working with security - web-services

I am using Spring 4, with Spring Security 4 to secure web-services. A normal web-service worked fine without security. My secured web-services also seemed to work great working locally and with unit testing.
We are using the SiteMinder example, which means we have authentication happenind from a remote authority. This delivers a token to the browser when we login. We pass the authentication token with a request header, and this is pulled from customerUserDetailsService. That class and methods pull the token from the header, authenticates the user against that remote authority, and we get a username. From that username, we make a DAO call to our database to get the User Details and their Roles, which in the Spring Security Context uses the roles to grant authority. This is all working fine, and we get an authenticated user and we have thier roles/grantedAuthorities.
So, as previously stated, we are now just securing web-services with spring-security.xml to secure the web-services based on the role of the user. Again, this all seemed to work fine with unit testing. We had a token for a user who did not have access to web-sites and we correctly got back a 403 error. When we used a token for a user who did have the right role, was able to execute the web-service.
Now I am trying to deploy this into a new environment, and I am not having much luck.
So, I have a spring-security.xml that looks like:
<http use-expressions="true" auto-config="false" entry-point-ref="http403EntryPoint">
<!-- Additional http configuration omitted -->
<intercept-url pattern="/records/authorizedRecords" access="hasRole('portalUser')" />
<intercept-url pattern="/records/myCode" access="hasRole('portalUser')" />
<intercept-url pattern="/users/email" access="hasRole('appAdmin')" />
<custom-filter position="PRE_AUTH_FILTER" ref="openAmFilter" />
</http>
<beans:bean id="openAmFilter" class="org.springframework.security.web.authentication.preauth.RequestHeaderAuthenticationFilter">
<beans:property name="principalRequestHeader" value="openam_token"/>
<beans:property name="authenticationManager" ref="authenticationManager" />
</beans:bean>
<beans:bean id="preauthAuthProvider" class="org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider">
<beans:property name="preAuthenticatedUserDetailsService">
<beans:bean id="userDetailsServiceWrapper" class="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper">
<beans:property name="userDetailsService" ref="customUserDetailsService"/>
</beans:bean>
</beans:property>
</beans:bean>
<authentication-manager alias="authenticationManager">
<authentication-provider ref="preauthAuthProvider" />
</authentication-manager>
<beans:bean id="customUserDetailsService" class="com.agmednet.server.security.CustomUserDetailsService"></beans:bean>
<beans:bean id="http403EntryPoint" class="org.springframework.security.web.authentication.Http403ForbiddenEntryPoint">
When we tried access to:
<intercept-url pattern="/users/email/*" access="hasRole('appAdmin')" />
this did not seem to match:
/rest/users/email/myemail#someemail.com
so I changed it to:
<intercept-url pattern="/rest/users/email/*" access="hasRole('appAdmin')" />
And I get this from the log.
DEBUG: org.springframework.security.web.util.matcher.AntPathRequestMatcher - Checking match of request : '/rest/trials/integratedtrials'; against '/rest/users/email/*'
DEBUG: org.springframework.security.web.access.intercept.FilterSecurityInterceptor - Public object - authentication not attempted
DEBUG: org.springframework.security.web.FilterChainProxy - /rest/trials/integratedTrials reached end of additional filter chain; proceeding with original chain
DEBUG: org.springframework.security.web.access.ExceptionTranslationFilter - Chain processed normally
DEBUG: org.springframework.security.web.context.SecurityContextPersistenceFilter - SecurityContextHolder now cleared, as request processing completed
At this point, I know we have an authenticated user, the username, and the roles are listed right there in the logs. We seem to find a matching URL in the spring-security.xml, the URL matches, the roles match, and now I feel we should be executing the logic behind the web-service, but I get an error message:
Apache Tomcat/8.0.30 - Error report
/services/rest/users/email/myemail#someemail.com
The requested resource is not available.
I am absolutely floored here .... unsecured web-services work great. I have to be missing something? Is it with the word "rest" in the URL? Web-services have always worked when they were unsecured. I added security and add unit tests to test this all out, and now I am unsure of what happened?

The problem is that I am an idiot!!!!
In the /WEB-INF/web.xml file I had this defined:
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/api/*</url-pattern>
</servlet-mapping>
I suppose that is why when I call any RESTful web-services with:
/rest/users/email/myemail#someemail.com
it doesn't work.
But when I use:
/api/users/email/myemail#someemail.com
now it works.
Conclusion: I am an idiot!!!

Related

WSO2 APIM-Analytic service (version:2.6.0) is not able to send the alert emails

In order to test this function, I chosed Abnormal Request Count option, which is in Alert Management menu of Api Store, and added a restful api. Then I called this api for many times by Postman.
The carbon.log, which is in <API-M_ANALYTICS_HOME>/wso2/worker/logs, recorded the following error message:
[2020-10-19 11:03:36,094] ERROR {org.wso2.siddhi.core.stream.output.sink.Sink} - Error on 'APIM_ALERT_EMAIL_NOTIFICATION'. Dropping event at Sink 'email' at 'EmailNotificationStream' as its still trying to reconnect!, events dropped '<strong>Message:</strong>A request from a new IP (10.9.16.77) detected by user:admin#carbon.super using application:devMap owned by admin#carbon.super. <br><br> <strong>Type:</strong>UnusualIPAccess <br><br> <strong>AlertTimestamp:</strong>2020-10-19 11:03:35'
[2020-10-19 11:06:10,307] ERROR {org.wso2.siddhi.core.stream.output.sink.Sink} - Error on 'APIM_ALERT_EMAIL_NOTIFICATION'. Dropping event at Sink 'email' at 'EmailNotificationStream' as its still trying to reconnect!, events dropped '<strong>Message:</strong>Abnormal request count detected during last minute using application devMap owned by admin#carbon.super for api :全球风向查询, abnormal request count:9. <br><br> <strong>Type:</strong>AbnormalRequestsPerMin <br><br> <strong>AlertTimestamp:</strong>2020-10-19 11:06:10'
About detailed configuration, I referred the following links:
Configuring Alerts:
https://docs.wso2.com/display/AM260/Configuring+Alerts#ConfiguringAlerts-ConfiguringalertsviatheStore
Enabling Notifications:
https://docs.wso2.com/display/AM260/Enabling+Notifications
According to these documents, I did the following things:
1.Open the <API-M_ANALYTICS_HOME>/conf/worker/deployment.yaml file to configure the sender email address. The sample code is shown below:
siddhi:
extensions:
...
-
extension:
name: email
namespace: sink
properties:
username: abcd#163.com
address: abcd#163.com
password: xxxx
...
2.Go to the <API-M_ANALYTICS_HOME>/resources/apim-analytics/ directory. Copy the APIM_ALERT_EMAIL_NOTIFICATION.siddhi file and paste it in the <API-M_ANALYTICS_HOME>/wso2/worker/deployment/siddhi-files directory.
3.Set the email server configurations in the <API-M_HOME>/repository/conf/output-event-adapters.xml file under the section.
<adapterConfig type="email">
<!-- Comment mail.smtp.user and mail.smtp.password properties to support connecting SMTP servers which use trust
based authentication rather username/password authentication -->
<property key="mail.smtp.from">abcd#163.com</property>
<property key="mail.smtp.user">abcd</property>
<property key="mail.smtp.password">xxxx</property>
<property key="mail.smtp.host">smtp.163.com</property>
<property key="mail.smtp.port">25</property>
<property key="mail.smtp.starttls.enable">true</property>
<property key="mail.smtp.auth">true</property>
<!-- Thread Pool Related Properties -->
<property key="minThread">8</property>
<property key="maxThread">100</property>
<property key="keepAliveTimeInMillis">20000</property>
<property key="jobQueueSize">10000</property>
</adapterConfig>
4.Log in to the Management Console and click Main > Resource > Browse. Browse to the /_system/config/apimgt/applicationdata/tenant-conf.json file and click Edit as Text.Set the NotificationsEnabled property to true as shown below:
"NotificationsEnabled":"true",
"Notifications":[{
"Type":"new_api_version",
"Notifiers" :[{
"Class":"org.wso2.carbon.apimgt.impl.notification.NewAPIVersionEmailNotifier",
"ClaimsRetrieverImplClass":"org.wso2.carbon.apimgt.impl.token.DefaultClaimsRetriever",
"Title": "Version $2 of $1 Released",
"Template": " <html> <body> <h3 style=\"color:Black;\">We’re happy to announce the arrival of the next major version $2 of $1 API which is now available in Our API Store.</h3>Click here to Visit WSO2 API Store</body></html>"
}]
}
]
I've also checked APIM_ALERT_EMAIL_NOTIFICATION.siddhi:
#App:name("APIM_ALERT_EMAIL_NOTIFICATION")
#App:description('Send email to all the subscribers of a particular alert')
#source(type="inMemory", topic="APIM_EMAIL_NOTIFICATION", #map(type='passThrough'))
define stream EmailAlertStream (
type string,
message string,
alertTimestamp string,
emails string);
#sink(type='email', content.type="text/html", #map(type ='text', #payload('<strong>Message:</strong>{{message}} <br><br> <strong>Type:</strong>{{type}} <br><br> <strong>AlertTimestamp:</strong>{{alertTimestamp}}')),subject='Alerts from WSO2 APIM Analytics',to='{{emails}}')
define stream EmailNotificationStream (
type string,
message string,
alertTimestamp string,
emails string);
from EmailAlertStream
select *
insert into EmailNotificationStream;
As you can see, there is nothing special.
Have I missed anything to do? I don't know what the problem is, please help me.
As per the exceptions you received. Looks like there are issues with connecting to the SMTP server. Can you please check the configurations and check there are any restrictions to use your email.
ex: in Gmail, you have to enable 'untrusted applications' to access Gmail.
I've found the reason of this problem.
By reading the source code (EmailSink.java), I know the information of SMTP Server should be configured in APIM_ALERT_EMAIL_NOTIFICATION.siddhi, otherwise the analytic server is going to use smtp.gmail.com by default.

mule - web service consumer (soap) always returns null

I am using the Zuora soap API. I am attempting to perform a query. I don't get any errors but the results are always null when I output the payload to log. What am I doing wrong? (the query I provide below should return 320 records, which is what I get if I execute the same query in a local non-mule test script)
This is the section of the flow.
I set the zoql query to flowVars (flowVars.query). For example : select id from Account WHERE updatedDate > '2016-06-24T23:00:00-06:00'
I use dataweave to create the xml payload (dw provided below)
I execute the query (web service consumer app xml details provided below)
DataWeave to set payload:
%dw 1.0
%output application/xml
%namespace ns0 http://api.zuora.com/
---
{
ns0#query: {
ns0#queryString: flowVars.query
}
}
Web Service Consumer app xml
<ws:consumer config-ref="ZuoraWebServiceConsumer" operation="query" doc:name="query_zuora"/>
ZuoraWebServiceConsumer config details:
<ws:consumer-config name="ZuoraWebServiceConsumer" wsdlLocation="zuora.a.49.0-sandbox.wsdl" service="ZuoraService" port="Soap" serviceAddress="https://apisandbox-api.zuora.com" doc:name="Web Service Consumer">
<ws:security>
<ws:wss-username-token username="myusername.here" password="mypassword.here" passwordType="TEXT" />
</ws:security>
</ws:consumer-config>
And the WSDL:
https://www.dropbox.com/s/fkrppvv7i5s1a4w/zuora.a.49.0-sandbox.wsdl?dl=0
After working with MuleSoft Support, it was discovered there is a bug with the Zuora connector. When Zuora returns an invalid session error, the Zuora connector is not catching it, destroying the connection from the pool, and initiating a new connection. MuleSoft has confirmed the bug.

Coldfusion - HTTPS error / X.509 ws-security

I'm very new to SOAP, and this is my first project. I am trying to connect to a HTTPS WSDL in order to pull some information on my webpage.
There is a certificate setup ready for both local server connect with the service provider server. There is a response when I try to connect the https webservice, so I believe there is no connection issue between both server :
Here is the SOAPUI sample given from the third party technical team :
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:soap="http://soap.ipr.tfp.com/">
<soapenv:Header/>
<soapenv:Body>
<soap:create>
<arg0>
<attribute_1>abc</attribute_1>
<attribute_2></attribute_2>
<attribute_3>abc123</attribute_3>
<attribute_4>abc234</attribute_4>
<attribute_5></attribute_5>
</arg0>
</soap:create>
</soapenv:Body>
</soapenv:Envelope>
Below is my cfm code used to connect the Webservice :
<cfscript>
ws = CreateObject("webservice", [HTTPS URL]?wsdl);
//show web service methods for debugging purposes
writeDump(ws);
// construct arguments
args = {attribute_1="abc"
, attribute_2=""
, attribute_3="abc123"
, attribute_4="abc234"
, attribute_5=""
};
// call the method
result = ws.create(arg0=args);
writeDump(result)
</cfscript>
Issue :
I'm getting below error message when execute my cfm script :
Cannot perform web service invocation create.
The fault returned when invoking the web service operation is:
AxisFault
faultCode: {http://schemas.xmlsoap.org/soap/envelope/}Server
faultSubcode:
faultString: These policy alternatives can not be satisfied:
{http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702}AsymmetricBinding: Received Timestamp does not match the requirements
{http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702}X509Token: The received token does not match the token inclusion requirement
{http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702}X509Token
{http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702}InitiatorToken
{http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702}RecipientToken
{http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702}IncludeTimestamp: Received Timestamp does not match the requirements
{http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702}SignedParts: {http://schemas.xmlsoap.org/soap/envelope/}Body not SIGNED
{http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702}EncryptedParts: {http://schemas.xmlsoap.org/soap/envelope/}Body not ENCRY...
Questions :
Is this error related to the SSL certificate setup in the ColdFusion keystore?
Anything wrong with my CFM script? Refer to the SOAPUI sample, the xml format is `[arg0] --> [attribute_1], [attribute_2] and so on. Can I pass the attributes this way?
result = ws.create(arg0=args);
The same service works from SoapUI tool. Am I missing anything here?
Thank you for your time. Your help is appreciated.
2016-05-30 - Update -
I tried to use the CFHTTP tag to submit the XML, but it seemed to return a differenct error:
<cfhttp
url = "[HTTPS URL]?wsdl"
method ="post"
result ="httpResponse"
charset ="utf-8">
<cfhttpparam
type="header"
name="accept-encoding"
value="no-compression"
/>
<cfhttpparam
type="xml"
value="#trim( soapBody )#"
/>
</cfhttp>
Error:
Here is the error message in the file content :
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<soap:Fault>
<faultcode>soap:Server</faultcode>
<faultstring>These policy alternatives can not be satisfied:
{http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702}
AsymmetricBinding: Received Timestamp does not match the requirements
{http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702}
X509Token: The received token does not match the token inclusion requirement
{http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702}
X509Token
{http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702}
InitiatorToken
{http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702}
RecipientToken
{http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702}
IncludeTimestamp: Received Timestamp does not match the requirements
{http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702}
SignedParts: {http://schemas.xmlsoap.org/soap/envelope/}
Body not SIGNED
{http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702}
EncryptedParts:
{http://schemas.xmlsoap.org/soap/envelope/}
Body not ENCRYPTED
</faultstring>
</soap:Fault>
</soap:Body>
</soap:Envelope>
The error message seems similar to cfobject tag. When I read closely in the error message, it seemed related with the X.509 ws-security encryption where the SOAP content needs to encrypted before send to the Web service request.
After did some research, the encryption flow seem work as below:
Save SOAP content into temp folder.
Used Java Class file to encrypt the SOAP content into X.509 ws-security format.
Sent new encrypted SOAP content to Webservice.
I have no idea how CF works with Java class files. Has anyone done the same encryption conversion before?
In your code to connect to web service, change
ws = CreateObject("webservice", [HTTPS URL]);
to
ws = CreateObject(
"webservice",
"[HTTPS URL]",
{wsversion="1"}
);
in case only Axis 1 works for you.
Also check at the other end, if your using ColdFusion to expose the web service make sure is set up for Axis 1.

MVC 5 + ASP Identity authorization - sharing cookie in subdomains

I have local website with subdomains like:
localhost:55307
aaa.localhost:55307
bbb.localhost:55307
It works perfectly except authorization - if I log in in localhost:55307 I'm not logged in aaa.localhost:55307 because my subdomains are treated as separate domain. I looking for solution but I can't find any for Asp Identity (Form authentication in MVC 4 it's useless).
Based on some questions and answers in SO I did:
Edit CookieAuthenticationOptions class in Startup.Auth.cs as below:
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/Account/Login"),
CookieDomain = ".localhost",
ExpireTimeSpan = new TimeSpan(0,12,0,0,0),
Provider = new CookieAuthenticationProvider
{
// Enables the application to validate the security stamp when the user logs in.
// This is a security feature which is used when you change a password or add an external login to your account.
OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
validateInterval: TimeSpan.FromMinutes(30),
regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
}
Get MachineKey from IIS Manager and add to web.config:
<system.web>
<authentication mode="None" />
<machineKey validationKey="61D42DE996486DEA64CEA26C0373C547E0D07108789662C2D2E15210A65C475925055009D962FEB3D5D93E9BEA3E3717187F1BCBF63E386EB198F641E6157044" decryptionKey="06CF7C1C31BDBD4E7056D0F3531BE253E98A658B50974155" validation="SHA1" decryption="Auto"/>
<compilation debug="true" targetFramework="4.5.2" />
<httpRuntime targetFramework="4.5.2" maxRequestLength="1073741824" />
</system.web>
Now i can login but cookies aren't shared - I still logged in one subdomain.
PS. I now that there is a lot of similar questions in StackOberflow but no one of them is about MVC 5 and ASP Identity and no of them got solutions.

Problems with Oracle Membership Provider and Framework 4

I'm having serious problems with creating a Web service in Visual Studio 2010 (Framework 4).
Anyway, I have to use a Oracle membership provider (I have installed "Oracle Providers for ASP.NET 4 11.2.0.2.0', which modifies the framework's machine.config), but I can not connect to the membership.
My code in web.config is as follows:
<configuration>
<connectionStrings>
<remove name="OraAspNetConString"></remove>
<add name="OraAspNetConString" connectionString="User Id=USUARIO;Password=PASSWORD;Data Source=DATABASENAME;" providerName="Oracle.DataAcces.Client"/>
</connectionStrings>
<system.web>
<membership defaultProvider="OracleMembershipProvider" userIsOnlineTimeWindow="30"/>
<roleManager defaultProvider="OracleRoleProvider" enabled="true" cacheRolesInCookie="true" cookieName=".ASPROLES" cookieTimeout="30" cookiePath="/" cookieRequireSSL="false" cookieSlidingExpiration="true" cookieProtection="All"/>
<authentication mode="None"/>
<authorization>
<allow users="*"/>
</authorization>
I also added the reference 'System.Web.ApplicationServices' to my project.
To test the connection to the membership of Oracle I have put this code in one of the OperationContract that has my web service:
MembershipUserCollection userC = Membership.GetAllUsers();
sample.StringValue += " - " + userC.Count;
bool resp = Membership.ValidateUser(id, id2);
The obtained MembershipUserCollection always appears without users. UserC.Count always equals zero.
The parameters 'id' and 'id2', username and password respectively, are used to validate (that is a poor use, I know) but always returns false.
Anybody can help me with this?
Thanks a lot.
PD: Authentication mode is 'None', I've tried with 'Forms' and still not working.
Problem solved.
I needed to put the name of the application (applicationName) on the label of the membership and role manager providers (in the file machine.config).
:-)