How to attach a certificate to a C# client for an ODATA service? - certificate

We have an ODATA service which is being secured using certificates. We are using AddWebReference to get the proxy in our C# code.
Is there a way to attach the certificate that is in our certificate store to this generated proxy class?
We can add the certificate using HTTPClient, but we would like to avoid using HTTPClient to talk to our ODATA service and prefer to use the AddWebReference method.

I guess this is probably 3 years too late for you, but hopefully someone else will be helped.
This article actually explains in great detail what is required.
You need to add a ClientCertificate property to the container generated by adding a web reference and use it. You can do this by creating a partial class that adds the behaviour:
public partial class YourContainer
{
private X509Certificate clientCertificate = null;
public X509Certificate ClientCertificate
{
get
{
return clientCertificate;
}
set
{
if (value == null)
{
// if the event has been hooked up before, we should remove it
if (clientCertificate != null)
this.SendingRequest -= this.OnSendingRequest_AddCertificate;
}
else
{
// hook up the event if its being set to something non-null
if (clientCertificate == null)
this.SendingRequest += this.OnSendingRequest_AddCertificate;
}
clientCertificate = value;
}
}
private void OnSendingRequest_AddCertificate(object sender, SendingRequestEventArgs args)
{
if (null != ClientCertificate)
{
((HttpWebRequest)args.Request).ClientCertificates.Add(ClientCertificate);
}
}
}
On the instantiated container you can now set the ClientCertificate property with the certificate you need:
// Get the store where your certificate is in.
var store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadOnly);
// Select your certificate from the store (any way you like).
X509Certificate2Collection certColl = store.Certificates.Find(X509FindType.FindByThumbprint, yourThumbprint, false);
// Set the certificate property on the container.
container.ClientCertificate = certColl[0];
store.Close();
WCF DataServices 5+ (not completely working)
Now if you're using WCF Dataservice 5+, then the SendingRequest event has been deprecated as indicated with the attribute [Obsolete("SendingRequest2 has been deprecated in favor of SendingRequest2.")] (not a typo on my side ;) ). I think you can still use it though, however, if you want to use SendingRequest2, your partial should look something like the following:
public partial class YourContainer
{
private X509Certificate clientCertificate = null;
public X509Certificate ClientCertificate
{
get
{
return clientCertificate;
}
set
{
if (value == null)
{
// if the event has been hooked up before, we should remove it
if (clientCertificate != null)
this.SendingRequest2 -= this.OnSendingRequest_AddCertificate;
}
else
{
// hook up the event if its being set to something non-null
if (clientCertificate == null)
this.SendingRequest2 += this.OnSendingRequest_AddCertificate;
}
clientCertificate = value;
}
}
private void OnSendingRequest_AddCertificate(object sender, SendingRequest2EventArgs args)
{
if (null != ClientCertificate)
{
((HttpWebRequestMessage)args.RequestMessage).HttpWebRequest.ClientCertificates.Add(ClientCertificate);
}
}
}
This worked for me for non-batch requests (found by trial and error as I couldn't find a lot of documentation about the differences between the SendingRequest and SendingRequest2).
However I seem to be experiencing some trouble now with args.RequestMessage being of type instead of HttpWebRequestMessage resulting in InvalidCastExceptions. Which is actually the reason I ended up on this question. It seems that it only goes wrong with Batch operations. The InternalODataRequestMessage has a private member requestMessage of type ODataBatchOperationRequestMessage. It doesn't seem to have any property to which I can add client certificates.
I have posted another question about that specific issue and will change this answer if the implementation I provided here turns out to be the problem.

Related

Claims transformation in ADFS 3.0 by making a call to REST API

We have a ASP.NET Web API (REST service) in our enterprise that gives us the list of coarse-grained claims for a user that we want to inject into the adfs token before passing the token onto the application. Does anyone know if making a rest call is possible using the Custom attribute store (by passing param's to the custom attribute store from the Claims rule language in ADFS 3.0) ?
Any help regarding this would be greatly appreciated!
Thanks,
Ady.
I'm able to make the REST call from the Custom Attribute store. For those who are still wondering about this can look at the below code.
using System;
using System.Collections.Generic;
using System.Text;
using System.IdentityModel;
using Microsoft.IdentityServer.ClaimsPolicy.Engine.AttributeStore;
using System.Net.Http;
using System.Net;
namespace CustomAttributeStores
{
public class CoarseGrainClaimsAttributeStore : IAttributeStore
{
#region Private Members
private string API_Server = "https://<Server Name>/API/";
#endregion
#region IAttributeStore Members
public IAsyncResult BeginExecuteQuery(string query, string[] parameters, AsyncCallback callback, object state)
{
string result = string.Empty;
if (parameters == null)
{
throw new AttributeStoreQueryFormatException("No query parameter.");
}
if (parameters.Length != 1)
{
throw new AttributeStoreQueryFormatException("More than one query parameter.");
}
string userName = parameters[0];
if (userName == null)
{
throw new AttributeStoreQueryFormatException("Query parameter cannot be null.");
}
//Ignore SSL Cert Error
//TODO: Need to set the SSL cert correctly for PROD Deployment
ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true;
using (var client = new HttpClient())
{
//The url can be passed as a query
string serviceUrl = API_Server + "GetAdditionalClaim";
serviceUrl += "?userName=" + userName;
//Get the SAML token from the API
result = client
.GetAsync(serviceUrl)
.Result
.Content.ReadAsStringAsync().Result;
result = result.Replace("\"", "");
}
string[][] outputValues = new string[1][];
outputValues[0] = new string[1];
outputValues[0][0] = result;
TypedAsyncResult<string[][]> asyncResult = new TypedAsyncResult<string[][]>(callback, state);
asyncResult.Complete(outputValues, true);
return asyncResult;
}
public string[][] EndExecuteQuery(IAsyncResult result)
{
return TypedAsyncResult<string[][]>.End(result);
}
public void Initialize(Dictionary<string, string> config)
{
// No initialization is required for this store.
}
#endregion
}
}
No, you can't do this with the claims rules language.
This is somewhat of a hack but you could write the claims to e.g. a DB and then use a custom attribute store
If you have access to WIF on the client side, you can augment the claims there e.g. Adding custom roles to windows roles in ASP.NET using claims.

Correct way to call async methods from within a data-bound property setter?

Now I know properties do not support async/await for good reasons. But sometimes you need to kick off some additional background processing from a property setter - a good example is data binding in a MVVM scenario.
In my case, I have a property that is bound to the SelectedItem of a ListView. Of course I immediately set the new value to the backing field and the main work of the property is done. But the change of the selected item in the UI needs also to trigger a REST service call to get some new data based on the now selected item.
So I need to call an async method. I can't await it, obviously, but I also do not want to fire and forget the call as I could miss exceptions during the async processing.
Now my take is the following:
private Feed selectedFeed;
public Feed SelectedFeed
{
get
{
return this.selectedFeed;
}
set
{
if (this.selectedFeed != value)
{
this.selectedFeed = value;
RaisePropertyChanged();
Task task = GetFeedArticles(value.Id);
task.ContinueWith(t =>
{
if (t.Status != TaskStatus.RanToCompletion)
{
MessengerInstance.Send<string>("Error description", "DisplayErrorNotification");
}
});
}
}
}
Ok so besides the fact I could move out the handling from the setter to a synchronous method, is this the correct way to handle such a scenario? Is there a better, less cluttered solution I do not see?
Would be very interested to see some other takes on this problem. I'm a bit curious that I was not able to find any other discussions on this concrete topic as it seems very common to me in MVVM apps that make heavy use of databinding.
I have a NotifyTaskCompletion type in my AsyncEx library that is essentially an INotifyPropertyChanged wrapper for Task/Task<T>. AFAIK there is very little information currently available on async combined with MVVM, so let me know if you find any other approaches.
Anyway, the NotifyTaskCompletion approach works best if your tasks return their results. I.e., from your current code sample it looks like GetFeedArticles is setting data-bound properties as a side effect instead of returning the articles. If you make this return Task<T> instead, you can end up with code like this:
private Feed selectedFeed;
public Feed SelectedFeed
{
get
{
return this.selectedFeed;
}
set
{
if (this.selectedFeed == value)
return;
this.selectedFeed = value;
RaisePropertyChanged();
Articles = NotifyTaskCompletion.Create(GetFeedArticlesAsync(value.Id));
}
}
private INotifyTaskCompletion<List<Article>> articles;
public INotifyTaskCompletion<List<Article>> Articles
{
get { return this.articles; }
set
{
if (this.articles == value)
return;
this.articles = value;
RaisePropertyChanged();
}
}
private async Task<List<Article>> GetFeedArticlesAsync(int id)
{
...
}
Then your databinding can use Articles.Result to get to the resulting collection (which is null until GetFeedArticlesAsync completes). You can use NotifyTaskCompletion "out of the box" to data-bind to errors as well (e.g., Articles.ErrorMessage) and it has a few boolean convenience properties (IsSuccessfullyCompleted, IsFaulted) to handle visibility toggles.
Note that this will correctly handle operations completing out of order. Since Articles actually represents the asynchronous operation itself (instead of the results directly), it is updated immediately when a new operation is started. So you'll never see out-of-date results.
You don't have to use data binding for your error handling. You can make whatever semantics you want by modifying the GetFeedArticlesAsync; for example, to handle exceptions by passing them to your MessengerInstance:
private async Task<List<Article>> GetFeedArticlesAsync(int id)
{
try
{
...
}
catch (Exception ex)
{
MessengerInstance.Send<string>("Error description", "DisplayErrorNotification");
return null;
}
}
Similarly, there's no notion of automatic cancellation built-in, but again it's easy to add to GetFeedArticlesAsync:
private CancellationTokenSource getFeedArticlesCts;
private async Task<List<Article>> GetFeedArticlesAsync(int id)
{
if (getFeedArticlesCts != null)
getFeedArticlesCts.Cancel();
using (getFeedArticlesCts = new CancellationTokenSource())
{
...
}
}
This is an area of current development, so please do make improvements or API suggestions!
public class AsyncRunner
{
public static void Run(Task task, Action<Task> onError = null)
{
if (onError == null)
{
task.ContinueWith((task1, o) => { }, TaskContinuationOptions.OnlyOnFaulted);
}
else
{
task.ContinueWith(onError, TaskContinuationOptions.OnlyOnFaulted);
}
}
}
Usage within the property
private NavigationMenuItem _selectedMenuItem;
public NavigationMenuItem SelectedMenuItem
{
get { return _selectedMenuItem; }
set
{
_selectedMenuItem = val;
AsyncRunner.Run(NavigateToMenuAsync(_selectedMenuItem));
}
}
private async Task NavigateToMenuAsync(NavigationMenuItem newNavigationMenu)
{
//call async tasks...
}

How to ensure proxies are created when using the repository pattern with entity framework?

I have this method in my SurveyController class:
public ActionResult AddProperties(int id, int[] propertyids, int page = 1)
{
var survey = _uow.SurveyRepository.Find(id);
if (propertyids == null)
return GetPropertiesTable(survey, page);
var repo = _uow.PropertySurveyRepository;
propertyids.Select(propertyid => new PropertySurvey
{
//Setting the Property rather than the PropertyID
//prevents the error occurring later
//Property = _uow.PropertyRepository.Find(propertyid),
PropertyID = propertyid,
SurveyID = id
})
.ForEach(x => repo.InsertOrUpdate(x));
_uow.Save();
return GetPropertiesTable(survey, page);
}
The GetPropertiesTable redisplays Properties but PropertySurvey.Property is marked virtual and I have created the entity using the new operator, so a proxy to support lazy loading was never created and it is null when I access it. When we have access direct to the DbContext we can use the Create method to explicitly create the proxy. But I have a unit of work and repository pattern here. I guess I could expose the context.Create method via a repository.Create method and then I need to remember to use that instead of the new operator when I add an entity . But wouldn't it be better to encapsulate the problem in my InsertOrUpdate method? Is there some way to detect that the entity being added is not a proxy when it should be and substitute a proxy? This is my InsertOrUpdate method in my base repository class:
protected virtual void InsertOrUpdate(T e, int id)
{
if (id == default(int))
{
// New entity
context.Set<T>().Add(e);
}
else
{
// Existing entity
context.Entry(e).State = EntityState.Modified;
}
}
Based on the answer supplied by qujck. Here is how you can do it without having to employ automapper:
Edited to always check for proxy - not just during insert - as suggested in comments
Edited again to use a different way of checking whether a proxy was passed in to the method. The reason for changing the technique is that I ran into a problem when I introduced an entity that inherited from another. In that case an inherited entity can fail the entity.e.GetType().Equals(instance.GetType() check even if it is a proxy. I got the new technique from this answer
public virtual T InsertOrUpdate(T e)
{
DbSet<T> dbSet = Context.Set<T>();
DbEntityEntry<T> entry;
if (e.GetType().BaseType != null
&& e.GetType().Namespace == "System.Data.Entity.DynamicProxies")
{
//The entity being added is already a proxy type that supports lazy
//loading - just get the context entry
entry = Context.Entry(e);
}
else
{
//The entity being added has been created using the "new" operator.
//Generate a proxy type to support lazy loading and attach it
T instance = dbSet.Create();
instance.ID = e.ID;
entry = Context.Entry(instance);
dbSet.Attach(instance);
//and set it's values to those of the entity
entry.CurrentValues.SetValues(e);
e = instance;
}
entry.State = e.ID == default(int) ?
EntityState.Added :
EntityState.Modified;
return e;
}
public abstract class ModelBase
{
public int ID { get; set; }
}
I agree with you that this should be handled in one place and the best place to catch all looks to be your repository. You can compare the type of T with an instance created by the context and use something like Automapper to quickly transfer all of the values if the types do not match.
private bool mapCreated = false;
protected virtual void InsertOrUpdate(T e, int id)
{
T instance = context.Set<T>().Create();
if (e.GetType().Equals(instance.GetType()))
instance = e;
else
{
//this bit should really be managed somewhere else
if (!mapCreated)
{
Mapper.CreateMap(e.GetType(), instance.GetType());
mapCreated = true;
}
instance = Mapper.Map(e, instance);
}
if (id == default(int))
context.Set<T>().Add(instance);
else
context.Entry(instance).State = EntityState.Modified;
}

class member returns null after osgi bind method

My problem is that in the main class I have some osgi references that work just fine when the class is call. But after that all the references became null. When I close the main windows and call shutdown method, the hubService reference returns null. What do I do wrong here?
private void shutdown() {
if(hubService == null) {
throw new NullPointerException();
}
hubService.shutdownHub(); // why is hubService null?
}
// bind hub service
public synchronized void setHubService(IHubService service) {
hubService = service;
try {
hubService.startHub(PORT, authenticationHandler);
} catch (Exception e) {
JOptionPane.showMessageDialog(mainFrame, e.toString(), "Server", JOptionPane.ERROR_MESSAGE);
System.exit(0);
}
}
// remove hub service
public synchronized void unsetHubService(IHubService service) {
hubService.shutdownHub();
hubService = null;
}
If a field can be read and written by multiple threads, you must protect access to read as well as write. Your first method, shutdown, does not protect the read of hubService so that the value of hubService can change between the first read and the second read. You don't show the declaration of the hubService field. You could make it volatile or only read when synchronized (on the same object used to synchronized when writing the field). Then your shutdown implementation could look like:
private volatile IHubService hubService;
private void shutdown() {
IHubService service = hubService; // make a copy of the field in a local variable
if (service != null) // use local var from now on since the field could have changed
service.shutdownHub();
}
I assume your shutdown method is the DS deactivate method? If so, why do you shutdown in the unset method as well in the shutdown method?
Overall the design does not seem very sound. The IHubService is used as a factory and should return some object that is then closed in the deactivate method. You made the IHubService effectively a singleton. Since it must come from another bundle, it should handle its life cycle itself.
Since you also do not use annotations, it is not clear if your set/unset methods are static/dynamic and/or single/multiple. The following code should not have your problems (exammple code with bnd annotations):
#Component public class MyImpl {
IHubService hub;
#Activate
void activate() {
hubService.startHub(PORT, authenticationHandler);
}
#DeActivate
void deactivate() {
hubService.shutdown();
}
#Reference
void setHub(IHubService hub) { this.hub = hub; }
}

ActionFilterAttribute to turn off SSL on Asp.Net MVC2 controller doesn't work consistently

This Action Filter doesn't seem to work consistently. Some times it turns SSL off and sometimes it doesn't. I have it applied to the entire controller at it's declaration.
public class SSLFilter:ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
HttpRequestBase req = filterContext.HttpContext.Request;
HttpResponseBase res = filterContext.HttpContext.Response;
if (req.IsSecureConnection)
{
var builder = new UriBuilder(req.Url)
{
Scheme = Uri.UriSchemeHttp,
Port = 80
};
res.Redirect(builder.Uri.ToString());
}
base.OnActionExecuting(filterContext);
}
}
It's kind of odd...any ideas why it might be working sporadically?
Have you tried decorating your controllers/actions with the [RequireHttps] attribute?
Oops, haven't noticed you was asking about ASP.NET MVC 2. This attribute is available in ASP.NET MVC 3 only, so here's the source code for it (as implemented in ASP.NET MVC 3):
using System;
using System.Diagnostics.CodeAnalysis;
using System.Web.Mvc.Resources;
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = false)]
public class RequireHttpsAttribute : FilterAttribute, IAuthorizationFilter {
public virtual void OnAuthorization(AuthorizationContext filterContext) {
if (filterContext == null) {
throw new ArgumentNullException("filterContext");
}
if (!filterContext.HttpContext.Request.IsSecureConnection) {
HandleNonHttpsRequest(filterContext);
}
}
protected virtual void HandleNonHttpsRequest(AuthorizationContext filterContext) {
// only redirect for GET requests, otherwise the browser might not propagate the verb and request
// body correctly.
if (!String.Equals(filterContext.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase)) {
throw new InvalidOperationException(MvcResources.RequireHttpsAttribute_MustUseSsl);
}
// redirect to HTTPS version of page
string url = "https://" + filterContext.HttpContext.Request.Url.Host + filterContext.HttpContext.Request.RawUrl;
filterContext.Result = new RedirectResult(url);
}
}
Notice that how instead of doing any redirects it uses a RedirectResult which is the correct way of performing redirects in ASP.NET MVC => by returning action results:
filterContext.Result = new RedirectResult(url);
Not only that this will perform the correct redirect but that's how to short-circuit the execution of an action. Also semantically your filter should actually be an IAuthorizationFilter as you are blocking access to some resource here.