A cloud-based identity and access management service for securing user authentication and resource access
Hello Bas C,
Thank you for sharing the detailed update and for your continued patience.
The issue you're seeing is likely due to a recent change in how Microsoft Graph validates symmetric keys (kty: "oct") when creating a trustFrameworkKeySet.
The k value now needs to be in Base64URL format, as described in the JWK specification (RFC 7518, Section 6.4.1). This encoding only allows letters, numbers, hyphens, and underscores. Characters like periods, tildes, or others outside this set are no longer accepted.
Although this behavior isn't clearly reflected in the error message, it aligns with the expected format outlined in the trustFrameworkKeySet and trustFrameworkKey documentation.
When using the Azure Portal, the system automatically encodes the key behind the scenes, which is why a value like "abc.def" seems to work. However, when using Graph Explorer or the SDK, the key needs to be correctly encoded before it is submitted.
Here’s a screenshot of the error returned by Graph Explorer when the k value is not encoded:

To fix this, encode the key before submitting the request. In my case, I used client credentials flow for authentication for which below permission must be added with consent:

Here’s a complete working example using the Microsoft Graph .NET SDK:
using System.Text;
using Azure.Identity;
using Microsoft.Graph.Beta;
using Microsoft.Graph.Beta.Models;
namespace GraphKeySetDemo
{
class Program
{
static async Task Main(string[] args)
{
var tenantId = "tenantId";
var clientId = "appId";
var clientSecret = "secret";
var scopes = new[] { "https://graph.microsoft.com/.default" };
var credential = new ClientSecretCredential(tenantId, clientId, clientSecret);
var graphClient = new GraphServiceClient(credential, scopes);
string rawKey = "abc.def";
string encodedKey = Base64UrlEncode(rawKey);
var key = new TrustFrameworkKey
{
K = encodedKey,
Kty = "oct",
Use = "sig"
};
var keySet = new TrustFrameworkKeySet
{
Id = "TEST123",
Keys = new List<TrustFrameworkKey> { key }
};
try
{
var result = await graphClient.TrustFramework.KeySets.PostAsync(keySet);
Console.WriteLine("KeySet created successfully with ID: " + result?.Id);
}
catch (Exception ex)
{
Console.WriteLine("Failed to create KeySet: " + ex.Message);
}
}
static string Base64UrlEncode(string input)
{
var bytes = Encoding.UTF8.GetBytes(input);
var base64 = Convert.ToBase64String(bytes);
return base64.Replace("+", "-").Replace("/", "_").TrimEnd('=');
}
}
}
Below is a successful response after the key is encoded correctly:

To confirm that, I checked the same in Portal where policy key created successfully as below:

Using percent-encoding (like %2E for .) will not work, as the Graph API specifically expects Base64URL format.
Hope this helps!
If this answer was helpful, please click "Accept the answer" and mark Yes, as this can help other community members.
If you have any other questions or are still facing issues, feel free to post in the comments and I’ll be happy to assist further.