JSON Signing and Encryption Walkthrough

This topic demonstrates how to use JSON signing and encryption in EmpowerID and is comprised of the following activities:

  1. Creating a Web API application in Workflow Studio
  2. Generating a signing certificate
  3. Creating a client application to consume the API Request

  4. Adding code to encrypt the request in Workflow Studio

  5. Creating a client application to consume the encrypted API Request

Creating a Web API application in Workflow Studio

  1. In Workflow Studio, create new Class Library item, TestJWSApi, and enable Web Api Implementation in this item. To enable Web API implementation, go to the Properties tab and from the Property Grid, select Supports and from the list of Supported Types, select WebApi and click OK.
  2. Switch to the Solution tab and from the Code Tree tab, right-click on the TestJWSApi item and from the context menu, select Add New WebApi Implementation.
  3. In the Code Tree, expand the Classes folder. You should see that Workflow Studio generated the following four classes:
    • SignedRequests.cs
    • Signed RequestController.cs
    • SignedRequestsInputModel.cs
    • SignedRequestsRoutes.cs

  4. From the Code Tree, double-click on SignedRequestsController.cs to open the file in the C# code editor.
  5. Modify the SignedRequestsController class so that it appears as shown in the below code.

    Please note the use of this.Json() instead of this.JsonWS().

    public class SignedRequestsController : ApiControllerBase
    {
         private SignedRequests _implInstance;
         public SignedRequestsController()
         {
              _implInstance = new SignedRequests();
         }
    		 
         [JsonWebSignature]
         [HttpPost]
         public IHttpActionResult GetUserJWS(SignedRequestsInputModel model)
         {
             var results = _implInstance.GetUser(model);
             return this.Json((object)results);
         }
    }
  6. Compile and Publish the TestJWSApi Class Library item.

Creating the Signing Certificate

  1. Locate and run the EmpowerID Certificate Manager, CertificateManager.exe, from the EmpowerID programs folder.
  2. Click the Generate tab, select X509 Certificate, provide a Password and an Output Folder path.
  3. Select the Import to EmpowerID Certificate Store and Import to Local Certificate Store options and then click Generate to generate a SHA256 self-signed certificate.



    The newly generated private key certificate, EmpowerID_SelfSigned_Cert.pfx, will be added to the Output Folder you specified as well to the EmpowerID database and the Local Certificate Store under Personal Certificates.

  4. From the EmpowerID Web UI, create an OAuth Provider Application, TestOAuth. Through the JSON Web Token tab, assign a Signing Certificate to the OAuth provider application. The Public Key of this certificate will be used to verify Signed JSON Requests to this application.

    The ClientID, the ApiKey, and the Client Secret of the TestOAuth OAuth Provider Application will be used later in this walkthrough.

Creating a client application to consume the API Request

  1. Open Visual Studio 2013 or above and create a new Console Application project, TestSignedApiRequests.
  2. Locate the following assemblies in the EmpowerID programs folder and add them to the project as references.
    • TheDotNetFactory.Framework.SAML.dll
    • Newtonsoft.Json.dll
    • Microsoft.Practices.EnterpriseLibrary.Data.dll
    • Microsoft.Practices.EnterpriseLibrary.Common.dll
    • Microsoft.Practices.EnterpriseLibrary.Caching.dll
    • Microsoft.IdentityModel.dll

  3. Add a new class, SignedRequestsInputModel, to the TestSignedApiRequests project and modify it so that it is as shown below.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace TestSignedApiRequests
    {
    
        [Serializable]
        public class SignedRequestsInputModel
        {
            public int PersonId { get; set; }
        }
    }
    
    
  4. In Visual Studio, open the Program.cs file in the code editor and add the below namespaces to it.

    using TheDotNetFactory.Framework;
    using System.Net;
    using System.Security.Cryptography.X509Certificates;
    using TheDotNetFactory.Framework.SAML.Api;
    using TheDotNetFactory.Framework.SSOIdentity;
    using Jose;
  5. In the body of the Main() method, declare the below variables where
    • url is the URL to the EmpowerID Web Server in your environment
    • apiKey is the ApiKey from the TestOAuth OAuth Provider Application you created earlier
    • clientId is the ClientID from the TestOAuth OAuth Provider Application you created earlier
    • clientSecret is the ClientScrent from the TestOAuth OAuth Provider Application you created earlier
    • userName is the user requesting access token for the TestOAuth OAuth Provider Application you created earlier
    • password is the password of the user requesting access token for the TestOAuth OAuth Provider Application you created earlier

      Be sure to replace the below values with those for your environment.

      string tokenUrl = "https://sso.empoweriam.com";
      string apiKey = "1daa135a-a9de-4a1f-a31f-2e8747c7e0f2";
      string clientId = "f9cc6222-2d1c-4802-938a-c6c35aaa38f8";
      string clientSecret = "9b474344-2f36-41c1-b7ed-0fddb692edea";
      string userName = "aapprover";
      string password = "p@$$w0rd";
  6. Add the code below to retrieve the certificate created in part 2 of the walk-through. The private key of this certificate is required to sign the JSON data in the REST api request. The public key of this certificate is associated with the TestOAuth OAuth Provider Application, which the REST api request is intended.

    X509Certificate2 signing = CertificateUtility.GetCertificate(StoreName.My, StoreLocation.LocalMachine, "0D7CA16D88E58E28D543883F0F39D97BE775F0E9");
  7. Add the below code to create a request for an access token to make calls to to the api application you created earlier.

    WebApiContext webApiContext = new WebApiContext(tokenUrl, userName,password, apiKey, clientId, clientSecret);
  8. Add the following code fragment to complete the code in the body of the Main() method.

    using (WebClient webClient = webApiContext.CreateWebCreate())
    {
    	SignedRequestsInputModel input = new SignedRequestsInputModel { PersonId = 1 };
    	string json = WebApi.ToJson<SignedRequestsInputModel>(input);
    	string data = JWS.Sign(json, signing);
    	byte[] str = System.Text.Encoding.UTF8.GetBytes(data);
    	string actionUrl = "https://sso.empoweriam.com/api/services/v1/SignedRequests/GetUserJWS";
    	byte[] results = webClient.UploadData(actionUrl, "POST", str);
    	string output = System.Text.Encoding.UTF8.GetString(results);
    	Console.WriteLine(output);
    }

    Notice that the method, JWS.Sign(), is called to sign the json data with the X509 certificate prior to performing the HTTP-POST request to the REST endpoint.

  9. Compile and run the TestSignedApiRequests console application – the output should state “User1”;

Adding code to encrypt the request in Workflow Studio

  1. In Workflow Studio, open the Class Library item, TestJWSApi, created earlier. From the Code Tree tab, use the context menu to add a New WebApi Implementation, EncryptRequests.

    The Code Tree should appear as shown below.



  2. From the Code Tree, double-click EncryptRequestsController.cs to open the file in the C# code editor.
  3. Modify the EncryptRequestsController class so that it appears as shown below.

    public class EncryptRequestsController : ApiControllerBase
    {
         private EncryptRequests _implInstance;
         public EncryptRequestsController()
         {
             _implInstance = new EncryptRequests();
         }
    
         [JsonWebEncryption(JweAlgorithm.A256KW, JweEncryption.A128CBC_HS256)]
         [HttpPost]
         public IHttpActionResult GetUserJWE(EncryptRequestsInputModel model)
         {
            var results = _implInstance.GetUser(model);
            return this.Json((object)results);
         }
           
    	public override byte[] GetJWEDecryptionKey(System.Web.Http.Controllers. HttpActionContext actionContext)
    	{
        	return new byte[32]
    		{ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
    			0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20
    		};
         }
    }

    Please note that the encryption algorithm and the type of encryption specified in the JsonWebEncryption attribute is determined by the specific encryption technique of interest to you. The above code assumes a Shared Secret Key specified by the GetJWEDecryptionKey() method. It is recommended that you follow the JOSE/JWT algorithm selection guide to determine which encryption algorithm is appropriate for your specific scenario - https://connect2id.com/products/nimbus-jose-jwt/algorithm-selection-guide

  4. Compile and Re-publish the TestJWSApi Class Library item.
  5. Recycle IIS and the EmpowerID Web Role Service as necessary to update the Web api.

Creating a client application to consume the encrypted API request

  1. Open Visual Studio 2013 or above, and create a new Console Application project, TestEncryptApiRequests.
  2. Locate the following assemblies in the EmpowerID programs folder and add them to the project as references.
    • TheDotNetFactory.Framework.SAML.dll
    • Newtonsoft.Json.dll
    • Microsoft.Practices.EnterpriseLibrary.Data.dll
    • Microsoft.Practices.EnterpriseLibrary.Common.dll
    • Microsoft.Practices.EnterpriseLibrary.Caching.dll
    • Microsoft.IdentityModel.dll

  3. Add a new class, EncryptRequestsInputModel.cs, to the TestEncryptApiRequests project and modify it so that it matches that below.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace TestEncryptApiRequests
    {
    
        [Serializable]
        public class EncryptRequestsInputModel
        {
            public int PersonId { get; set; }
        }
    }
  4. Open the Program.cs file in the code editor and add the below code to it.

    using TheDotNetFactory.Framework;
    using System.Net;
    using System.Security.Cryptography.X509Certificates;
    using TheDotNetFactory.Framework.SAML.Api;
    using TheDotNetFactory.Framework.SSOIdentity;
    using Jose;
  5. In the body of the Main() method, declare the below variables where
    • url is the URL to the EmpowerID Web Server in your environment
    • apiKey is the ApiKey from the TestOAuth OAuth Provider Application you created earlier
    • clientId is the ClientID from the TestOAuth OAuth Provider Application you created earlier
    • clientSecret is the ClientScrent from the TestOAuth OAuth Provider Application you created earlier
    • userName is the user requesting access token for the TestOAuth OAuth Provider Application you created earlier
    • password is the password of the user requesting access token for the TestOAuth OAuth Provider Application you created earlier

      Be sure to replace the below values with those for your environment.

      string tokenUrl = "https://sso.empoweriam.com";
      string apiKey = "1daa135a-a9de-4a1f-a31f-2e8747c7e0f2";
      string clientId = "f9cc6222-2d1c-4802-938a-c6c35aaa38f8";
      string clientSecret = "9b474344-2f36-41c1-b7ed-0fddb692edea";
      string userName = "aapprover";
      string password = "p@$$w0rd";
  6. Add the code below to request for an access token for making calls to the api application created earlier.

    WebApiContext webApiContext = new WebApiContext(tokenUrl, userName,password, apiKey, clientId, clientSecret);
  7. Add the below cocde to create the JSON input data to encrypt.

    EncryptRequestsInputModel input = new EncryptRequestsInputModel { PersonId = 1 };
    string json = WebApi.ToJson<EncryptRequestsInputModel>(input);
  8. Add the below code fragment to complete the code in the body of the Main() method.

    using (WebClient webClient = webApiContext.CreateWebCreate())
    {
    	byte[] encryptionKey = new byte[32]
    	{ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
    	0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
    	0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20
    	};
    
    	//Encrypt the JSON data with the key specified by encryptionKey
    	string data = JWT.Encode(json, encryptionKey, JweAlgorithm.A256KW, JweEncryption.A128CBC_HS256);
    
    	byte[] str = System.Text.Encoding.UTF8.GetBytes(data);
    	string actionUrl = "https://sso.empoweriam.com/api/services/v1/EncryptRequests/GetUserJWE";
    
    	//Call the GetUserJWE endpoint.
    	byte[] results = webClient.UploadData(actionUrl, "POST", str);
    
    	//Write the output
    	string output = System.Text.Encoding.UTF8.GetString(results);
    	Console.WriteLine(output);
    }

    Notice that the method, JWT.Encode(), is called to encrypt the json data with a shared secret prior to performing the HTTP-POST request to the REST endpoint.

  9. Add the code fragment below to complete the code in the body of the Main()
  10. Compile and run the TestEncryptApiRequests console application. The output should state “User1”;


On this page