I am trying to write server side integration tests of my Spring Web Service Endpoint secured using
- Spring WS Security 2.1.2.RELEASE and
- WSS4j 1.6.9.
I am trying to follow Spring documentation http://static.springsource.org/spring-ws/sites/2.0/reference/html/server.html. With the setup that I have got so far, I can send a request payload
<myns:MyRequest xmlns:myns="...">
...
</myns:MyRequest>
using MockWebServiceClient as
mockWebServiceClient.sendRequest(withPayload(requestPayload)).andExpect(clientOrSenderFault());
which the integration test properly maps to the endpoint in the test context and I get a "Could not validate request: No WS-Security header found" error as expected.
Problem: Now the problem here is if I send a request in a SOAP envelope with a security header and body, I would get an endpoint not found exception.
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:myns="...">
<soapenv:Header>
...
</soapenv:Header>
<soapenv:Body>
<myns:MyRequest>
...
</myns:MyRequest>
</soapenv:Body>
</soapenv:Envelope>
since it will try to find an endpoint around "{http://schemas.xmlsoap.org/soap/envelope/}Envelope".
Is there a way to work around this problem?
The newer version of Spring WS Test which is 2.1 has two methods added in RequestCreaters: RequestCreators.withSoapEnvelope(Source soapEnvelope) and RequestCreators.withSoapEnvelope(Resource soapEnvelope) which allow sending SOAP envelopes for Integration testing. http://forum.springsource.org/showthread.php?135298-Integration-Testing-of-secure-Spring-Web-Service
Related
I am using Apigee as gateway to our application. Several applications will hit Apigee and Apigee will in-turn route the request to backend servers. Every incoming request will have a JWT token.
I want Apigee to pass that token to a auth server and auth server will validate if the token is valid or not.
If token is invalid(if auth server return any status other then 200) , I want Apigee to return 403 error as response to request else pass the request to backend server.
How can I implement this kind of shared flow? Is it even possible with Apigee ? Is there any better way to achieve this?
You can do that.
Create a shared flow for Authentication/Authorization which includes ServiceCallout policy which will make a call to auth server.
Based on result for Unauthorized/Bad request you can raise a fault response with help of RaiseFault.
If the response is OK it will proceed smooth to backend.
Sample shared flow.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<SharedFlowBundle revision="1" name="Auth">
<Policies>
<Policy>AssignVariableJwks</Policy> <!-- Assign Input values if needed via AssignMessage policy -->
<Policy>RequestAuthServer</Policy> <!-- Extrnal auth server call using ServiceCallout policy -->
<Policy>TokenNotFoundValidation</Policy> <!-- Validate response and raise fault if needed using RaiseFault policy -->
</Policies>
<Resources/>
<Spec/>
<subType>SharedFlow</subType>
<SharedFlows>
<SharedFlow>default</SharedFlow>
</SharedFlows>
</SharedFlowBundle>
For above shared flow create & attach required policies with logic and you're good to go.
I'm implementing GetReservation because TravelItineraryRead will soon be deprecated.
When creating a PNR, I get successful responses of GetReservation, but when I try to query the previously created PNR, Sabre WS rejects with "Viewership is restricted for the PNR, caused by [Viewership is restricted for the PNR (Unsupported security check), code: 700102, severity: MODERATE"
I'm connecting to Sabre WS via SOAP, in test endpoint https://sws-tls.cert.sabre.com.
The RQ I'm sending is:
<GetReservationRQ xmlns="http://webservices.sabre.com/pnrbuilder/v1_19" Version="1.19.0">
<Locator>XWYZA</Locator>
<RequestType>Stateless</RequestType>
<ReturnOptions PriceQuoteServiceVersion="3.2.0">
<SubjectAreas>
<SubjectArea>FULL</SubjectArea>
</SubjectAreas>
<ViewName>Full</ViewName>
<ResponseFormat>STL</ResponseFormat>
</ReturnOptions>
</GetReservationRQ>
I've tried with others Views and SubjectAreas, but I always get that response, what am I doing wrong?
The problem was that I needed to send RequestType: Stateful instead of Stateless
<GetReservationRQ xmlns="http://webservices.sabre.com/pnrbuilder/v1_19" Version="1.19.0">
<Locator>KDQPNP</Locator>
<RequestType>Stateful</RequestType>
<ReturnOptions PriceQuoteServiceVersion="3.2.0">
<SubjectAreas>
<SubjectArea>FULL</SubjectArea>
<SubjectArea>PRICE_QUOTE</SubjectArea>
</SubjectAreas>
<ViewName>Full</ViewName>
<ResponseFormat>STL</ResponseFormat>
</ReturnOptions>
</GetReservationRQ>
I am using QuicBook Premier Edition UK , I have a company file open inside QuickBook. Build a sample WebService provided in samples and host in IIS. Added that application in WebConnector by using qwc file in samples.
I understood the callback methods required by WebConnector in soap service.
• authenticate
• clientVersion
• closeConnection
• connectionError
• getLastError
• receiveResponseXML
• sendRequestXML
I have tested web service by using WebConnector by using Update Selected button and it gives response 'OK' . But I am still confused how to get started with soap service , samples include 3 Xml request
CustomerQuery,
InvoiceQuery and
BillQuery .
How I test these request and see the response by using service . Can anyone explain the steps required to get me started with my own request of Get all Sales Order.
Thanks
Here is the screenshot
Here is the Last Output.
Version:
2.0.0.1
Message:
OK
Description:
Via closeConnection(): CloseConnection called to application.
Response received from application = OK
Explanation:
After calling authenticate(...), the Web Connector will call the sendRequestXML(...) method.
The sendRequestXML(...) method is essentially the Web Connector's way of saying "Hey, what do you want me to do?"
You should respond with a qbXML request telling QuickBooks/the Web Connector to do something. For example, if you are trying to get sales orders from QuickBooks, you could respond with a SalesOrderQuery qbXML request, something like this:
<?xml version="1.0" encoding="utf-8"?>
<?qbxml version="8.0"?>
<QBXML>
<QBXMLMsgsRq onError="stopOnError">
<SalesOrderQueryRq requestID="2">
</SalesOrderQueryRq>
</QBXMLMsgsRq>
</QBXML>
The Web Connector will then send that request to QuickBooks, it will be processed, and the Web Connector will then call your receiveResponseXML(...) method.
The receiveResponseXML(...) method is essentially the Web Connector's way of saying "Hey, you told me to do something, I did it, and here's all of the data I got back: ... (big blob of XML from QuickBooks here)".
TLDR:
Return a qbXML request from the sendRequestXML method. A qbXML response will be sent to you in the receiveResponseXML method.
More notes:
Bigger explanation of the Web Connector here: http://www.consolibyte.com/docs/index.php/QuickBooks_Web_Connector_Overview
Lots of qbXML examples here: http://www.consolibyte.com/docs/index.php/Example_qbXML_Requests
Hundreds of pages of documentation in the QuickBooks SDK: https://developer.intuit.com/docs/0250_qb/0020_get_set_up/sdk_downloads
I try to intercept encrypted soap message with SoapUI. The reference site of WS Security with Wildfly 8 and Eclipse IDE is
https://docs.jboss.org/author/display/JBWS/WS-Security#WS-Security-Authenticationandauthorization
WS Security implementation is successful and the response message is encrypted successfully. The main key in WS security is manifest.mf. I add the following lines in manifest.mf file and it works well in Eclipse IDE.
Manifest-Version: 1.0
Dependencies: org.apache.cxf.impl, org.apache.ws.security services
Class-Path:
But in SoapUI application soap message encryption is failed. Me reference site is
http://www.soapui.org/soapui-projects/ws-security.html
http://blog.thilinamb.com/2011/02/invoking-secured-web-service-with.html
The SEI throws the following exception.
<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}ProtectionToken
{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}SymmetricBinding: Received Timestamp does not match the requirements
{http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702}EndorsingSupportingTokens: The received token does not match the endorsing supporting token requirement
{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}EncryptedParts: {http://schemas.xmlsoap.org/soap/envelope/}Body not ENCRYPTED
{http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702}SignedParts: {http://schemas.xmlsoap.org/soap/envelope/}Body not SIGNED</faultstring>
</soap:Fault>
</soap:Body>
</soap:Envelope>
The same exception was thrown in Eclipse IDE when I did not add the Dependancies line in manifest.mf file. Do you think those are related and have the same configuration problem?
I am looking forward to developed the Spring MVC + Apache Oltu + Linkedin integration example. In this example, you need to send Client ID and Client Secret to access the private resource from the Linked in Site.
First Step - we need to create App in Linkedin, follow the steps: http://codeboxr.com/how-to-create-linkedin-app.html
Once App is created, you need to make sure you've given value for the redirect URL.
In the java code I used
setScope("r_network w_share r_basicprofile")
setState("987654321")
When I used the following code:
request= new OAuthBearerClientRequest("https://api.linkedin.com/v1/people/").buildQueryMessage();
I get the following errror. Could anyone please?
Could not access resource: 401 <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<error>
<status>401</status>
<timestamp>1429554559432</timestamp>
<request-id>QJWNLL5PWX</request-id>
<error-code>0</error-code>
<message>Unknown authentication scheme</message>
</error>
An important thing, I am getting correct details below, but seems accessing private resources:
{"access_token":"SQXZVmVM05AOzDB_DdBm5iaJkrEC8oK-FgE1m1snEZbMcKUODew9I0ZQ6NWc8JtGDxTtEd-yyPul0FtF3-hG4ah6LZ9P4oaSVuhhtybRFmjfsZcJwOs5Lm2IDUGQnjmq5EdT3PVR7Bocq31VBXg0JtkQdImab945oicO_w2j6CjlByp-bWw",
"expires_in":5108376}
It seems that you're successfully obtaining an OAuth 2.0 access token, you'll need to pass access_token in a query parameter when making API calls. That's how OAuth 2.0 authentication is handled (OAuth 1.0 required the access token to be in the header whereas OAuth 2.0 relies on a query parameter).
For example:
GET https://api.linkedin.com/v1/people/~?oauth2_access_token={your-access-token}
Please follow the link, if in case requires more details: https://developer-programs.linkedin.com/forum/unknown-authentication-scheme
If you send token along with the request to access protected resources, then you should be getting the following details.
The corrected code snippet:
request= new OAuthBearerClientRequest
("https://api.linkedin.com/v1/people/~?oauth2_access_token="+oAuthResponse.getAccessToken()).
buildQueryMessage();
In My Example, I am getting the following HTTP 200 OK response, just wanted to show you..
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<person>
<id>LLIyXMKhNI</id>
<first-name>FirstName</first-name>
<last-name>LastName</last-name>
<headline>Spring Developer at Amazon</headline>
<site-standard-profile-request>
<url>https://www.linkedin.com/profile/view?id=154416688&authType=name&authToken=ipNL&trk=api*a4360331*s4423501*</url>
</site-standard-profile-request>
</person>
Hope this will be help you.