Home > Identity Server > Identity Server v3 LOB Part 2 Web Api & WCF Configuration

Identity Server v3 LOB Part 2 Web Api & WCF Configuration

This is Part 2 of a series of three posts about setting up and configuring Identity Server for a Line of Business application.

Links

Intro Identity Server v3 Walk through for LOB application

Part 1 Hosting Identity Framework With IIS

Part 2 IDSv3 Web Api & WCF Configuration

Part 3 IDS Client Walkthrough

Client Sample Code

Identity Server Code

In Part 2, we’re going to walk through the Web Api & WCF setup. Web Api is simple and straight forward. I’m adding a stub here for it in case we need to add more information down the road.

Web Api

While writing this post, I don’t recall if we added the IdentityWebApis to the Thinktecture.IdentityServer3 solution or the original zip contained it but the configuration is in the Starup.cs file.

In the UseIdentityServerBearerTokenAuthentication() method. Set the Authority to the URL of your Identity Server web app. Required scopes will not need to be changed unless you changed the scope for the IdSvr startup and the client application.

If you want to force authentication, in the WebApiConfig.cs you add the following line of code: config.Filters.Add(new
AuthorizeAttribute());

That’s pretty much it Web Api.

WCF

WCF was built for SOAP and natively for claims authentication, WIF is typically used with SAML tokens. However, WCF is highly configurable and with the help of some online posts we figured out how to create a custom IDispatcherMessageInspector to handle bearer tokens. The WCFJWTServices is the web app inside the Thinktecture.IdentityServer3 solution the sample we’ll use to walk through how to configure WCF to build a ClaimsPrincipal out of a JWT token obtained from IDS v3.

The following NuGet packages are required for the code below to work.

Identity Protocol Extensions for Microsoft .Net Framework 4.5

JSON Web Token Handler for Microsoft .Net Framework 4.5

Json.Net

The BearerTokenMessageInspector class contains the custom code which will allow our WCF services to build a ClaimsPrincipal from a JWT token.

AfterReceiveRequest() method inspects the HttpRequest headers and makes sure there is an AuthorizationHeader passed in. In Part 3 of this series, we will cover how to build an Http Authorization header to pass into WCF.

The Authenticate class is where the JWT is processed.

First to make sure we’re dealing with a JWT token, we check for Bearer at the start of the header. If present we extract the JWT token from the string.

We make a call to CanReadToken() to make sure the token is readable.

Next, we must instantiate a TokenValidationParamters variable. We use a private CreateTokenValidationParameters() method to build these options. The key here is to make sure the audience is valid and we build a X509SecurityToken which be used to Validate the JWT token.

To build the Json Web Key (JWK) dynamically, first we make a call to Identity services /core/.well-known/jwks endpoint because we need the x5c value. We parse the string into a JObject. Then we write code to parse out the x5c value. We use the x5c value to ultimately build an X509SecurityToken. Note, you can use a browser and browse to the URL, get the value and hard code it in a config file or somewhere if you don’t care about doing this dynamically.

Once we have the TokenValidationParameters, then we make a call to ValidateToken(). To do this, we must use the JwtSecurityTokenHandler. In other samples, you define your SecurityTokenHandlers in the web.config. However, what I found is that using JwtSecurityTokenHandler, the call to FederatedAuthentication.FederationConfiguration.IdentityConfiguration.SecurityTokenHandlers.ValidateToken() only takes one parameter. To process a JWT token, JwtSecurityTokenHandler requires you pass in the token, validationparameters and then a reference to a SecurityToken which will get built if ValidateToken() is successful.

The call to ValidateToken() if successful will generate a ClaimsPrincipal which will used to Authenticate. Once authenticated, then the Service AuthorizationContext is populated and completes the authentication.

 

Note: Most of the code for the Bearer Token inspector and WCF configuration below came from this post. The code to for CreateTokenValidationParameters is based off code found here.

 

WCF Configuration

Once the WCF code above is completed, we must make changes to the web.config for the WCF service for the new code to work. First, to wire up the BearerTokenMessageInspector, we must add an extensions element to the system.servicemodel element.

<extensions>

<behaviorExtensions>

<add
name=bearerTokenRequired
type=WCFJWTServices.BearerTokenExtensionElement, WCFJWTServices />

</behaviorExtensions>

</extensions>

Next, in the Servicebehavior section, add the newly created extension.

<behaviors>

<serviceBehaviors>

<behavior
name=WcfServiceBehavior>

<!– To avoid disclosing metadata information, set the values below to false before deployment –>

<serviceMetadata
httpGetEnabled=true
httpsGetEnabled=true/>

<!– To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information –>

<serviceDebug
includeExceptionDetailInFaults=false/>

 

<serviceCredentials
useIdentityConfiguration=true />

<serviceAuthorization
principalPermissionMode=Always />

 

<!– Comment this out to update WSDL –>


<bearerTokenRequired />

 

</behavior>

</serviceBehaviors>

</behaviors>

Note, at the writing of this post, I find when we make changes to our services, we must comment out <bearerTokenRequired /> to generate or update the WSDL. When done, uncomment. Otherwise you will get an exception.

Additionally we have to configuration for IdentityModel.

First the following configSections are added:

<configSections>

<section
name=system.identityModel
type=System.IdentityModel.Configuration.SystemIdentityModelSection, System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089 />

<section
name=system.identityModel.services
type=System.IdentityModel.Services.Configuration.SystemIdentityModelServicesSection, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089 />

</configSections>

 

The config file I use contains an element for System.IdentityModel.Services in the Compilation/Assemblies section.

The system.IdentityModel section is where define the JwtSecurityTokenHandler. I had issues with the IssuerNameRegistry section that’s commented out in the sample.

<system.identityModel>

<identityConfiguration>

<audienceUris>

<add
value=users />

</audienceUris>

<securityTokenHandlers>

<clear />

<!–<add type=”System.IdentityModel.Tokens.JwtSecurityTokenHandler, System.IdentityModel.Tokens.Jwt, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35″ />–>

<add
type=System.IdentityModel.Tokens.JwtSecurityTokenHandler, System.IdentityModel.Tokens.Jwt />

<securityTokenHandlerConfiguration>

<certificateValidation
certificateValidationMode=None />

<!–<issuerNameRegistry type=”System.IdentityModel.Tokens.ConfigurationBasedIssuerNameRegistry, System.IdentityModel”>

<trustedIssuers>

<add thumbprint=”97249e … 158de” name=”contoso.com” />

</trustedIssuers>

</issuerNameRegistry>–>

</securityTokenHandlerConfiguration>

</securityTokenHandlers>

</identityConfiguration>

</system.identityModel>

Conclusion

With the above configuration, any calls made to your WCF services, the BearerTokenMessageInspector code should run for any call. If there are problems, the exception reported back to the client at this point is generic and not helpful most of the time. I’d advise attaching to the IIS process and setting a break point in the AfterReceiveRequest() first then work your way from there.

Again, if you want to test the service endpoint loads in a browser to check for issues or you need to generate a WSDL, you must comment out the <bearerTokenRequired /> from the ServiceBehavior. This disables security so be sure and re-enable it when finished.

 

Advertisements
Categories: Identity Server
  1. csizo
    August 14, 2015 at 11:23 am

    Saved me more than a week worktime!
    Actually this solution is also working with WebHttpBinding (WCF REST) too.
    Thanks!

  2. September 22, 2015 at 7:28 am

    Great walkthrough, thanks.

    Quick question – the “sub” claim is missing. Sometimes ClaimTypes.NameIdentifier is provided; other times it is not.

    Is there anyway to guarantee access to the User ID?

  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: