次の方法で共有


Introducing the Developer Preview of the JSON Web Token Handler for the Microsoft .NET Framework 4.5

image
The JWT handler class diagram, spanning 3 monitors :-)

 

Today I am really, really happy to announce the developer preview of a new extension that will make the JSON Web Token format (JWT) a first-class citizen in the .NET Framework: the JSON Web Token Handler for the Microsoft .NET Framework 4.5 (JWT handler from now on in this post :-)). 

What is the JSON Web Token (JWT) Format Anyway?

“JSON Web Token (JWT) is a compact token format intended for space constrained environments such as HTTP Authorization headers and URI query parameters. JWTs encode claims to be transmitted as a JavaScript Object Notation (JSON) object […]”. That quote is taken straight from the IETF’s (OAuth Working Group) Internet Draft that specifies the format.

That’s a remarkably straightforward definition, which hints at the good properties of the JWT format which make it especially useful in REST based solutions. JWT is very popular. Just search the web for “JWT token” followed by your programming language of choice, and chances are you’ll find an implementation; Oracle uses it in its Fusion Middleware; Google uses it in its App Engine Security Module;  Salesforce uses it for handling application access; and closer to home, JWT is the token format used by Windows Azure Active Directory for issuing claims for all of its workloads entailing REST exchanges, such as issuing tokens for querying the Graph API; ACS namespaces can issue JWTs as well, even for Web SSO. If that would not be enough, consider that JWT is the token format used in  OpenID Connect. Convinced of the importance of JWT yet? :-)

The JWT Handler

If you want to protect your resources using Windows Azure Active Directory and a lightweight token format, you’ll want your applications to be able to work with JWTs. That will be the appropriate choice especially when more demanding options are not viable: for example, securing a REST service with a SAML token is very likely to put your system under strain, whereas a JWT is the perfect choice for it. And if you are building your applications on .NET 4.5, that’s where the JWT handler comes in.

Given that I am giving the formal definition, let me use the full name of the product for the occasion:

The JSON Web Token Handler for the Microsoft .NET Framework 4.5 is a .NET 4.5 assembly, distributed via a NuGet package, providing a collection of classes you can use for deserializing, validating, manipulating, generating, issuing and serializing JWTs.

The .NET Framework 4.5 already has the concept of security token, in the form of the WIF classes providing abstract types (SecurityToken, SecurityTokenHandler) and out of the box support for concrete formats: SAML1.1, SAML 2.0, X.509, and the like. The JWT handler builds on that framework, providing the necessary classes to allow you to work with JWTs like if they were just as another token format among the ones provided directly in .NET 4.5.
As such, you’ll find in the package classes like JWTSecurityTokenHandler, JWTSecurityToken, JWTIssuerNameRegistry, JWTIssuerTokenResolver and all the classes which are necessary for the WIF machinery to work with the new token type. You would not normally deal with those directly, you’d just configure your app to use WIF (say for Web SSO) and add the JWTSecurityTokenHandler to the handlers collection; the WIF pipeline would call those classes at the right time for you.

Although integration with the existing WIF pipeline is good, we wanted to make sure that you’d have a great developer experience in handling JWTs even when your application is not configured to use WIF. After all, the .NET framework does not offer anything out of the box for enforcing access control for REST services hence (for now ;-)) you’d have to code the request authentication logic yourself, and asking you to set up the WIF config environment on top of that would make things more difficult for you.  To that purpose, we made two key design decisions:

  • We created an explicit representation of the validation coordinates that should be used to establish if a JWT is valid, and codified it in a public class (TokenValidationParameters). We added the necessary logic for populating this class from the usual WIF web.config settings.
  • Along with the usual methods you’d find in a normal implementation of SecurityTokenHandler, which operate with the data retrieved from the WIF configuration, we added an overload of ValidateToken that accept the bits of the token and a TokenValidationParameters instance; that allows you to take advantage of the handler’s validation logic without adding any config overhead.

This is just an introduction, which will be followed by deep dives and documentation: hence I won’t go too deep into the details; however I just want to stress that we really tried our best to make things as easy as we could to program against. For example:  although in the generic case you should be able to validate issuer and audience from lists of multiple values, we provided both collection and scalar versions of the corresponding properties in TokenValidationParameters so that the code in the single values case is as simple as possible. Your feedback will be super important to validate those choices or critique them!

After this super-quick introduction, let’s get a bit more practical with a couple of concrete examples.

Using the JWT Handler with REST Services

Today we also released a refresh of the developer preview of our Windows Azure Authentication Library (AAL). As part of that refresh, we updated all the associated samples to use the JWT hander to validate tokens on the resource side: hence, those samples are meant to demonstrate both AAL and the JWT handler.

To give you a taste of the “WIF-less” use of the JWT token, I’ll walk you through a short snippet from one of the AAL samples.

The ShipperServiceWebAPI project is a simple Web API based service. If you go to the global.asax, you’ll find that we added a DelegatingHandler for extracting the token from incoming requests secured via OAuth2 bearer tokens, which in our specific case (tokens obtained from Windows Azure AD via AAL) happen to be JWTs. Below you can find the relevant code using the JWT handler:

    1:   JWTSecurityTokenHandler tokenHandler = 
             new JWTSecurityTokenHandler();
    2:  // Set the expected properties of the JWT token in the TokenValidationParameters
    3:  TokenValidationParameters validationParameters = 
             new TokenValidationParameters()
    4:   {                   
    5:       AllowedAudience = ConfigurationManager.AppSettings["AllowedAudience"],
    6:         ValidIssuer = ConfigurationManager.AppSettings["Issuer"],
    
    8:         // Fetch the signing token from the FederationMetadata document of the tenant.
    9:         SigningToken = new X509SecurityToken(new X509Certificate2(
                 GetSigningCertificate(
                   ConfigurationManager.AppSettings["FedMetadataEndpoint"])))
   10:   };                       
   11:                  
   12:   Thread.CurrentPrincipal = tokenHandler.ValidateToken(token, 
                                                 validationParameters);

1: create a new JWTSecurityTokenHandler

3: create a new instance of TokenValidationParameters, passing in

5: the expected audience for the service (in our case, urn:shipperservice:interactiveauthentication)

6: the expected issuer of the token (in our case, an ACS namespace: https://humongousinsurance.accesscontrol.windows.net/)

9: the key we use for validating the issuer’s signature. Here we are using a simple utility function for reaching out to ACS’ metadata to get the certificate on the fly, but you could also have it installed in the store, saved it in the file system, or whatever other mechanism comes to mind. Also, of course you could have used a simple symmetric key if the issuer is configured to sign with it.

12: call ValidateToken on tokenHandler, passing in the JWT bits and the validation coordinates. If successfully validated, a ClaimsPrincipal instance will be populated with the claims received in the token and assigned in the current principal.

That’s all there is to it! Very straightforward, right? If you’d compare it with the initialization required by “traditional” WIF token handlers, I am sure you’d be pleasantly surprised :-)

 

Using the JWT Handler With WIF Applications

Great, you can use the JWT handler outside of WIF; but what about using with your existing WIF applications? Well, that’s quite straightforward.

Let’s say you have an MVC4 application configured to handle Web Sign On using ACS; any application will do. For example: remember the blog post I published a couple of weeks ago, the one about creating an ACS namespace which trusts both a Windows Azure Active Directory tenant and Facebook? I will refer to that (although, it’s worth stressing it, ANY web app trusting ACS via WIF will do).

Head to the ACS management portal, select your RP and scroll down to the token format section. By default, SAML is selected; hit the dropdown and select JWT instead.

image

Great! Now open your solution in Visual Studio, and add a package reference to the JSON Web Token Handler for the Microsoft .NET Framework 4.5 NuGet.

That said, open your config file and locate the system.identityModel section:

    1:<system.identityModel>
    2: <identityConfiguration>
    3:   <audienceUris>
    4:     <add value="https://localhost:61211/" />
    5:   </audienceUris>
    6:   <securityTokenHandlers>
    7:     <add type="Microsoft.IdentityModel.Tokens.JWT.JWTSecurityTokenHandler,
                 Microsoft.IdentityModel.Tokens.JWT" />
    8:      <securityTokenHandlerConfiguration>
    9:         <certificateValidation certificateValidationMode="PeerTrust"/>
   10:      </securityTokenHandlerConfiguration>
   11:   </securityTokenHandlers>

Right under </audienceURIs,> paste the lines from 6 to 11. Those lines tell to WIF that there is a class for handling JWT tokens; furthermore, it specifies what signing certificates should be considered valid. Now, that requires a little digression. WIF has another config element, the IssuerNameRegistry, which specifies the thumbprints of the certificates that are associated with trusted issuers. The good news is that the JWT handler will automatically pick up the IssuerNameRegistry settings.

Issuers in the Microsoft world (ACS, ADFS, custom STSes based on WIF) will typically send together with the SAML token itself the bits of the certificate whose corresponding private key was used for signing. That means that you do not really need to install the certificate bits in order to verify the signature of incoming tokens, as you’ll receive the cert bits just in time. And given that the cert bits must correspond to the thumbprint specified by IssuerNameRegistry anyway, you can turn off cert validation (which would verify whether the cert is installed in the trusted people store, that it has been emitted by a trusted CA, or both) without being too worried about spoofing.

Now, JWT is ALL about being nimble: as such, it would be pretty surprising if it too would carry an entire X.509 certificate at every roundtrip; right? The implication for us is that in order to validate the signature of the incoming JWT, we must install the signature verification certificate in the trusted people store.

How do you do that? Well, there are many different tricks you can use. The simplest: open the metadata document (example: https://lefederateur.accesscontrol.windows.net/FederationMetadata/2007-06/FederationMetadata.xml), copy the text of the X509Certificate element from the RoleDescriptor/KeyDescriptor/KeyInfo/X509Data path and save it in a text file with extension .CER. Double-click on the file, hit the “Install Certificate…” button, choose Local Machine, Trusted People, and you’re in business. Yes, I too wish it would be less complicated; I wrote a little utility for automating this, I’ll see if we can find a way to publish it.

Anyway, at this point we are done! Hit F5, and you’ll experience Web SSO backed by a JWT instead of a SAML token. The only visible difference at this point is that your Name property will likely look a bit odd: right now we are assigning the nameidentifier claim to it, which is not what we want to do moving forward, but we wanted to make sure that there is a value in that property for you as you experiment with the handler.

How Will You Use It?

Well, there you have it. JWT is a very important format, and Windows Azure Active Directory uses it across the board. With the developer preview of the JWT handler, you now have a way to process JWTs in your applications. We’ll talk more about the JWT handler and suggest more ways you can take advantage of the handler. Above all, we are very interested to hear from you how you want to use the handler in your own solutions: the time to speak up is now, as during the dev preview we still have time to adjust the aim. Looking forward for your feedback!