private async Task <AccessToken> ProcessToken(JsonOperationContext context, WebSocket webSocket) { using (var reader = await context.ReadFromWebSocket(webSocket, DebugTag, ServerStore.ServerShutdown)) { var requestContents = ExtractChallengeResponse(reader); var encryptedData = ExtractEncryptedData(requestContents); var challengeDictionary = OAuthHelper.ParseDictionary(OAuthServerHelper.DecryptAsymmetric(encryptedData)); var apiKeyName = challengeDictionary.GetOrDefault(OAuthHelper.Keys.APIKeyName); var challenge = challengeDictionary.GetOrDefault(OAuthHelper.Keys.Challenge); var response = challengeDictionary.GetOrDefault(OAuthHelper.Keys.Response); if (string.IsNullOrEmpty(apiKeyName) || string.IsNullOrEmpty(challenge) || string.IsNullOrEmpty(response)) { throw new InvalidOperationException( "Got null or empty apiKeyName/challenge/response in 'ChallengeResponse' message"); } var challengeData = OAuthHelper.ParseDictionary(OAuthServerHelper.DecryptSymmetric(challenge)); var timestampStr = challengeData.GetOrDefault(OAuthHelper.Keys.ChallengeTimestamp); if (string.IsNullOrEmpty(timestampStr)) { throw new InvalidOperationException("Got null or empty encryptedData in 'ChallengeResponse' message"); } ThrowIfTimestampNotVerified(timestampStr); string secret; var accessToken = BuildAccessTokenAndGetApiKeySecret(apiKeyName, out secret); var expectedResponse = OAuthHelper.Hash(string.Format(OAuthHelper.Keys.ResponseFormat, challenge, secret)); if (response != expectedResponse) { if (_logger.IsInfoEnabled) { _logger.Info($"Failure to authenticate api key {apiKeyName}"); } return(null); } return(accessToken); } }