async Task <IActionResult> IAdapterAuthorize.HandleCallbackAsync(DeploymentScope deploymentScope, HttpRequest request, IAuthorizationEndpoints authorizationEndpoints) { if (deploymentScope is null) { throw new ArgumentNullException(nameof(deploymentScope)); } if (request is null) { throw new ArgumentNullException(nameof(request)); } if (authorizationEndpoints is null) { throw new ArgumentNullException(nameof(authorizationEndpoints)); } var json = await request .ReadJsonAsync() .ConfigureAwait(false); var appId = json .SelectToken("installation.app_id")? .ToString(); var token = await TokenClient .GetAsync <GitHubToken>(deploymentScope) .ConfigureAwait(false); if (token?.ApplicationId?.Equals(appId, StringComparison.OrdinalIgnoreCase) ?? false) { var action = json .SelectToken("action")? .ToString(); switch (action) { case "created": token.InstallationId = json .SelectToken("installation.id")? .ToString(); break; case "deleted": token = new GitHubToken(deploymentScope); break; case "suspend": token.Suspended = true; break; case "unsuspend": token.Suspended = false; break; default: token = null; break; } if (token is not null) { _ = await TokenClient .SetAsync(token) .ConfigureAwait(false); return(new OkResult()); } } return(new NotFoundResult()); }
async Task <IActionResult> IAdapterAuthorize.HandleAuthorizeAsync(DeploymentScope deploymentScope, HttpRequest request, IAuthorizationEndpoints authorizationEndpoints) { if (deploymentScope is null) { throw new ArgumentNullException(nameof(deploymentScope)); } if (request is null) { throw new ArgumentNullException(nameof(request)); } if (authorizationEndpoints is null) { throw new ArgumentNullException(nameof(authorizationEndpoints)); } var queryParams = Url.ParseQueryParams(request.QueryString.ToString()); var queryState = queryParams.GetValueOrDefault("state"); var queryCode = queryParams.GetValueOrDefault("code"); var queryError = queryParams.GetValueOrDefault("error"); var session = await SessionClient .GetAsync <GitHubSession>(deploymentScope) .ConfigureAwait(false); session ??= await SessionClient .SetAsync(new GitHubSession(deploymentScope)) .ConfigureAwait(false); var data = string.IsNullOrWhiteSpace(deploymentScope.InputData) ? default : TeamCloudSerialize.DeserializeObject <GitHubData>(deploymentScope.InputData); var token = await TokenClient .GetAsync <GitHubToken>(deploymentScope) .ConfigureAwait(false); if (string.IsNullOrEmpty(queryError) && Guid.TryParse(queryState, out var stateId)) { if (!stateId.ToString().Equals(session.SessionId, StringComparison.OrdinalIgnoreCase)) { return(new RedirectResult(authorizationEndpoints.AuthorizationUrl.SetQueryParam("error", "Session timed out.").ToString())); } else if (string.IsNullOrWhiteSpace(queryCode)) { return(new RedirectResult(authorizationEndpoints.AuthorizationUrl.SetQueryParam("error", "Missing GitHub handshake information.").ToString())); } token ??= new GitHubToken(deploymentScope); // Using Flurl as Octokit doesn't support this API yet // https://github.com/octokit/octokit.net/issues/2138 var url = $"https://api.github.com/app-manifests/{queryCode}/conversions"; var response = await url .WithHeader("User-Agent", GitHubConstants.ProductHeader.ToString()) .PostStringAsync(string.Empty) .ConfigureAwait(false); if (!response.IsSuccessStatusCode()) { return(new RedirectResult(authorizationEndpoints.AuthorizationUrl.SetQueryParam("error", $"Failed to get application token ({response.StatusCode} - {response.ResponseMessage.ReasonPhrase}).").ToString())); } var json = await response .GetStringAsync() .ConfigureAwait(false); TeamCloudSerialize.PopulateObject(json, token); if (string.IsNullOrEmpty(token.OwnerLogin)) { token.OwnerLogin = JToken.Parse(json) .SelectToken("owner.login") .ToString(); } token = await TokenClient .SetAsync(token, true) .ConfigureAwait(false); return(new ContentResult { StatusCode = (int)HttpStatusCode.OK, ContentType = "text/html", Content = Assembly.GetExecutingAssembly().GetManifestResourceTemplate($"{GetType().FullName}_Install.html", GetFormContext()) }); } else { return(new ContentResult { StatusCode = (int)HttpStatusCode.OK, ContentType = "text/html", Content = Assembly.GetExecutingAssembly().GetManifestResourceTemplate($"{GetType().FullName}_Register.html", GetFormContext()) }); } object GetFormContext() => new { deploymentScope = deploymentScope, authorizationEndpoints = authorizationEndpoints, token = token, data = data, session = session, error = queryError ?? string.Empty, succeeded = queryParams.Contains("succeeded") }; }