Skip to content

Instantly share code, notes, and snippets.

@joerodgers
Created March 17, 2026 19:39
Show Gist options
  • Select an option

  • Save joerodgers/7d5f87d5e4f53b032ce4e28fc9641adb to your computer and use it in GitHub Desktop.

Select an option

Save joerodgers/7d5f87d5e4f53b032ce4e28fc9641adb to your computer and use it in GitHub Desktop.
Sample Power Platform custom connector script to reformat an access Entra token to support token signature validation.
using Newtonsoft.Json;
using System.Net;
using System.Security.Cryptography;
using System.Text;
public class Script : ScriptBase
{
public override async Task<HttpResponseMessage> ExecuteAsync()
{
// Check if the operation ID matches what is specified in the OpenAPI definition of the connector
if (string.Equals(this.Context.OperationId, "ReformatAccessForSignatureValidation", StringComparison.OrdinalIgnoreCase))
{
return await HandleReformatAccessForSignatureValidationOperation().ConfigureAwait(false);
}
// Handle an invalid operation ID
HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.BadRequest);
response.Content = CreateJsonContent($"Unknown operation ID '{this.Context.OperationId}'");
return response;
}
private async Task<HttpResponseMessage> HandleReformatAccessForSignatureValidationOperation()
{
try
{
var body = JsonConvert.DeserializeObject<IncomingRequestBody>(await Context.Request.Content.ReadAsStringAsync());
if (body == null || string.IsNullOrEmpty(body.AccessToken))
{
return new HttpResponseMessage(HttpStatusCode.BadRequest) { Content = CreateJsonContent(JsonConvert.SerializeObject(new { message = "error parsing body" })) };
}
var jwtSecurityTokenHandler = new JwtSecurityTokenHandler();
var jwtSecurityToken = jwtSecurityTokenHandler.ReadJwtToken(body.AccessToken);
jwtSecurityToken.Header.nonce = ComputeSHA265Hash(jwtSecurityToken.Header.nonce);
return new HttpResponseMessage(HttpStatusCode.OK) { Content = CreateJsonContent(JsonConvert.SerializeObject(new { accessToken = jwtSecurityTokenHandler.WriteJwtToken(jwtSecurityToken) })) };
}
catch (System.Exception)
{
return new HttpResponseMessage(HttpStatusCode.BadRequest) { Content = CreateJsonContent(JsonConvert.SerializeObject(new { message = "Error parsing body" })) };
}
}
private string ComputeSHA265Hash(string input)
{
using var sha256 = SHA256.Create();
byte[] bytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(input));
return Base64UrlEncoder.Encode(bytes);
}
public class IncomingRequestBody
{
[Newtonsoft.Json.JsonProperty(PropertyName = "accessToken")]
public string AccessToken { get; set; } = string.Empty;
}
public class JwtSecurityTokenHandler
{
public JwtSecurityToken ReadJwtToken(string token)
{
return new JwtSecurityToken(token);
}
public string WriteJwtToken(JwtSecurityToken token)
{
return string.Format("{0}.{1}.{2}", token.EncodedHeader, token.EncodedPayload, token.RawSignature);
}
}
public class JwtSecurityToken
{
private string accessToken = string.Empty;
public JwtTokenHeader Header { get; set; }
public string EncodedHeader
{
get
{
return Base64UrlEncoder.Encode(JsonConvert.SerializeObject(Header, Newtonsoft.Json.Formatting.None));
}
}
public string EncodedPayload { get; private set; }
public string RawSignature { get; private set; }
public JwtSecurityToken(string jwtEncodedString)
{
accessToken = jwtEncodedString;
var parts = accessToken.Split('.');
if (parts.Length != 3)
{
throw new ArgumentException("Invalid JWT token format.");
}
Header = JsonConvert.DeserializeObject<JwtTokenHeader>(Base64UrlEncoder.Decode(parts[0]));
if( Header == null)
{
throw new ArgumentException("Invalid JWT token format.");
}
EncodedPayload = parts[1];
RawSignature = parts[2];
}
}
public class JwtTokenHeader
{
[Newtonsoft.Json.JsonProperty(PropertyName = "typ")]
public string typ { get; set; }
[Newtonsoft.Json.JsonProperty(PropertyName = "nonce")]
public string nonce { get; set; }
[Newtonsoft.Json.JsonProperty(PropertyName = "alg")]
public string alg { get; set; }
[Newtonsoft.Json.JsonProperty(PropertyName = "x5t")]
public string x5t { get; set; }
[Newtonsoft.Json.JsonProperty(PropertyName = "kid")]
public string kid { get; set; }
}
public static class Base64UrlEncoder
{
public static string Encode(byte[] bytes)
{
string base64 = Convert.ToBase64String(bytes);
return base64.Replace('+', '-').Replace('/', '_').TrimEnd('=');
}
public static string Encode(string input)
{
string base64 = Convert.ToBase64String(Encoding.UTF8.GetBytes(input));
return base64.Replace('+', '-').Replace('/', '_').TrimEnd('=');
}
public static string Decode(string input)
{
string base64 = input.Replace('-', '+').Replace('_', '/');
switch (base64.Length % 4)
{
case 2: base64 += "=="; break;
case 3: base64 += "="; break;
}
byte[] bytes = Convert.FromBase64String(base64);
return Encoding.UTF8.GetString(bytes);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment