public bool TryGetInvocationContext(HttpRequestMessage request, out InvocationContext context) { context = new InvocationContext(); // Required properties context.ConnectionId = request.Headers.GetValues(Constants.AsrsConnectionIdHeader).FirstOrDefault(); if (string.IsNullOrEmpty(context.ConnectionId)) { return(false); } context.Hub = request.Headers.GetValues(Constants.AsrsHubNameHeader).FirstOrDefault(); context.Category = request.Headers.GetValues(Constants.AsrsCategory).FirstOrDefault(); context.Event = request.Headers.GetValues(Constants.AsrsEvent).FirstOrDefault(); // Optional properties if (request.Headers.TryGetValues(Constants.AsrsUserId, out var values)) { context.UserId = values.FirstOrDefault(); } if (request.Headers.TryGetValues(Constants.AsrsClientQueryString, out values)) { context.Query = SignalRTriggerUtils.GetQueryDictionary(values.FirstOrDefault()); } if (request.Headers.TryGetValues(Constants.AsrsUserClaims, out values)) { context.Claims = SignalRTriggerUtils.GetClaimDictionary(values.FirstOrDefault()); } context.Headers = SignalRTriggerUtils.GetHeaderDictionary(request.Headers); return(true); }
// The algorithm is defined in spec: Hex_encoded(HMAC_SHA256(access-key, connection-id)) public bool ValidateSignature(HttpRequestMessage request, string accessToken) { if (!_validateSignature) { return(true); } if (!string.IsNullOrEmpty(accessToken) && request.Headers.TryGetValues(Constants.AsrsSignature, out var values)) { var signatures = SignalRTriggerUtils.GetSignatureList(values.FirstOrDefault()); if (signatures == null) { return(false); } using (var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(accessToken))) { var hashBytes = hmac.ComputeHash(Encoding.UTF8.GetBytes(request.Headers.GetValues(Constants.AsrsConnectionIdHeader).First())); var hash = "sha256=" + BitConverter.ToString(hashBytes).Replace("-", ""); return(signatures.Contains(hash, StringComparer.OrdinalIgnoreCase)); } } return(false); }
internal SignalRTriggerAttribute GetParameterResolvedAttribute(SignalRTriggerAttribute attribute, ParameterInfo parameterInfo) { //TODO: AutoResolve more properties in attribute var hubName = attribute.HubName; var category = attribute.Category; var @event = attribute.Event; var parameterNames = attribute.ParameterNames ?? Array.Empty <string>(); var connectionStringSetting = attribute.ConnectionStringSetting; // We have two models for C#, one is function based model which also work in multiple language // Another one is class based model, which is highly close to SignalR itself but must keep some conventions. var method = (MethodInfo)parameterInfo.Member; var declaredType = method.DeclaringType; string[] parameterNamesFromAttribute; if (declaredType != null && IsServerlessHub(declaredType)) { // Class based model if (!string.IsNullOrEmpty(hubName) || !string.IsNullOrEmpty(category) || !string.IsNullOrEmpty(@event) || parameterNames.Length != 0) { throw new ArgumentException($"{nameof(SignalRTriggerAttribute)} must use parameterless constructor in class based model."); } parameterNamesFromAttribute = method.GetParameters().Where(IsLegalClassBasedParameter).Select(p => p.Name).ToArray(); hubName = declaredType.Name; category = GetCategoryFromMethodName(method.Name); @event = GetEventFromMethodName(method.Name, category); connectionStringSetting = SignalRTriggerUtils.GetConnectionNameFromAttribute(declaredType) ?? attribute.ConnectionStringSetting; } else { parameterNamesFromAttribute = method.GetParameters(). Where(p => p.GetCustomAttribute <SignalRParameterAttribute>(false) != null). Select(p => p.Name).ToArray(); if (parameterNamesFromAttribute.Length != 0 && parameterNames.Length != 0) { throw new InvalidOperationException( $"{nameof(SignalRTriggerAttribute)}.{nameof(SignalRTriggerAttribute.ParameterNames)} and {nameof(SignalRParameterAttribute)} can not be set in the same Function."); } // If we aren't using the class-based model, make sure we resolve binding expressions for attribute properties here. hubName = _nameResolver.ResolveWholeString(hubName); category = _nameResolver.ResolveWholeString(category); @event = _nameResolver.ResolveWholeString(@event); } parameterNames = parameterNamesFromAttribute.Length != 0 ? parameterNamesFromAttribute : parameterNames; return(new SignalRTriggerAttribute(hubName, category, @event, parameterNames) { ConnectionStringSetting = connectionStringSetting }); }
public Task <IListener> CreateListenerAsync(ListenerFactoryContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } // It's not a real listener, and it doesn't need a start or close. _dispatcher.Map((_attribute.HubName, _attribute.Category, _attribute.Event), new ExecutionContext { Executor = context.Executor, AccessKey = SignalRTriggerUtils.GetAccessKey(_attribute.ConnectionStringSetting) }); return(Task.FromResult <IListener>(new NullListener())); }
// The algorithm is defined in spec: Hex_encoded(HMAC_SHA256(access-key, connection-id)) public bool ValidateSignature(HttpRequestMessage request, AccessKey[] accessKeys) { if (!_validateSignature) { return(true); } if (accessKeys is null) { throw new ArgumentNullException(nameof(accessKeys)); } foreach (var accessKey in accessKeys) { // Skip validation for aad access key. if (accessKey is AadAccessKey) { return(true); } var accessToken = accessKey.Value; if (!string.IsNullOrEmpty(accessToken) && request.Headers.TryGetValues(Constants.AsrsSignature, out var values)) { var signatures = SignalRTriggerUtils.GetSignatureList(values.FirstOrDefault()); if (signatures == null) { continue; } using (var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(accessToken))) { var hashBytes = hmac.ComputeHash(Encoding.UTF8.GetBytes(request.Headers.GetValues(Constants.AsrsConnectionIdHeader).First())); var hash = "sha256=" + BitConverter.ToString(hashBytes).Replace("-", ""); if (signatures.Contains(hash, StringComparer.OrdinalIgnoreCase)) { return(true); } else { continue; } } } } return(false); }