JSON Signing and Encryption Walkthrough
This topic demonstrates how to use JSON signing and encryption in EmpowerID and is comprised of the following activities:
Creating a Web API application in Workflow Studio
Generating a signing certificate
Creating a client application to consume the API Request
Adding code to encrypt the request in Workflow Studio
Creating a client application to consume the encrypted API Request
Creating a Web API application in Workflow Studio
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.
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.
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
From the Code Tree, double-click on SignedRequestsController.cs to open the file in the C# code editor.
Modify the SignedRequestsController class so that it appears as shown in the below code.
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); } }Compile and Publish the TestJWSApi Class Library item.
Creating the Signing Certificate
Locate and run the EmpowerID Certificate Manager, CertificateManager.exe, from the EmpowerID programs folder.
Click the Generate tab, select X509 Certificate, provide a Password and an Output Folder path.
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.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.
Creating a client application to consume the API Request
Open Visual Studio 2013 or above and create a new Console Application project, TestSignedApiRequests.
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
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; } } }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;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
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";
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");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);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); }Compile and run the TestSignedApiRequests console application – the output should state “User1”;
Adding code to encrypt the request in Workflow Studio
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.From the Code Tree, double-click EncryptRequestsController.cs to open the file in the C# code editor.
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 }; } }Compile and Re-publish the TestJWSApi Class Library item.
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
Open Visual Studio 2013 or above, and create a new Console Application project, TestEncryptApiRequests.
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
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; } } }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;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
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";
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);Add the below cocde to create the JSON input data to encrypt.
EncryptRequestsInputModel input = new EncryptRequestsInputModel { PersonId = 1 }; string json = WebApi.ToJson<EncryptRequestsInputModel>(input);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); }Add the code fragment below to complete the code in the body of the Main()
Compile and run the TestEncryptApiRequests console application. The output should state “User1”;