How do I change my WCF's FederationMetadata.xml file for various deployments? - wcf

We have an ADFS 2.0 installation that's working well for our MVC apps in our various environments. I believe it uses "passive authentication" (I'm still getting used to the proper terminology) - it definitely is where it redirects the user to our adfs proxy if the user is not logged in and adfs redirects the user back to our MVC app once they are logged in.
We are now beginning to expose some secured web services and want to tap into this same authentication system. My understanding is that I want to use ws2007FederationHttpBinding as my binding to do this. I believe I have my WCF's web.config all setup for this but my struggle is now centered around the FederationMetadata.xml file.
Looking at this file, I see some things that obviously need to change, such as entityID="http://localhost/UserServices" and the certificate. Then there are some things that I have no clue what they are and if they need to change or not, such as EntityDescriptor ID="_2b510fe8-98b8...... and <ds:SignatureValue>CZe5mEu19/bDNoZrY8f6C559CJ........
Where can I get a better understanding on how I should be managing this file for my various environments? I have the following environments hosting these services that we'll be deploying to one way or another:
Individual developer workstations (3x for now, more later)
A shared Dev environment for people writing apps against these services but not necessarily modifying the services
QA
Staging
Production (3 different environments with different certs/domains/etc.)
As such, we have a fairly streamlined process in place managing our web.config files in the different environments using transforms and finding/replacing certain tokens, so I'd like to do the same thing with this xml file. So ultimately, all I'm looking for is some understanding in what changes are necessary when managing this FederationMetadata.xml file for my various environments.
My current FederationMetadata.base.xml file is below and I BELIEVE this is about right (I just need names/roles) and I just need to intelligently replace the various tokens, such as ~RootServiceUrlTokenToReplace~, in here:
<?xml version="1.0" encoding="utf-8"?>
<EntityDescriptor ID="~EntityDescriptorIdTokenToReplace~" entityID="http://~RootServiceUrlTokenToReplace~" xmlns="urn:oasis:names:tc:SAML:2.0:metadata">
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
<ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" />
<ds:Reference URI="#~ReferenceURITokenToReplace~">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" />
<ds:DigestValue>~DigestValueTokenToReplace~</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>~SignatureValueTokenToReplace~</ds:SignatureValue>
<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
<X509Data>
<X509Certificate>~CertificateTokenToReplace~</X509Certificate>
</X509Data>
</KeyInfo>
</ds:Signature>
<RoleDescriptor xsi:type="fed:ApplicationServiceType" protocolSupportEnumeration="http://schemas.xmlsoap.org/ws/2005/02/trust http://docs.oasis-open.org/ws-sx/ws-trust/200512" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:fed="http://docs.oasis-open.org/wsfed/federation/200706">
<KeyDescriptor use="encryption">
<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
<X509Data>
<X509Certificate>~CertificateTokenToReplace~</X509Certificate>
</X509Data>
</KeyInfo>
</KeyDescriptor>
<fed:ClaimTypesRequested>
<auth:ClaimType Uri="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name" Optional="true" xmlns:auth="http://docs.oasis-open.org/wsfed/authorization/200706" />
<auth:ClaimType Uri="http://schemas.microsoft.com/ws/2008/06/identity/claims/role" Optional="true" xmlns:auth="http://docs.oasis-open.org/wsfed/authorization/200706" />
</fed:ClaimTypesRequested>
<fed:TargetScopes>
<EndpointReference xmlns="http://www.w3.org/2005/08/addressing">
<Address>http://~RootServiceUrlTokenToReplace~</Address>
</EndpointReference>
</fed:TargetScopes>
<fed:ApplicationServiceEndpoint>
<EndpointReference xmlns="http://www.w3.org/2005/08/addressing">
<Address>http://~RootServiceUrlTokenToReplace~</Address>
</EndpointReference>
</fed:ApplicationServiceEndpoint>
</RoleDescriptor>
</EntityDescriptor>

A WIF-based application's FederationMetadata.xml is not related to the claims-based web services it offers.
(A URL pointing to) FederationMetadata.xml is used by AD FS, to automatically update the information to be used in a Relying Party Trust. AD FS can for example regularly query this URL, and update the Relying Party Trust information accordingly.
The information about a web service (claims-based or otherwise), i.e., its metadata, is published as a WSDL document. In a WCF-based service this is a URL that often looks like this: http://myhost.example.com/appName/serviceName.svc?wsdl. That WSDL document often does not exist as a physical file, but is automatically generated by WCF.

I have found a partial answer to my question in this blog post. I'm looking into it more to discover whether or not this answers all of my questions. I just found it. Apparently I do need to change my EntityID (that contains the URL) as I redeploy this to different environments but the SignatureValue contains a hash of that URL (among other things?) so by modifying the URL, I invalidate the SignatureValue and it needs to be regenereated. Apparently this FederationMetadata Generator can help me with this.

Related

CRM Online 2015 Authentication Raw Soap

Hi and thanks for taking this time to look,
I've recently been asked to investigate integration using CRM Online 2015, I've come across some issues trying to Authenticate using Raw SOAP requests.
While I know there's other ways to authenticate, predominantly the using the CRM SDK, my iron will is pushing me to find a solution using Raw SOAP.
I came across a very helpful blog by Jason Lattimer: http://jlattimer.blogspot.co.uk/2015/02/soap-only-authentication-using-c.html
Following this sample, I successfully authenticated with a Trial CRM account using RAW SOAP... Great... Done... I was wrong.
As soon as I pointed this sample at the CRM development environment I got a SOAP error:
<?xml version="1.0" encoding="utf-8" ?>
<S:Envelope xmlns:S="http://www.w3.org/2003/05/soap-envelope" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:wst="http://schemas.xmlsoap.org/ws/2005/02/trust" xmlns:psf="http://schemas.microsoft.com/Passport/SoapServices/SOAPFault">
<S:Body>
<S:Fault>
<S:Code>
<S:Value>S:Sender</S:Value>
<S:Subcode>
<S:Value>wst:FailedAuthentication</S:Value>
</S:Subcode>
</S:Code>
<S:Reason>
<S:Text xml:lang="en-US">Authentication Failure</S:Text>
</S:Reason>
<S:Detail>
<psf:error>
<psf:value>0x80048821</psf:value>
<psf:internalerror>
<psf:code>0x80047860</psf:code>
<psf:text>Direct login to WLID is not allowed for this federated namespace</psf:text>
</psf:internalerror>
</psf:error>
</S:Detail>
</S:Fault>
</S:Body>
</S:Envelope>
The only difference I can think between the Trial version which worked and the development environment is that the development environment setup uses ADFS / AD On-Premises.
Fiddler logs show that Jason's Sample goes straight to login.microsoftonline.com whereas CRM SDK (which works) goes to dynamicscrmemea.accesscontrol.windows.net.
So I believe this is the problem area!
I've been around in circles on stack overflow/other sources, I have a feeling it will a relatively small change required to the SOAP request but I've reached the point where I need some fresh eyes/advice.
Has anyone had experience with this setup? Can anyone gently push me in the right direction?
Many Thanks
Gareth
We experienced a similar issue, attempting to create a BizTalk integration. Eventually we resolved the issue by using a Windows Live/Office 365 account to actually connect with, rather than one that authenticated against the actual AD. CRM determines authentication types by User, not by org, so you can mix and match...

External http endpoint worker role, no acces right with executionContext elevated

Yet another post on http service on worker role.
Hello everyone,
I have been looking everywhere for an answer and I can't find any.
Here is the problem :
I have a worker role with a tcp entry point. It works fine locally and on azure. So far so good.
I have a windows phone app (sdk 8.0, .net 4.5) that I want to connect to this endpoint.
First problem here, the only way to access a wcf service with a windows phone project is to Right-click project, "Add service reference" and put the service address. BUT ! it doesn't work with tcp.net://{address}:{port}/{service name}.
I've searched and found that I need a http service.
All right then, I'll create a http endpoint. Code is easy, can be found everywhere.
Now here's the interesting part, I have the following error :
HTTP could not register URL http://+:8080/myservice. Your process does not have access rights to this namespace.
So I've looked it up on the internet and found 2 answers :
adding
<Runtime executionContext="elevated" />
to the ServiceDefinition.csdef file.
And setting
var binding = new BasicHttpBinding { HostNameComparisonMode = HostNameComparisonMode.Exact };
Now here's the kicker, I've done that and it still doesn't work.
Here are my Endpoints in ServiceDefinition.csdef file.
<Endpoints>
<InputEndpoint name="External" protocol="tcp" port="10100" />
<InputEndpoint name="Http" protocol="http" port="8080" />
</Endpoints>
Looking for help.

WSO2 API Manager - "Make this the default version" causes authentication errors?

I have an API that works no problem providing the "Make this the default version" checkbox isnt checked, once checked I get this error back
<ams:fault
xmlns:ams="http://wso2.org/apimanager/security">
<ams:code>900906</ams:code>
<ams:message>No matching resource found in the API for the given request</ams:message>
<ams:description>Access failure for API: xxxx/xxxx, version: v0.1 with key: xxxxxx</ams:description>
</ams:fault>
Is there something I have missed at all?
Thanks,
Ash.
EDIT - Extra Detail and Logs
TID[-1234] [AM] [2014-07-10 13:05:56,238] ERROR
{org.wso2.carbon.apimgt.gateway.handlers.security.APIAuthenticationHandler}
- API authentication failure org.wso2.carbon.apimgt.gateway.handlers.security.oauth.OAuthAuthenticator.authenticate(OAuthAuthenticator.java:157)
org.wso2.carbon.apimgt.gateway.handlers.security.APIAuthenticationHandler.handleRequest(APIAuthenticationHandler.java:92)
org.apache.synapse.rest.API.process(API.java:285)
org.apache.synapse.rest.RESTRequestHandler.dispatchToAPI(RESTRequestHandler.java:83)
org.apache.synapse.rest.RESTRequestHandler.process(RESTRequestHandler.java:64)
org.apache.synapse.core.axis2.Axis2SynapseEnvironment.injectMessage(Axis2SynapseEnvironment.java:220)
org.apache.synapse.core.axis2.SynapseMessageReceiver.receive(SynapseMessageReceiver.java:83)
org.apache.axis2.engine.AxisEngine.receive(AxisEngine.java:180)
org.apache.synapse.transport.passthru.ServerWorker.processNonEntityEnclosingRESTHandler(ServerWorker.java:344)
org.apache.synapse.transport.passthru.ServerWorker.run(ServerWorker.java:168)
org.apache.axis2.transport.base.threads.NativeWorkerPool$1.run(NativeWorkerPool.java:172)
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
java.lang.Thread.run(Thread.java:744)
Please save and publish the API once you made the change to the API. This may be causing the issue.
Once you have published you should see 2 sets of production url (one with the version and one without the version). Please check if the same is available in the API store for your API.
You'll first want to turn on wire logs in that environment by editing your ../repository/conf/log4j.properties file and restarting the service. This will allow you to see the request headers for both the initial request to the gateway and the request from the gateway to itself (or other gateways in your cluster) since that's how requests to a default API version are resolved. This can help you identify whether your Authorization header values are actually making it to the authentication handler.
After you take a look at this, note that when you publish an API with a default version, you're actually creating (or updating) two separate synapse configurations for the API: a versioned configuration and an unversioned configuration. The portion of the latter's definition that you need to check is:
<else>
<header name="WSO2_AM_API_DEFAULT_VERSION" scope="transport" value="true"/>
<property name="uri.var.portnum" expression="get-property('https.nio.port')"/>
<send>
<endpoint>
<http uri-template="https://localhost:{uri.var.portnum}/myApi/v1">
<timeout>
<duration>60000</duration>
<responseAction>fault</responseAction>
</timeout>
</http>
</endpoint>
</send>
</else>
By default, the newly generated definition for the default version attempts to send the request to localhost, which may not be what you want. Check at ../repository/deployment/synapse-configs/default/api and make sure that this definition is correct.
Since it looks like this is actually an authentication error, you should also test a new subscription. Create a new application with some subscriber, subscribe to the API, and generate new access tokens. I wouldn't understand why (since setting a default version doesn't create a new API entry in the AM_API table) but this could possibly be due to the access token credentials being invalid for the default version, and generating new tokens should (in theory) test against this.

One Apigee Api Proxy with a different target endpoint for each environment

I am an Apigee beginner. We are doing a migration to Apigee.
We have our environments in our host names, for example:
something.int.other.thing.co.uk
something.test.other.thing.co.uk
something.stage.other.thing.co.uk
something.prod.other.thing.co.uk
I would like to be able to map them to the 4 environments of the apigee api proxy itself, respectively int, test, stage, prod.
I currently have one Rest resource for them, for example: /resource
Basically I would like the apigee api proxy with one rest resource, to map to 4 different target endpoints, depending on the environment.
So far I have tried to do it from the UI and have not been able to do so.
I have been going through the documentation and I have found these so far:
According to this it should be possible:
"An API proxy can contain zero or more TargetEndpoints." (TargetEndpoint section)
http://apigee.com/docs/api-services/content/api-proxy-configuration-reference
According to these, you can make routerules to the proxy endpoint, but I have not been able to implement it to the targetendpoint:
Create a New Endpoint on an existing API Proxy with "No Target Endpoint"
One API proxy calling two different target endpoints
I also tried doing something along the lines of this, for TargetEndpoint, where I tested for the environment name, but it didn't work:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<TargetEndpoint name="default">
<Description/>
<Flows/>
<PreFlow name="PreFlow">
<Request/>
<Response/>
</PreFlow>
<HTTPTargetConnection>
<URL>something.int.other.thing.co.uk</URL>
</HTTPTargetConnection>
<RouteRule name="int">
<Condition>environment.name == "int"</Condition>
<TargetEndpoint>something.int.other.thing.co.uk</TargetEndpoint>
</RouteRule>
<RouteRule name="test">
<Condition>environment.name == "test"</Condition>
<TargetEndpoint>something.test.other.thing.co.uk/</TargetEndpoint>
</RouteRule>
<RouteRule name="stage">
<Condition>environment.name == "stage"</Condition>
<TargetEndpoint>something.stage.other.thing.co.uk/</TargetEndpoint>
</RouteRule>
<RouteRule name="prod">
<Condition>environment.name == "prod"</Condition>
<TargetEndpoint>something.prod.other.thing.co.uk</TargetEndpoint>
</RouteRule>
<PostFlow name="PostFlow">
<Request/>
<Response/>
</PostFlow>
</TargetEndpoint>
So is this possible?
Apigee supports the concept of Target Servers -which abstracts the backend host from the proxies and also provides load balancing. Same target servers can be configured to point to different host for each environment (this concept is built in to Apigee already).
Take a look, this should help.
Srikanth
LoadBalancer and TargetServer settings go in the TargetEndpoint definition, specifically in the HTTPTargetConnection element.
Check the example here:
http://apigee.com/docs/api-services/content/load-balancing-across-backend-servers
If you do want to curl a TargetEndpoint definition to your API proxy, have a look at the following sample script to see working API calls:
https://github.com/apigee/api-platform-samples/blob/master/tools/proxy_gen.sh
This script shows you how to create an API proxy and update ProxyEndpoint and TargetEndpoints via API calls.

Magento Enterprise 1.12 - Accessing customer custom attributes from the V2 API

I've got a client that would like to use Magento's web services API to create and update customers. Using the API we can easily manipulate the system defined attributes - firstname, lastname, etc using the V1 or V2 API. Se we're good to go there.
This is where it gets sticky - this site uses Magento Enterprise 1.12 and we have added some custom customer attributes for linking the Magento customers to their CRM data on an external system. Using the V1 API, I have full access to the custom attributes. However, the V2 API will not expose them. Since the caller is coming from .NET, I believe he needs to use the V2 API.
Tracing the code with a debugger, I see that the V2 code gets all the attribute data and then drops all the custom data when the web service response is generated. I tried adding the attributes to the Customer (Mage/Customer/etc/) WSDL and WSI files, but that did not do the trick.
Can anyone give me a pointer as to what I should do to expose the customer attributes?
Greg
Create a new module
In Your_Module/etc/wsdl.xml and wsi.xml add your new attribute in the same node as in the Mage_Customer wsdl.xml and wsi.xml
Magento merges all wsdl.xml and wsi.xml files together
Here's an example of a wsdl.xml file that I used to add customer_number to the API.
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns:typens="urn:{{var wsdl.name}}" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns="http://schemas.xmlsoap.org/wsdl/"
name="{{var wsdl.name}}" targetNamespace="urn:{{var wsdl.name}}">
<types>
<schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="urn:Magento">
<complexType name="customerCustomerEntity">
<all>
<element name="customer_number" type="xsd:string" minOccurs="0" />
</all>
</complexType>
</schema>
</types>
</definitions>