none
Rest API /WCF authentication over HTTPS RRS feed

  • Question

  • I have developed a Rest API and hosting it by using WebServiceHost where I am trying to authenticate over HTTPS. Applied SSL certificate by using netsh command. Deployed the service in a Application server in the network. 

    When I try to browse the service URL by using IE or Chrome, I am getting the response without asking any network credentials.

    Code :

    _serviceHost = new System.ServiceModel.Web.WebServiceHost(typeof(PolicySearchService, new Uri(Configuration.SearchPolicyBaseAddress));
    _serviceHost.Open();


    My app.config file looks following....

    <system.serviceModel>
       <services>
        <service name="MyCompany.PolicyReferenceService.PolicySearchService" behaviorConfiguration="serviceBehavior">
          <endpoint address="" binding="basicHttpBinding" bindingConfiguration="BasicHttpSSLBinding" contract="MyCompany.PolicyReferenceService.Service.IPolicySearchService" />      
          <host>
            <baseAddresses>
              <add baseAddress="https//Server:8845/PolicySearchService"/>
            </baseAddresses>
          </host>
        </service>
      </services>
      <behaviors>
        <serviceBehaviors>
          <behavior name="serviceBehavior">
            <serviceMetadata httpGetEnabled="false" httpsGetEnabled="true"></serviceMetadata>
            <serviceDebug includeExceptionDetailInFaults="false"/>        
          </behavior>
        </serviceBehaviors>    
      </behaviors>
      <bindings>
      <basicHttpBinding>
        <binding name="BasicHttpSSLBinding">
          <security mode="Transport">         
          </security>
        </binding>
      </basicHttpBinding>
    </bindings>
      </system.serviceModel> 


    Just to check user authentication, I am using the following two lines of code. It always says context is anonymous.
    Code:
    ------
    ServiceSecurityContext context = OperationContext.Current.ServiceSecurityContext;
    if(context.IsAnonymous)
      throw new Exception("You are not authenticated.");


    How to tell service to ask for credentials when someone is browsing the URL over HTTPS ?

    Thanks,
    Prav
    Wednesday, September 21, 2016 3:20 PM

Answers

  •     

    HI,

    Browsing to the endpoint is different to invoking the service. 

    These settings apply to the webhttpbinding named "webHttp" as per config. 

    1. You have configured transport security over SSL

    2. You are using transport credentials (Basic) for authentication.

    When you browse to the URL on IE, you are not invoking the service contract Test.PolicyReferenceService.Service.IPolicySearchService endpoint , but accessing the metadata endpoint over https get as per the line (shown below) from your config. Accessing the metadata  is anonymous over https and does not require authentication.

    Note:  This would be different if your application  was hosted in IIS, when you can enable authentication at the Web app level, so when you browse IIS will handle the request first and expect it be authenticated.

    <serviceBehaviors> <behavior name="serviceBehavior"> <serviceMetadata httpGetEnabled="false" httpsGetEnabled="true">

    </serviceMetadata> <serviceDebug includeExceptionDetailInFaults="false"/> </behavior>


    Given then this is self hosted, in order to check if your app requires authentication is to actually invoke a service operation and check like you already have .

    ServiceSecurityContext svcSecurityContext; 
    svcSecurityContext = OperationContext.Current.ServiceSecurityContext;
    
    if(svcSecurityContext.IsAnonymous == true)
    
      throw new Exception("You are not authenticated.");
    

    If this does not still work with the setting like Edward has already mentioned, then it needs to be investigated further..
    <!-- Transport mode means SSL (https here )-->     
    <security mode="Transport">
    <!-- This is authentication-->
        <transport clientCredentialType="Basic" />
    </security>


    So when you go to the metadata endpoint via https get , that does not need authentication. So the browser not prompting for credentials is correct behaviour, as it the service contract that requires authentication not the meta data.


    Tuesday, October 4, 2016 8:16 AM

All replies

  • Hi Prav,

    HTTPS is used to security the message between client and service, it is not used to authenticate. And Rest Service uses WebHttpBinding instead of basicHttpBinding. Your configuration file is used to SOAP Service.

    For Rest Service Security considerations, I suggest you refer the link below:

    # Security Considerations

    https://msdn.microsoft.com/en-us/library/dd203052.aspx

    For security WCF Rest service over https, I suggest you refer

    Reference: http://www.allenconway.net/2012/05/creating-wcf-restful-service-and-secure.html

    For Basic Authentication for Rest Service, I suggest you refer

    # Basic Authentication for REST service WebHttpBinding

    http://www.allenconway.net/2012/05/creating-wcf-restful-service-and-secure.html

    Best Regards,

    Edward


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.


    Thursday, September 22, 2016 9:19 AM
  • Hi Edward,

    Thanks to your reply.

    I have exactly configured as Allen mentioned in the following blog.

    http://www.allenconway.net/2012/05/creating-wcf-restful-service-and-secure.html

    Now, I am getting IsAnonymous is true. My question is, how to authenticate the client ?

    <system.serviceModel>
       <services>
        <service name="MyCompany.PolicyReferenceService.PolicySearchService" behaviorConfiguration="serviceBehavior">
          <endpoint address="" binding="webHttpBinding" bindingConfiguration="webHttpBehavior" contract="MyCompany.PolicyReferenceService.Service.IPolicySearchService" behaviorConfiguration="webHttpBehavior"/>
           <endpoint address="mex" binding="mexHttpsBinding" contract="MyCompany.PolicyReferenceService.Service.IPolicySearchService" />
          <host>
            <baseAddresses>
              <add baseAddress="https//server:8845/PolicySearchService"/>
            </baseAddresses>
          </host>
        </service>
      </services>
      <behaviors>
        <serviceBehaviors>
          <behavior name="serviceBehavior">
            <serviceMetadata httpGetEnabled="false" httpsGetEnabled="true"></serviceMetadata>
            <serviceDebug includeExceptionDetailInFaults="false"/>        
          </behavior>
        </serviceBehaviors>
        <endpointBehaviors>
          <behavior name="web">
            <webHttp/>
          </behavior>
        </endpointBehaviors>
      </behaviors>
      <bindings>
      <webHttpBinding>
        <binding name="webHttpTransportSecurity">
         <security mode="Transport">          
            </security>
        </binding>
      </webHttpBinding>
    </bindings>

    Code :

    ServiceSecurityContext svcSecurityContext;
    svcSecurityContext = OperationContext.Current.ServiceSecurityContext;

    if(svcSecurityContext.IsAnonymous == true)

      throw new Exception("You are not authenticated.");

    My question is, how to authenticate the client ?

    Thanks,

    Prav

    Thursday, September 22, 2016 2:03 PM
  • Hi Prav,

    For asking network credentials, I think you could try Transport security with Basic clientCredentialType.

    Here is a simple configuration.

         <webHttpBinding>
    
            <binding name="webHttp">
    
              <security mode="Transport">
    
                <transport clientCredentialType="Basic"/>
    
              </security>          
    
            </binding>
    
          </webHttpBinding>
    

    Best Regards,

    Edward


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.


    Friday, September 23, 2016 2:31 AM
  • Hi Edward,

    I have changed as you suggested but when I browse the service URL in IE or Chrome it is not asking for any credentials. My App.Config looks like below.

    Mind that this is a windows service launching service as WebServiceHost

    Code:

    private ServiceHost _serviceHost;

    _serviceHost = new System.ServiceModel.Web.WebServiceHost(typeof(PolicySearchService), new Uri("https//server:8845/PolicySearchService"));

    App.Config

    <system.serviceModel>
       <services>
        <service name="Test.PolicyReferenceService.PolicySearchService" behaviorConfiguration="serviceBehavior">
          <endpoint address="" binding="webHttpBinding" bindingConfiguration="webHttp" contract="Test.PolicyReferenceService.Service.IPolicySearchService" behaviorConfiguration="web"/>
           <endpoint address="mex" binding="mexHttpsBinding" contract="Test.PolicyReferenceService.Service.IPolicySearchService" />
          <host>
            <baseAddresses>
              <add baseAddress="https//server:8845/PolicySearchService"/>
            </baseAddresses>
          </host>
        </service>
      </services>
      <behaviors>
        <serviceBehaviors>
          <behavior name="serviceBehavior">
            <serviceMetadata httpGetEnabled="false" httpsGetEnabled="true"></serviceMetadata>
            <serviceDebug includeExceptionDetailInFaults="false"/>        
          </behavior>
        </serviceBehaviors>
        <endpointBehaviors>
          <behavior name="web">
            <webHttp/>
          </behavior>
        </endpointBehaviors>
      </behaviors>
      <bindings>
      <webHttpBinding>
        <binding name="webHttp">
         <security mode="Transport">
              <transport clientCredentialType="Basic" />
            </security>
        </binding>
      </webHttpBinding>
    </bindings>
      </system.serviceModel>  

    Thanks,

    Praveen

    Tuesday, September 27, 2016 1:07 PM
  • Hi Prav,

    Did you get any error? Could you call your service method successfully without credential? As my test, if you use Uri both in code and configuration with “https//server:8845/PolicySearchService”, it will get error like “This collection already contains an address with scheme https”.

    I suggest you try below code without URI, and make sure your baseAddress is a valid https address in App.config..

    WebServiceHost host = new WebServiceHost(typeof(RestService));

    Best Regards,

    Edward


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.





    Wednesday, September 28, 2016 12:50 PM
  •     

    HI,

    Browsing to the endpoint is different to invoking the service. 

    These settings apply to the webhttpbinding named "webHttp" as per config. 

    1. You have configured transport security over SSL

    2. You are using transport credentials (Basic) for authentication.

    When you browse to the URL on IE, you are not invoking the service contract Test.PolicyReferenceService.Service.IPolicySearchService endpoint , but accessing the metadata endpoint over https get as per the line (shown below) from your config. Accessing the metadata  is anonymous over https and does not require authentication.

    Note:  This would be different if your application  was hosted in IIS, when you can enable authentication at the Web app level, so when you browse IIS will handle the request first and expect it be authenticated.

    <serviceBehaviors> <behavior name="serviceBehavior"> <serviceMetadata httpGetEnabled="false" httpsGetEnabled="true">

    </serviceMetadata> <serviceDebug includeExceptionDetailInFaults="false"/> </behavior>


    Given then this is self hosted, in order to check if your app requires authentication is to actually invoke a service operation and check like you already have .

    ServiceSecurityContext svcSecurityContext; 
    svcSecurityContext = OperationContext.Current.ServiceSecurityContext;
    
    if(svcSecurityContext.IsAnonymous == true)
    
      throw new Exception("You are not authenticated.");
    

    If this does not still work with the setting like Edward has already mentioned, then it needs to be investigated further..
    <!-- Transport mode means SSL (https here )-->     
    <security mode="Transport">
    <!-- This is authentication-->
        <transport clientCredentialType="Basic" />
    </security>


    So when you go to the metadata endpoint via https get , that does not need authentication. So the browser not prompting for credentials is correct behaviour, as it the service contract that requires authentication not the meta data.


    Tuesday, October 4, 2016 8:16 AM
  • Hi Lanax/Edward,

    I have changed the app.config file setting as mentioned above and the service is now asking for credentials and able to get OperationContext.Current.ServiceSecurityContext.WindowsIdentity.Name in the service.

    Thanks for your help.

    Regards,

    Prav

    Friday, October 7, 2016 9:02 AM