Active Client token request

Jun 22, 2012 at 2:30 AM

I have identityserver setup on a sandbox server "einstein" host name.

I have a test service https://joedev001/Portal on my development server "joedev001". Federated to identityserver on the "einstein" sandbox server.

How would I configure the identityserver "global configuration" and "Relying Parties" to allow an active client running on my "joedev001" machine to request a SAML 1.0 token using simple get?

I would like to create a ChannelFactory to my portal service with the token obtained by my active client? Is this even possible? at least for testing :D

Coordinator
Jun 22, 2012 at 7:22 AM

why ChannelFactory and GET in combination?

Are you doing HTTP/REST or SOAP?

http://wiki.thinktecture.com/IdentityServer.MainPage.ashx

Jun 22, 2012 at 1:26 PM

Hi Dominick,

My service (hosted via IIS7.5 service.svc file) has two endpoints exposed one is SOAP the other is REST.  It will be interacted with a smart client. I am trying to test the endpoints by obtaining a token from identityServer, using .NET C# HttpClent for the REST endpoint and SOAP Channel for the SOAP endpoint call CreatChannelWithIssuedToken.

Can I do this? using the "simple" endpoint to request a token using the HttpClient class GetAsync method request a SAML1.0 token, and use that token to make a POST request to my REST endpoint. And can I use the same token to then create a SOAP channel to call the SOAP methods?

Right now I can't get the token request to come back to my smart client.  I can see the activity for the request in the identityserver.svclog so, I know the request is making it to the IdentityServer. The trace goes like this:

  1. Token type: urn:oasis:names:tc:SAML:1.0:assertion
  2. Simple HTTP endpoint called for realm http://joedev001/portal/
  3. Fetching Cache_GlobalConfiguration from cache: hit
  4. Configuring token service
  5. Fetching Cache_GlobalConfiguration from cache: hit
  6. Fetching Cache_SigningCertificate from cache: hit
  7. Starting token request from Administrator for http://joedev/portal/
  8. Authentication method: http://schemas.microsoft.com/ws/2008/06/identity/authenticationmethod/password
  9. Starting PolicyOptions creation
  10. Token Type: urn:oasis:names:tc:SAML:1.0:assertion
  11. Requested KeyType: http://schemas.microsoft.com/idfx/keytype/bearer
  12. Passive request (this makes me suspicious)
  13. Relying Party found in registry - Realm: http://joedev001/portal/ (Portal Service)
  14. Encrypting certificate set from registry
  15. Token encryption: True
  16. ReplyTo address set to realm address (my relying party config for the service ReplyTo setting is currently empty, what do you use for a service?)
  17. SSL used: False
  18. No request claims (thought I should get username, role claims)
  19. PolicyOptions creation done.
  20. Starting policy validation
  21. Configuration requires SSL - but clear text reply address used

Keep in mind I'm very green when most of this technology; but I have made a lot of progress!!!

I'm sure I'll have to relook at how the service's web.config, the clients app.config, identityServers "Global Configuration", and "Relying Party" configuration.

I can POST to the service with fiddler, without token, and I get the expected response as Anonymous user.

Coordinator
Jun 25, 2012 at 4:52 PM

Use https:// for the realm (step 2).

Jun 26, 2012 at 3:11 AM

My Service has no UI.

I still don't get any security context other than anonymous at my service.

Here is my service's Web.config file.

<?xml version="1.0" encoding="UTF-8"?>
<!--
    Note: As an alternative to hand editing this file you can use the 
    web admin tool to configure settings for your application. Use
    the Website->Asp.Net Configuration option in Visual Studio.
    A full list of settings and comments can be found in 
    machine.config.comments usually located in 
    \Windows\Microsoft.Net\Framework\v2.x\Config 
-->
<configuration>
  <configSections>
    <section name="microsoft.identityModel" type="Microsoft.IdentityModel.Configuration.MicrosoftIdentityModelSection, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
    <section name="loggingConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.LoggingSettings, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.505.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="true" />
  </configSections>
  <appSettings>
    <add key="FederationMetadataLocation" value="https://einstein/sageCrowdSTS/FederationMetadata/2007-06/FederationMetadata.xml" />
  </appSettings>
  <connectionStrings />
  <location path="FederationMetadata">
    <system.web>
      <authorization>
        <allow users="*" />
      </authorization>
    </system.web>
  </location>
  <system.net>
    <!-- The default proxy settings are so that fiddler can monitor traffic remove for production deployment -->
    <!--<defaultProxy>
      <proxy bypassonlocal="False" usesystemdefault="True" proxyaddress="8888"/>
    </defaultProxy>-->
  </system.net>
  <system.web>
    <authorization>
      <allow users="*" />
    </authorization>
    <compilation debug="true" targetFramework="4.0">
      <assemblies>
        <add assembly="Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
        <add assembly="System.ServiceProcess, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A" />
        <add assembly="System.Web.WebPages.Razor, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
        <add assembly="Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
      </assemblies>
    </compilation>
    <authentication mode="None" />
    <pages>
      <controls>
        <add tagPrefix="asp" namespace="System.Web.UI" assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
      </controls>
    </pages>
    <httpRuntime requestValidationType="WSFedRequestValidator" />
  </system.web>
  <system.web.extensions>
    <scripting>
      <webServices>
        <!--
          Uncomment this section to enable the authentication service. Include 
          requireSSL="true" if appropriate.
        -->
        <!-- <authenticationService enabled="true" requireSSL = "true" /> -->
        <!--
          Uncomment these lines to enable the profile service, and to choose the 
          profile properties that can be retrieved and modified in ASP.NET AJAX 
          applications.
        -->
        <!-- 
        <profileService enabled="true"
                        readAccessProperties="propertyname1,propertyname2"
                        writeAccessProperties="propertyname1,propertyname2" />
        -->
        <!-- Uncomment this section to enable the role service. -->
        <!-- <roleService enabled="true"/> -->
      </webServices>
      <!-- <scriptResourceHandler enableCompression="true" enableCaching="true" /> -->
    </scripting>
  </system.web.extensions>
  <system.serviceModel>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true">
      <serviceActivations>
        <add relativeAddress="service.svc" service="sageCrowd.Portal.PortalService" />
      </serviceActivations>
    </serviceHostingEnvironment>
    <standardEndpoints>
      <webHttpEndpoint>
        <standardEndpoint name="" helpEnabled="true" automaticFormatSelectionEnabled="true" />
      </webHttpEndpoint>
    </standardEndpoints>
    <extensions>
      <behaviorExtensions>
        <add name="federatedServiceHostConfiguration" type="Microsoft.IdentityModel.Configuration.ConfigureServiceHostBehaviorExtensionElement, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
      </behaviorExtensions>
    </extensions>
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <federatedServiceHostConfiguration name="PortalService" />
          <serviceCredentials>
            <!--Certificate added by FedUtil.  Subject='CN=JoeDev001', Issuer='CN=JoeDev001'.-->
            <serviceCertificate findValue="65FA5727531DCBE995C22B2B66BEBA8B731F3F13" storeLocation="LocalMachine" storeName="My" x509FindType="FindByThumbprint" />
          </serviceCredentials>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <protocolMapping>
      <add scheme="http" binding="ws2007FederationHttpBinding" />
    </protocolMapping>
    <bindings>
      <ws2007FederationHttpBinding>
        <binding>
          <security mode="Message" >
            <message issuedTokenType="http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV2.0" >
              <issuerMetadata address="https://einstein/sageCrowdSTS/issue/wstrust/mex" />
              <claimTypeRequirements>
                <!--Following are the claims offered by STS 'https://einstein/trust/initial'. Add or uncomment claims that you require by your application and then update the federation metadata of this application.-->
                <add claimType="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name" isOptional="true" />
                <add claimType="http://schemas.microsoft.com/ws/2008/06/identity/claims/role" isOptional="true" />
                <add claimType="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" isOptional="true" />
                <!--<add claimType="http://identityserver.thinktecture.com/claims/profileclaims/facebookid" isOptional="true" />-->
                <!--<add claimType="http://identityserver.thinktecture.com/claims/profileclaims/webpage" isOptional="true" />-->
                <!--<add claimType="http://identityserver.thinktecture.com/claims/profileclaims/facebookname" isOptional="true" />-->
              </claimTypeRequirements>
            </message>
          </security>
        </binding>
      </ws2007FederationHttpBinding>
    </bindings>
  </system.serviceModel>
  <!-- 
  Uncomment the lines below to enable WIF tracing to: WIFTrace.e2e. 
  Open the trace file using the SvcTraceViewer.exe tool (shipped with the WCF SDK available from Microsoft) or a xml viewer.
  Refer to MSDN if you wish to add WCF tracing.
  -->
  <system.diagnostics>
    <!-- set autoflush to false to increase performance -->
    <trace autoflush="true" />
    <sources>
      <source name="Microsoft.IdentityModel" switchValue="Verbose">
        <listeners>
          <add name="xml" type="System.Diagnostics.XmlWriterTraceListener" initializeData="WIFTrace.e2e" />
        </listeners>
      </source>
      <!-- message logging -->
      <source name="System.ServiceModel.MessageLogging">
        <listeners>
          <add name="ServiceModelMessageLoggingListener" />
        </listeners>
      </source>
      <!-- service model tracing -->
      <source name="System.ServiceModel" switchValue="Warning,ActivityTracing" propagateActivity="true">
        <listeners>
          <add name="ServiceModelTraceListener" />
        </listeners>
      </source>
      <!-- WIF tracing -->
      <source name="Microsoft.IdentityModel" switchValue="Warning">
        <listeners>
          <add name="IdentityModelListener" />
        </listeners>
      </source>
    </sources>
    <!-- worker process account needs write access to the configured tracing directories -->
    <sharedListeners>
      <add name="IdentityModelListener" type="System.Diagnostics.XmlWriterTraceListener, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" initializeData="c:\inetpub\wwwroot\Portal\Logs\portal_identityModel.svclog" traceOutputOptions="Timestamp">
        <filter type="" />
      </add>
      <add name="ServiceModelMessageLoggingListener" type="System.Diagnostics.XmlWriterTraceListener, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" initializeData="c:\inetpub\wwwroot\Portal\Logs\portal_messages.svclog" traceOutputOptions="Timestamp">
        <filter type="" />
      </add>
      <add name="ServiceModelTraceListener" type="System.Diagnostics.XmlWriterTraceListener, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" initializeData="c:\inetpub\wwwroot\Portal\Logs\portal_trace.svclog" traceOutputOptions="Timestamp">
        <filter type="" />
      </add>
    </sharedListeners>
  </system.diagnostics>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true">
      <add name="SessionAuthenticationModule" type="Microsoft.IdentityModel.Web.SessionAuthenticationModule, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
      <add name="WSFederationAuthenticationModule" type="Microsoft.IdentityModel.Web.WSFederationAuthenticationModule, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
    </modules>
  </system.webServer>
  <loggingConfiguration name="PortalLogging" tracingEnabled="true" defaultCategory="General">
    <listeners>
      <add name="Rolling Flat File Trace Listener" type="Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.RollingFlatFileTraceListener, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.505.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.RollingFlatFileTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.505.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" formatter="Text Formatter" rollSizeKB="10000" />
    </listeners>
    <formatters>
      <add type="Microsoft.Practices.EnterpriseLibrary.Logging.Formatters.TextFormatter, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.505.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" template="Timestamp: {timestamp}{newline}&#xA;Message: {message}{newline}&#xA;Category: {category}{newline}&#xA;Priority: {priority}{newline}&#xA;EventId: {eventid}{newline}&#xA;Severity: {severity}{newline}&#xA;Title:{title}{newline}&#xA;Machine: {localMachine}{newline}&#xA;App Domain: {localAppDomain}{newline}&#xA;ProcessId: {localProcessId}{newline}&#xA;Process Name: {localProcessName}{newline}&#xA;Thread Name: {threadName}{newline}&#xA;Win32 ThreadId:{win32ThreadId}{newline}&#xA;Extended Properties: {dictionary({key} - {value}{newline})}" name="Text Formatter" />
    </formatters>
    <categorySources>
      <add switchValue="All" name="General">
        <listeners>
          <add name="Rolling Flat File Trace Listener" />
        </listeners>
      </add>
    </categorySources>
    <specialSources>
      <allEvents switchValue="All" name="All Events" />
      <notProcessed switchValue="All" name="Unprocessed Category" />
      <errors switchValue="All" name="Logging Errors &amp; Warnings">
        <listeners>
          <add name="Rolling Flat File Trace Listener" />
        </listeners>
      </errors>
    </specialSources>
  </loggingConfiguration>
  <microsoft.identityModel>
    <service name="PortalService" saveBootstrapTokens="true" >
      <audienceUris>
        <add value="https://joedev001/Portal/" />
      </audienceUris>
      <securityTokenHandlers>
        <securityTokenHandlerConfiguration saveBootstrapTokens="true" />
      </securityTokenHandlers> 
      <federatedAuthentication>
        <wsFederation passiveRedirectEnabled="true"
                      issuer="https://einstein/trust/initial"
                      realm="https://joedev001/portal/"
                      requireHttps="true" />
      </federatedAuthentication>
      <issuerNameRegistry type="Microsoft.IdentityModel.Tokens.ConfigurationBasedIssuerNameRegistry, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
        <trustedIssuers>
          <add thumbprint="xxxxxxxx" name="https://einstein/trust/initial" />
        </trustedIssuers>
      </issuerNameRegistry>
    </service>
  </microsoft.identityModel>
</configuration>
My Global.asax looks like This
<%@ Application Language="C#" %>
<script runat="server">
    void Application_Start(object sender, EventArgs e) 
    {
        // Code that runs on application startup
        System.Web.Routing.RouteTable.Routes.Add(
            new System.ServiceModel.Activation.ServiceRoute("",
                new System.ServiceModel.Activation.WebServiceHostFactory(),
                typeof(sageCrowd.Portal.PortalService)));
    }
    
    void Application_End(object sender, EventArgs e) 
    {
        //  Code that runs on application shutdown
    }
        
    void Application_Error(object sender, EventArgs e) 
    { 
        // Code that runs when an unhandled error occurs
    }

    void Session_Start(object sender, EventArgs e) 
    {
        // Code that runs when a new session is started
    }

    void Session_End(object sender, EventArgs e) 
    {
        // Code that runs when a session ends. 
        // Note: The Session_End event is raised only when the sessionstate mode
        // is set to InProc in the Web.config file. If session mode is set to StateServer 
        // or SQLServer, the event is not raised.
    }
       
</script>

Here is how i get my token
private static string TestGetIdPTokenSimpleHttpGet()
{
  System.Diagnostics.Debug.WriteLine("requesting token from IdP...");

  var stsClient = new HttpClient();
  stsClient.SetBasicAuthenticationHeader("Administrator", "xxxxx");
  string stsSimpleUri = string.Format("{0}?realm={1}", idpSimpleEndpoint, svcRealm);
  var result = stsClient.Get(stsSimpleUri);
  string content = result.Content.ReadAsString();
  return content;
}
Here is how I call myService
private void TestPortalRESTEndpoint()
{
  string token = TestGetIdPTokenSimpleHttpGet();
  var portalClient = new System.Net.Http.HttpClient();
  portalClient.BaseAddress = new Uri(svcEndpoint);
  portalClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token);
  System.Net.Http.StringContent body = new System.Net.Http.StringContent(
                "<string xmlns=\"http://schemas.microsoft.com/2003/10/Serialization/\">Hello</string>", Encoding.UTF8, "application/xml");
  var responseMessage = portalClient.PostAsync(svcEndpoint + "/SubmitRequest", body).Result;
  responseMessage.EnsureSuccessStatusCode();
  string respone = responseMessage.Content.ReadAsStringAsync().Result;
}
Hopefully this is enough info to tell me what I'm doing wrong.
Coordinator
Jun 26, 2012 at 7:26 AM

I see - you are using the ws federation binding - but this is supposed to be a HTTP-based service (WebServiceHost).

They don't work together.

You would need to use something like this:

https://github.com/thinktecture/Thinktecture.IdentityModel.Web

...or switch to ASP.NET Web API when you are doing HTTP.