Skip to content

Instantly share code, notes, and snippets.

Created August 27, 2020 22:45
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
What would you like to do?
using Dalion.HttpMessageSigning.Signing;
using Dalion.HttpMessageSigning;
using Microsoft.IdentityModel.Tokens;
using Newtonsoft.Json;
using System;
using System.Net.Http.Headers;
using System.Net.Http;
using System.Security.Cryptography.X509Certificates;
using System.Security.Cryptography;
using System.Threading.Tasks;
using System.Collections.Generic;
using System.Net;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
namespace Services
internal class MagdaAccessToken
internal MagdaAccessToken()
this.TokenDate = DateTime.Now;
public string AccessToken { get; set; }
public DateTime ExpireDate
return this.TokenDate.AddSeconds(this.ExpiresIn);
public DateTime TokenDate { get; private set; }
public int ExpiresIn { get; set; }
public string TokenType { get; set; }
public string Scope { get; set; }
public class MagdaTokenBasedServicesExample
private readonly string _keyId = "rsa-key-1";
private readonly string _clientId = "1234"; //TODO: Provide your client id
private readonly string _authUrl = "";
private readonly string _messagesEndpointUrl = "";
private MagdaAccessToken _accessToken;
private X509Certificate2 _clientCertificate;
private IRequestSignerFactory _requestSignerFactory;
private HttpClient _httpClient;
private JwtSecurityTokenHandler _tokenHandler;
public MagdaTokenBasedServicesExample(IRequestSignerFactory requestSignerFactory)
this._requestSignerFactory = requestSignerFactory;
this._clientCertificate = null; // TODO: Load your VO-DCB client certificate (pfx)
var httpClientHandler = new HttpClientHandler();
this._httpClient = new HttpClient(httpClientHandler);
this._tokenHandler = new JwtSecurityTokenHandler();
public async Task<HttpResponseMessage> SendMessage()
if (this._accessToken == null || (this._accessToken != null && this._accessToken.ExpireDate <= DateTime.Now.AddMinutes(1)))
this._accessToken = await this.GetAccessToken();
var request = new HttpRequestMessage
Method = HttpMethod.Post,
RequestUri = new Uri(this._messagesEndpointUrl)
await SignHttpRequestMessage(request);
// Add additional payload properties here
// Like MessageToSend
return await this._httpClient.SendAsync(request);
private async Task SignHttpRequestMessage(HttpRequestMessage request)
request.Headers.Add("signature-public-key", WrapCertificateInJWK(this._clientCertificate, _keyId));
request.Headers.Date = DateTimeOffset.UtcNow;
SigningSettings settings = new SigningSettings
SignatureAlgorithm = SignatureAlgorithm.CreateForSigning(this._clientCertificate, HashAlgorithmName.SHA512),
DigestHashAlgorithm = HashAlgorithmName.SHA512,
EnableNonce = false,
Headers = new[]
new HeaderName("signature-public-key")
UseDeprecatedAlgorithmParameter = true
var requestSigner = this._requestSignerFactory.Create(_keyId, settings);
await requestSigner.Sign(request);
request.Headers.Add("Signature", request.Headers.Authorization.Parameter);
request.Headers.Add("x-correlation-id", Guid.NewGuid().ToString());
request.Headers.Add("Accept", "application/json");
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", this._accessToken.AccessToken);
private string WrapCertificateInJWK(X509Certificate2 certificate, string keyName)
var x509SigningKey = new X509SigningCredentials(certificate);
var x509Key = new X509SecurityKey(certificate);
var cert64 = Convert.ToBase64String(x509Key.Certificate.RawData);
var pubKey = x509Key.PublicKey as RSA;
var parameters = pubKey.ExportParameters(false);
var exponent = Convert.ToBase64String(parameters.Exponent);
var modulus = Convert.ToBase64String(parameters.Modulus);
var webKey = new JsonWebKey
Kty = "RSA",
Use = "sig",
Kid = keyName,
X5t = x509Key.Certificate.Thumbprint,
E = exponent,
N = modulus,
Alg = x509SigningKey.Algorithm
var simplifiedWebKey = new { kty = webKey.Kty, kid = webKey.Kid, n = webKey.N, e = webKey.E, x5c = webKey.X5c };
return JsonConvert.SerializeObject(simplifiedWebKey);
private async Task<MagdaAccessToken> GetAccessToken()
var request = new HttpRequestMessage
Method = HttpMethod.Post,
RequestUri = new Uri(this._authUrl)
request.Headers.Add("Accept", "application/json");
request.Headers.Add("Accept-Encoding", "gzip, deflate, br");
List<string> scopes = new List<string>() {
Dictionary<string, string> postParams = new Dictionary<string, string>();
postParams.Add("grant_type", "client_credentials");
postParams.Add("scope", string.Join(" ", scopes));
postParams.Add("client_assertion_type", "urn:ietf:params:oauth:client-assertion-type:jwt-bearer");
postParams.Add("client_assertion", this.GetAuthJwtToken(string.Join(" ", scopes)));
request.Content = new FormUrlEncodedContent(postParams);
var response = await this._httpClient.SendAsync(request);
var responseContent = await response.Content.ReadAsStringAsync();
switch (response.StatusCode)
case HttpStatusCode.OK:
return JsonConvert.DeserializeObject<MagdaAccessToken>(responseContent);
throw new Exception($"HTTP call GetToken failed with status code {response.StatusCode} and message {responseContent}");
private string GetAuthJwtToken(string scopes)
X509SecurityKey privateKey = new X509SecurityKey(this._clientCertificate);
ClaimsIdentity claimsIdentity = new ClaimsIdentity();
claimsIdentity.AddClaim(new Claim("sub", this._clientId));
claimsIdentity.AddClaim(new Claim("scope", scopes));
claimsIdentity.AddClaim(new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()));
return this._tokenHandler.CreateEncodedJwt(this._clientId, this._authUrl, claimsIdentity, null, DateTime.UtcNow.AddMinutes(10), DateTime.UtcNow, new SigningCredentials(privateKey, SecurityAlgorithms.RsaSha256Signature));
Copy link

brz commented May 6, 2021

Dank voor dit stukje code! Ik zat even vast bij de message signing.

Copy link

fdervishi90 commented Jun 8, 2021

Can you please share how you instantiate the MagdaTokenBasedServicesExample class. More specifically how do you build the IRequestSignerFactory dependency on the contructor ?

Copy link

brz commented Jun 8, 2021

Can you please share how you instantiate the MagdaTokenBasedServicesExample class. More specifically how do you build the IRequestSignerFactory dependency on the contructor ?

Currently the only way of instantiating an IRequestSignerFactory object is by using dependency injection. I opened an issue on the GitHub page of Dalion.HttpMessageSigning to improve this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment