public static async Task <bool> ValidateRequest(HttpRequestHeaders requestHeaders, string requestBody, TraceWriter log) { requestHeaders.TryGetValues("SignatureCertChainUrl", out var signatureChainUrls); var signatureChainUrl = signatureChainUrls == null ? null : signatureChainUrls.FirstOrDefault(); if (String.IsNullOrWhiteSpace(signatureChainUrl)) { return(false); } Uri certUrl; try { certUrl = new Uri(signatureChainUrl); } catch { return(false); } requestHeaders.TryGetValues("Signature", out var signatures); var signature = signatures == null ? null : signatures.FirstOrDefault(); if (String.IsNullOrWhiteSpace(signature)) { return(false); } if (String.IsNullOrWhiteSpace(requestBody)) { return(false); } var valid = await AlexaRequestSecurity.Verify(signature, certUrl, requestBody, log); if (!valid) { return(false); } return(true); }
public static async Task <HttpResponseMessage> Run( [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = null)] HttpRequestMessage req, [Table("AlexaUser")] CloudTable outputTable, TraceWriter log, CancellationToken cancellationToken) { Log = log; log.Info("HTTP trigger function processed a request."); log.Info($"Debug: {IsDebug}"); string reqBody = await req?.Content?.ReadAsStringAsync(); var isValidRequest = await AlexaRequestSecurity.ValidateRequest(req.Headers, reqBody, log); if (!isValidRequest && !IsDebug) { return(new HttpResponseMessage(HttpStatusCode.BadRequest)); } SkillRequest skillRequest = JsonConvert.DeserializeObject <SkillRequest>(reqBody); //1. look up user id in cloud table //2. if you can't find an account and memberid then look up account info and get member id string identityName = ""; AccessToken accessToken = null; try { var patToken = AlexaRequestSecurity.GetEncodedPatToken(req.Headers); if (IsDebug && patToken != null) { identityName = "Debug Mode"; accessToken = new AccessToken("basic", patToken); } else { // Would this need to be done more than once (if at all) we persisted the identityName? // We could let VSTS take care of this validation // Get the VSTS Principle from Oauth token ClaimsPrincipal principal = await AlexaRequestSecurity.GetVSTSPrinciple(skillRequest, log, cancellationToken); identityName = principal.Identity.Name; accessToken = new AccessToken("bearer", skillRequest.Session.User.AccessToken); } } catch (Exception exception) { return(AlexaResponse(exception.Message)); } var intentRequest = skillRequest.Request as IntentRequest; var intentName = intentRequest?.Intent?.Name; if (string.IsNullOrWhiteSpace(intentName)) { return(await VstsApiRequest(log, accessToken, "default")); } // check the intent name to determine what you should do if (intentRequest.Intent.Name.Equals("Account")) { return(AlexaResponse($"You are using {identityName}'s account")); } if (intentRequest.Intent.Name.Equals("pullRequestStatus")) { return(await VstsApiRequest(log, accessToken, "pullRequestStatus")); } if (intentRequest.Intent.Name.Equals("queueBuilds")) { return(await VstsApiRequest(log, accessToken, "queueBuilds")); } return(AlexaResponse($"I don't know how to do that yet")); }