Skip to content

Instantly share code, notes, and snippets.

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

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