based on https://learn.microsoft.com/en-us/azure/azure-signalr/signalr-concept-client-negotiation#self-exposing-negotiate-endpoint I managed to inject custom user identity claim from our custom incoming JWT into SignaR access token:
import { sign, decode } from "jws";
const inputSignalR = input.generic({
type: "signalRConnectionInfo",
name: "connectionInfo",
hubName: "my-hub",
});
async function negotiate(request: HttpRequest, context: InvocationContext) {
const signalRDefaultConnectionInfo = context.extraInputs.get(inputSignalR);
const signalRConnectionString = process.env.AzureSignalRConnectionString;
const signalRAccessKey = /AccessKey=(.*?);/.exec(signalRConnectionString)[1];
const userId = extractUserId(request); // extract user identity claim from your JWT
const originalDecodedToken = decode(signalRDefaultConnectionInfo.accessToken);
const customizedToken = sign({
header: originalDecodedToken.header,
payload: {
...originalDecodedToken.payload,
"asrs.s.uid": userId, // claim used by SignalR Service to hold user identity
},
secret: signalRAccessKey
});
return { url: signalRDefaultConnectionInfo.url, accessToken: customizedToken };
}
app.post("negotiate", {
authLevel: "anonymous",
handler: negotiate,
route: "negotiate",
extraInputs: [inputSignalR],
});