WF4 Services and WIF Integration - wcf

Are there proven patterns that anyone could share regarding Workflow 4.0 services integrated with Windows Identity Foundation? We are looking for the best way to inspect the STS token and claims in order to derive who the user is outside the workflow service instance context and make the application's user object available to the workflow context.
We want to maintain separation of concerns between the service implementation of WIF and workflow business logic so our workflow services are highly testable. We have seen a few examples provided which point to wrapping the Receive activity with a code activity that instantiates an implementation of IReceiveMessageCallback in order to get a reference to the OperationContext. Link to Maurice's Blog Post. However, this means activities internal to the service are dependent on the existence of the operation context and possibly even the IClaimsIdentity.
The best solution we can come up with so far is to create an implementation of IDispatchMessageInspector for the service that interrogates the token and creates the application user objects needed by the workflow making them available to the workflow runtime via InstanceContext.Extensions. This seems to work but doesn't feel exactly solid. Any help or feedback is greatly appreciated!
Service Behavior
public class SecurityTokenServiceBehavior : IServiceBehavior, IDispatchMessageInspector
{
...
public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
{
var claimsPrincipal = (IClaimsPrincipal)(Thread.CurrentPrincipal is GenericPrincipal ? null : Thread.CurrentPrincipal);
...
instanceContext.Extensions.Add(new SecurityContextExtension(appUser, audit));
return null;
}
...
}
IReceiveMessageCallback
public class SecurityContextCallback : IReceiveMessageCallback
{
[DataMember]
public SecurityContextExtension SecurityContext { get; private set; }
public void OnReceiveMessage(OperationContext operationContext, ExecutionProperties activityExecutionProperties)
{
SecurityContext = operationContext.InstanceContext.Extensions.Find<SecurityContextExtension>();
}
}

Did you see this blog post about using the ClaimsAuthorizationManager as well? Using the ClaimsAuthorizationManager is the usual way to check for authorization when using WIF.
See Dominick post here for some example on how to embed checks in your code using either the ClaimsAuthorize attribute or the static ClaimsAuthorize.CheckAccess() method. You might also want to take a look at the WF Security Pack CTP 1 here.

Related

NServiceBus Removing IBus - Utilising IPipelineContext and IMessageSession

I am in the process of migrating NServiceBus up to v6 and am at a roadblock in the process of removing reference to IBus.
We build upon a common library for many of our applications (Website, Micro Services etc) and this library has the concept of IEventPublisher which is essentially a Send and Publish interface. This library has no knowledge of NSB.
We can then supply the implementation of this IEventPublisher using DI from the application, this allows the library's message passing to be replaced with another technology very easily.
So what we end up with is an implementation similar to
public class NsbEventPublisher : IEventPublisher
{
IEndpointInstance _instance;
public NsbEventPublisher(IEndpointInstance endpoint)
{
instance = endpoint;
}
public void Send(object message)
{
instance.Send(message, sendOptions);
}
public void Publish(object message)
{
instance.Publish(message, sendOptions);
}
}
This is a simplification of what actually happens but illustrates my problem.
Now when the DI container is asked for an IEventPublisher it knows to return a NsbEventPublisher and it knows to resolve the IEndpointInstance as we bind this in the bootstrapper for the website to the container as a singleton.
All is fine and my site runs perfect.
I am now migrating the micro-services (running in NSB.Host) and the DI container is refusing to resolve IEndpointInstance when resolving the dependencies within a message handler. Reading the docs this is intentional and I should be using IMessageHandlerContext when in a message handler.
https://docs.particular.net/nservicebus/upgrades/5to6/moving-away-from-ibus
The docs even elude to the issue I have in the bottom example around the class MyContextAccessingDependency. The suggestion is to pass the message context through the method which puts a hard dependency on the code running in the context of a message handler.
What I would like to do is have access to a sender/publisher and the DI container can give me the correct implementation. The code does not need any concept of the caller and if it was called from a message handler or from a self hosted application that just wants to publish.
I see that there is two interfaces for communicating with the "Bus" IPipelineContext and IMessageSession which IMessageHandlerContext and IEndpointInstance interfaces extend respectively.
What I am wondering is there some unification of the two interfaces that gets bound by NSB into the container so I can accept an interface that sends/publishes messages. In a handler it is an IMessageHandlerContext and on my self hosted application the IEndPointInstance.
For now I am looking to change my implementation of IEventPublisher depending on application hosting. I was just hoping there might be some discussion about how this approach is modeled without a reliable interface to send/publish irrespective of what initiated the execution of the code path.
A few things to note before I get to the code:
The abstraction over abstraction promise, never works. I have never seen the argument of "I'm going to abstract ESB/Messaging/Database/ORM so that I can swap it in future" work. ever.
When you abstract message sending functionality like that, you'll lose some of the features the library provides. In this case, you can't perform 'Conversations' or use 'Sagas' which would hinder your overall experience, e.g. when using monitoring tools and watching diagrams in ServiceInsight, you won't see the whole picture but only nugets of messages passing through the system.
Now in order to make that work, you need to register IEndpointInstance in your container when your endpoint starts up. Then that interface can be used in your dependency injection e.g. in NsbEventPublisher to send the messages.
Something like this (depending which IoC container you're using, here I assume Autofac):
static async Task AsyncMain()
{
IEndpointInstance endpoint = null;
var builder = new ContainerBuilder();
builder.Register(x => endpoint)
.As<IEndpointInstance>()
.SingleInstance();
//Endpoint configuration goes here...
endpoint = await Endpoint.Start(busConfiguration)
.ConfigureAwait(false);
}
The issues with using IEndpointInstance / IMessageSession are mentioned here.

consuming wcf service secured by adfs in windows phone application

I have a wcf service secured by ADFS deployed in azure. I am able to consume that service in my console application. But when I am not sure how to consume that service in windows phone 7 application.
In my console application, I am retrieving a security token and passing that token to channelfactory object using CreateChannelWithIssuedToken method. But there is no such method in windows phone app to pass the token to wcf service. Can anyone guide me in this issue?
Thanks in advance.
CreateChannelWithIssuedToken was an extension method added by the WIF assembly in .NET 3.5/4.0 (I believe .NET 4.5 has most of this stuff now built-in to the System.ServiceModel namespace). Since you won't have this on the phone, you're stuck with the regular WCF methods to create and use channels.
This is still the case when working on WinForms/WPF apps, though in that case you have the option of bringing in the WIF assembly. Still, it isn't required, and consuming an ADFS-secured service is perfectly doable with the regular WCF classes.
Windows Phone seems to support this stuff, though with some caveats. Looking at the implementation of the extension method, it doesn't seem like they are doing anything all that fancy really:
public static T CreateChannelWithIssuedToken<T>(this ChannelFactory<T> factory, SecurityToken issuedToken)
{
return ChannelFactoryOperations.CreateChannelWithParameters<T>(factory, new FederatedClientCredentialsParameters
{
IssuedSecurityToken = issuedToken
});
}
public static T CreateChannelWithParameters<T>(ChannelFactory<T> factory, FederatedClientCredentialsParameters parameters)
{
ChannelFactoryOperations.VerifyChannelFactory<T>(factory);
T t = factory.CreateChannel();
((IChannel)t).GetProperty<ChannelParameterCollection>().Add(parameters);
return t;
}
The verify method simply performs some diagnostics and throws exceptions (such as if the endpoint isn't set). ChannelParameterCollection is defined in System.ServiceModel.Channels and is supported in Silverlight/WP7. And FederatedClientCredentialsParameters is nothing special either:
public class FederatedClientCredentialsParameters
{
public SecurityToken ActAs ( get; set; )
public SecurityToken OnBehalfOf ( get; set; )
public SecurityToken IssuedSecurityToken ( get; set; )
}
It seems like you should be able to create a channel and use your token with it normally, even from WP7, though I'm afraid I don't have the exact steps to do so. Maybe someone else does or maybe this leads you in the right direction.
This article shows how to access a WIF-protected WCF service from Silverlight, which I imagine is nearly identical to how you'd do it on the phone.
There is a training kit (http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=8396) example ACSAndWindowsPhone7 that may help here (I've not looked at it in detail). I know that Wade Wegner has a number of blog posts on ACS and WP7, but not sure if he's tackled ADFS specifically versus OAuth type mechanisms.

Business Logic Layer expose in WCF Service

We have already Business logic layer available in our application. It has lots of classes. and this is in separate library(.Dll). Now we want to use this in to our WCF Service. For that We create new project and gave reference to that .Dll. But we are not able to see our class .. I verify that class is public..
Could you please let me know what should I do?
Here I am attaching my code what I need to do
My Business Layer class
namespace BusinessLayer
{
public class MessageContext : Dictionary<string, object>
{ ....}
}
Now I am reference this Project to my WCF project and tried to expose this class into WCF client. So I Create one MessageContextHelper class which inherit from MessageContext the code is following
namespace WCFService
{
public class MessageContextHelper : MessageContext
{ ...... }
}
On client I am not able to get MessageContextHelper class.
Thanks
JK
WCF doesn't send business logic classes to the client. If you're using the SOAP version of WCF (BasicHttpBinding for example) then what WCF will expose is methods that are in your service contract. Your client can call those.
So if you have methods in a business logic class that you want exposed, create methods in your WCF service that will in turn call the business layer methods.
A very rudimentary (and not complete) version would look something like this:
namespace WCFService
{
public class MyService: IMyService
[OperationContract]
public String DoSomeStuff() {
return MessageContext.DoSomething();
}
}
You absolutely cannot (and should not) use your business layer from your client code. As the previous reply message, WCF does not send your business class to the client. Think about how long it will take to send. The business layer (your dll) should be used on the server only. Your WCF should only accept modified/new data from the client, pass the data to the business layer, and then return the results to the client.

NHibernate + WCF + Windows Service and WcfOperationSessionContext class

I have a Windows Service Application
in which i create WCF services in it.
One of the services is data
services: add, delete,
read , updatte data via
WCF.
WCF use NHibernate for data manipulation
So my guestions are:
Any advice (best practice) for session management for Hibernate using with WCF?
Anybody knows anything about
WcfOperationSessionContext (hibernate 3.0) class?
how to use it with WCF?
Well to make it concrete :
Suppose that i have WCF Service called DataServices
class WCFDataService .....
{
void SaveMyEntity(MyEntity entity)
{
.....................?? // How to do? Best Way
// Should i take one session and use it all times
// Should i take session and dipsose when operation finished then get
//new session for new operations?
// If many clients call my WCF service function at the same time?
// what may go wrong?
// etc....
}
}
And I need a NHibernateServiceProvider class
class NHibernateServiceProvider ....
{
// How to get Session ?? Best way
ISession GetCurrentSession(){.... }
DisposeSession(){ ....}
}
Best Wishes
PS: I have read similiar entries here and other web pages. But can not see "concrete" answers.
The WcfOperationSessionContext, similar to ThreadStaticSessionContext and WebRequestSessionContext is an implementation for a session context. The session context is used to bind (associate) a ISession instance to a particular context.
The session in the current context can be retrieved by calling ISessionFactory.GetCurrentSession().
You can find more information about session context here.
The WcfOperationSessionContext represents a context that spans for the entire duration of a WCF operation. You still need to handle the binding of the session in the begining of the operation and the unbinding/commiting/disposal of the session at the end of the operation.
To get access to the begin/end actions in the wcf pipeline you need to implement a IDispatchMessageInspector. You can see a sample here.
Also regarding WCF integration: if you use ThreadStatic session context it will appear to work on development, but you will hit the wall in production when various components (ex: authorization, authentication ) from the wcf pipeline are executed on different threads.
As for best practices you almost nailed it: Use WcfOperationSessionContext to store the current session and the IDispatchMessageInspector to begin/complete your unit of work.
EDIT - to address the details you added:
If you configured WcfOperationSessionContext and do the binding/unbinding as i explained above, all you have to do to is inject the ISessionFactory into your service and just use factory.GetCurrentSession(). I'll post a sample prj if time permits.
Here is the sample project
The model we use for managing NHibernate sessions with WCF is as follows:
1) We have our own ServiceHost class that inherits from System.ServiceModel.ServiceHost which also implements ICallContextInitializer. We add the service host instance to each of the operations in our service as follows:
protected override void InitializeRuntime()
{
base.InitializeRuntime();
foreach (ChannelDispatcher cd in this.ChannelDispatchers)
{
foreach (EndpointDispatcher ed in cd.Endpoints)
{
foreach (DispatchOperation op in ed.DispatchRuntime.Operations)
{
op.CallContextInitializers.Add(this);
}
}
}
}
public void AfterInvoke(object correlationState)
{
// We don't do anything after the invoke
}
public object BeforeInvoke(InstanceContext instanceContext, IClientChannel channel, Message message)
{
OperationContext.Current.Extensions.Add(new SessionOperationContext());
return null;
}
The BeforeInvoke simply makes sure that the OperationContext for each WCF call has it's own session. We have found problems with IDispatchMessageInspector where the session is not available during response serialisation - a problem if you use lazy loading.
2) Our SessionOperationContext will then be called to attach itself and we use the OperationCompleted event to remove ourselves. This way we can be sure the session will be available for response serialisation.
public class SessionOperationContext : IExtension<OperationContext>
{
public ISession Session { get; private set; }
public static SessionOperationContext Current
{
get
{
OperationContext oc = OperationContext.Current;
if (oc == null) throw new InvalidOperationException("Must be in an operation context.");
return oc.Extensions.Find<SessionOperationContext>();
}
}
public void Attach(OperationContext owner)
{
// Create the session and do anything else you required
this.Session = ... // Whatever instantiation method you use
// Hook into the OperationCompleted event which will be raised
// after the operation has completed and the response serialised.
owner.OperationCompleted += new EventHandler(OperationCompleted);
}
void OperationCompleted(object sender, EventArgs e)
{
// Tell WCF this extension is done
((OperationContext)sender).Extensions.Remove(this);
}
public void Detach(OperationContext owner)
{
// Close our session, do any cleanup, even auto commit
// transactions if required.
this.Session.Dispose();
this.Session = null;
}
}
We've used the above pattern successfully in high-load applications and it seems to work well.
In summary this is similar to what the new WcfOperationSessionContext does (it wasn't around when we figured out the pattern above;-)) but also overcomes issues surrounding lazy loading.
Regarding the additional questions asked: If you use the model outlined above you would simply do the following:
void SaveMyEntity(MyEntity entity)
{
SessionOperationContext.Current.Session.Save(entity);
}
You are guaranteed that the session is always there and that it will be disposed once the WCF operation is completed. You can use transactions if required in the normal way.
Here is a post describing, in detail, all the steps for registering and using the WcfOperationSessionContext. It also includes instructions for using it with the agatha-rrsl project.
Ok, after few days of reading internet posts etc. all approaches shown in the internets seems to be wrong. When we are using UnitOfWork pattern with NH 3^ with nhibernate transaction this all aprochaes are producing exceptions. To test it and proof that we need to create test enviroment with MSMQ transaction queue, special interface with OneWay operation contract with transaction required set on it. This approach should works like this:
1. We put transactionally message in queue.
2. Service is getting transactionally messege from queue.
3. Everything works queue is empty.
In some cases not so obious with internet approaches this does not work properly. So here are expamples which we tested that are wrong and why:
Fabio Maulo approach: Use ICallContextInitializer - open NH session/transaction on BeforeCall, after that WCF is executing service method, on AfterCall in context initializer we call session.Flush + transaction.commit. Automaticly session will be saved when transaction scope will commit operation. In situation when on calling transaction.Complete exception will be thrown WCF service will shutdown! Question can be ok, so take transaction.Complete in try/catch clausule - great! - NO wrong! Then transaction scope will commit transaction and message will be taken from queue but data will not be saved !
Another approach is to use IDispatchMessageInspector - yesterday I thought this is best approach. Here we need to open session/transaction in method AfterReceiveRequest, after WCF invoke service operation on message dispatcher inspector BeforeSendReply is called. In this method we have info about [reply] which in OneWay operation is null, but filled with fault information if it occured on invoking service method. Great I thought - this is this ! but NOT! Problem is that at this point in WCF processing pipe we have no transaction ! So if transaction.Complete throw error or session.Flush will throw it we will have not data saved in database and message will not come back to queue what is wrong.
What is the solution?
IOperationInvoker and only this!
You need to implement this interface as a decorator pattern on default invoker. In method Invoke before call we are openning session/transaction open then we call invoke default invoker and after that call transaction.complete in finally clausule we call session.flush. What types of problem this solves:
1. We have transaction scope on this level so when complete throws exception message will go back to queue and WCF will not shutdown.
2. When invocation will throw exception transaction.complete will not be called what will not change database state
I hope this will clear everyones missinformation.
In some free time I will try to write some example.

WCF, SubSonic SimpleRepository and multithreading

I'm currently in the process of writing a WCF REST service with SubSonic SimpleRepository and the WCF REST Contrib library. The service is going to be hosted on IIS 7. The database is going to be MS SQL Server. I could not really find a good example which is using this combination of technologies on the internet. The service should expose a database in a RESTful manner but also contains some business rules (e.g. registering users, saving statistics) so I can't use ADO.net Data Services. Because there are going to be a lot of clients accessing the service at the same time it's important that the service can serve several clients at the same time.
For good performance I want to use the following service behaviour:
[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerSession, ConcurrencyMode=ConcurrencyMode.Multiple)]
There are no instance variables in the Service class and as I understand it, those attribute values cause new a instance of the service class to be created for every call (not per session because it is called over https).
I used the following simple class for creating the SimpleRepository once (singleton):
public class DB
{
private static SimpleRepository _Repository;
public static SimpleRepository Repository
{
get
{
if (_Repository == null)
{
_Repository = new SimpleRepository("5Drive", SimpleRepositoryOptions.RunMigrations);
}
return _Repository;
}
}
}
Here is an example method of my service:
Interface:
[OperationContract]
[WebGet(UriTemplate = "vehicles")]
[WebDispatchFormatter]
Vehicles GetVehicles();
Implementation:
public Vehicles GetVehicles()
{
// get all vehicles for the logged in user
var vehicles = from v in DB.Repository.All<Vehicle>()
where v.UserID == GetUserID()
orderby v.Name
select v;
return new Vehicles(vehicles);
}
So, here is my question: can I do it this way? Is SimpleRepository thread-safe? Do I have to create a SimpleRepository in every method instead of using a singleton? What about performance when I do that? I looked at the SimpleRepository source code and I think that the migration code is not thread safe because the "private readonly List migrated;" is not synchronized but I might be wrong.
Maybe I'm missing something and I can just ignore multi-threading and configure IIS differently?
Thanks for your help!