Ask a questionAsk a question
 

Proposed AnswerWCF + Azure = Nightmare!

  • Sunday, November 01, 2009 10:10 PMlsberman Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     

    Hi! I've spent the prior week trying to get a secure form of WCF to work on Azure, but all to no avail! My use case is pretty simple. I want to call a WCF endpoint in the cloud and pass messages to be queued for a Worker Role. Beyond that I want to limit access to pre-authrorized users, authenticated via username & password.

    I've tried to get this working with Transport, TransportWithMessageCredential and Message security but nothing seems to work. Indeed, I've worked through every example and snippet that I could find, most recently the "Service using binary HTTP binding with transport security and message credentials and Silverlight client" example on the http://code.msdn.microsoft.com/wcfazure page. I'm pretty sure that I'm being knocked down by small bugs and beta changes but the end result is that I'm totally stuck.

    This is a critical path item for me so any suggestions would be greatly appreciated. A complete working example or a walkthrough would be even better!

All Replies

  • Monday, November 02, 2009 9:41 AMAnton Staykov Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Proposed Answer
    Hello,
    Have you tried the ServiceBus. Instead of using traditional WCF hosted in WebRole, you can have WCF hosted direcly in your worker role and expose a ServiceBus endpoint. Then with the service bus you have more options for authentication and the samples and walkthroughs for .NET Services are pretty well organized and giving a good starting point.
    .NET Services SDK: http://www.microsoft.com/downloads/details.aspx?familyid=38D8CF79-FC39-4AEF-B3FD-EF280F2E9FA6&displaylang=en
    When you install it, there will be a "samples.zip" file in the destination folder.
    You can also check .NET Services forum if are blocked by some issue.
    • Proposed As Answer byAnton Staykov Monday, November 02, 2009 12:40 PM
    •  
  • Tuesday, November 03, 2009 5:36 AMYi-Lun LuoMSFT, ModeratorUsers MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    Hello, can you be more specific about your problem? What is wrong? Doesn't the "Service using binary HTTP binding with transport security and message credentials and Silverlight client" work for you? Do you see any error messages?

    While Service Bus is also a solution, if your service is hosted in a web role, it is generally recommended to host a normal WCF service in IIS, because it's easier, more scalable, and cheaper (you don't need to pay for .NET Services).

    If you let us know what exactly problem you are encountering, we may be able to help you to work our a solution.

    Just some general information: When implementing username/password based authentication in WCF, most people will choose one of the two approaches:

    1. A custom UserNamePasswordValidator, which is used by the sample you pointed out. Well, maybe that sample doesn't walk through each steps. You can find a more detailed description on http://msdn.microsoft.com/en-us/library/aa702565.aspx. This approach is very easy to implement, and works best when you simply need to authenticate the user. It works for both transport and message security.

    2. Use ASP.NET Membership Provider. A detailed walkthrough can be found on http://msdn.microsoft.com/en-us/library/ms731049.aspx. This apporach is also very easy to implement. Yes, it doesn't work for a self hosted service, but if the service is hosted in IIS in a web role, it will work fine. Just remember you must use SQL Azure instead of a normal SQL Server (which means you have to create the database on SQL Azure before hand). Alternatively, you can use the TableStorageMembershipProvider shipped with the SDK sample. And do not forget to enable ASP.NET compatibility mode.
    Lante, shanaolanxing This posting is provided "AS IS" with no warranties, and confers no rights.
  • Tuesday, November 03, 2009 5:02 PMlsberman Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    Hi!  Thanks for your helpful response.  Unfortunately, after many tries, I still can't get the "Service using binary HTTP binding with transport security and message credentials and Silverlight client" in the "WCF Azure Samples" to work.  I think the problem has to do with the self-signed cert I've created but so far I've had no luck in teasing out a solution.  I created the self-signed cert via IIS7 then dragged it from "Local Computer" to "Current User".  The cert has the following info:

    Subject:  LSBDEV
    Issuer:  LSBDEV
    Friendly Name:  SelfSignedDevCert

    When I run the sample I get a "The requested service, 'https://127.0.0.1/SecureCalculator/Service.svc/binary' could not be activated. See the server's diagnostic trace logs for more information." error.

    I've enclosed the "ServiceDefinition.csdef" file plus the serviceModel section of my web.config below on the change they'll be helpful.

    Again, thanks for your help!


    <?

     

    xml version="1.0" encoding="utf-8"?>

    <

     

    ServiceDefinition name="Calculator" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition">

    <

     

    WebRole name="WcfSamples" enableNativeCodeExecution="true">

    <

     

    InputEndpoints>

    <!--

     

    Must use port 80 for http and port 443 for https when running in the cloud --><!--

    <InputEndpoint name="HttpIn" protocol="http" port="80" />

     

    -->

     

    <!--

     

    Only used by SecureCalcualtor sample-->

    <

     

    InputEndpoint name="HttpsIn" protocol="https" port="443"/>

    </

     

    InputEndpoints>

     

    <!--

     

    Only used by PictureRestService sample -->

    <

     

    ConfigurationSettings>

    <

     

    Setting name="PictureRestServiceUrl"/>

    </

     

    ConfigurationSettings>

    </

     

    WebRole>

    </

     

    ServiceDefinition>


    ////////////////////////////////////////////////////////////////////////////////////


    <

     

    system.serviceModel>

    <

     

    bindings>

    <

     

    customBinding>

    <!--

     

    Only used by SecureCalculator sample -->

    <

     

    binding name="secureBinaryHttpBinding">

    <

     

    security authenticationMode="UserNameOverTransport" />

    <

     

    binaryMessageEncoding />

    <

     

    httpsTransport />

    </

     

    binding>

    </

     

    customBinding>

    </

     

    bindings>

    <

     

    behaviors>

    <

     

    serviceBehaviors>

    <!--

     

    Only used by SecureCalculator sample -->

    <

     

    behavior name="SecureService.ServiceBehavior">

    <

     

    serviceMetadata httpGetEnabled="true" />

    <

     

    serviceDebug includeExceptionDetailInFaults="false" />

    <

     

    serviceCredentials>

    <

     

    userNameAuthentication

     

     

    userNamePasswordValidationMode="Custom"

     

     

    customUserNamePasswordValidatorType=

     

     

    "SecureService.MyCustomValidator, WcfSamples"/>

    </

     

    serviceCredentials>

    <!--

     

    http://support.microsoft.com/kb/971842 required for this to work in the dev fabric.

    This has not been deployed to the Azure cloud yet, so comment it out before publishing.

     

    -->

    <

     

    useRequestHeadersForMetadataAddress>

    <

     

    defaultPorts>

    <!--

     

    <add scheme="http" port="81" />-->

    <

     

    add scheme="https" port="444" />

    </

     

    defaultPorts>

    </

     

    useRequestHeadersForMetadataAddress>

    </

     

    behavior>

    </

     

    serviceBehaviors>

    </

     

    behaviors>

    <

     

    services>

    <!--

     

    Only used by SecureCalculator sample -->

    <

     

    service

     

     

    behaviorConfiguration="SecureService.ServiceBehavior"

     

     

    name="SecureService.Service">

    <

     

    endpoint

     

     

    address="binary"

     

     

    binding="customBinding"

     

     

    bindingConfiguration="secureBinaryHttpBinding"

     

     

    contract="SecureService.Service" />

    <

     

    endpoint

     

     

    address="mex"

     

     

    binding="mexHttpBinding"

     

     

    contract="IMetadataExchange" />

    </

     

    service>

    </

     

    services>

    </

     

    system.serviceModel>