protected override async Task <bool> GetHtmlAsync(IOwinEnvironment context, IClient client, CancellationToken cancellationToken) { var queryString = QueryStringParser.Parse(context.Request.QueryString, _logger); var stateToken = queryString.GetString("state"); var parsedStateToken = new StateTokenParser(client, _configuration.Client.ApiKey, stateToken, _logger); if (!parsedStateToken.Valid) { _logger.Warn("State token was invalid", nameof(GithubCallbackRoute)); return(await HttpResponse.Redirect(context, SocialExecutor.CreateErrorUri(_configuration.Web.Login, stateToken: null))); } var code = queryString.GetString("code"); if (string.IsNullOrEmpty(code)) { _logger.Warn("Social code was empty", nameof(GithubCallbackRoute)); return(await HttpResponse.Redirect(context, SocialExecutor.CreateErrorUri(_configuration.Web.Login, stateToken))); } var accessToken = await ExchangeCodeAsync(code, cancellationToken); if (string.IsNullOrEmpty(accessToken)) { _logger.Warn("Exchanged access token was null", source: nameof(GithubCallbackRoute)); return(await HttpResponse.Redirect(context, SocialExecutor.CreateErrorUri(_configuration.Web.Login, stateToken))); } var application = await client.GetApplicationAsync(_configuration.Application.Href, cancellationToken); var socialExecutor = new SocialExecutor(client, _configuration, _handlers, _logger); try { var providerRequest = client.Providers() .Github() .Account() .SetAccessToken(accessToken) .Build(); var loginResult = await socialExecutor.LoginWithProviderRequestAsync(context, providerRequest, cancellationToken); await socialExecutor.HandleLoginResultAsync( context, application, loginResult, cancellationToken); return(await socialExecutor.HandleRedirectAsync(client, context, loginResult, parsedStateToken.Path, cancellationToken)); } catch (Exception ex) { _logger.Warn($"Got '{ex.Message}' during social login request", source: nameof(GithubCallbackRoute)); return(await HttpResponse.Redirect(context, SocialExecutor.CreateErrorUri(_configuration.Web.Login, stateToken))); } }
private async Task <bool> HandleSocialLogin(IOwinEnvironment context, IClient client, LoginPostModel model, CancellationToken cancellationToken) { if (string.IsNullOrEmpty(model.ProviderData.ProviderId)) { return(await Error.Create(context, new BadRequest("No provider specified"), cancellationToken)); } var application = await client.GetApplicationAsync(_configuration.Application.Href, cancellationToken); var socialExecutor = new SocialExecutor(client, _configuration, _handlers, _logger); try { IProviderAccountRequest providerRequest; switch (model.ProviderData.ProviderId) { case "facebook": { providerRequest = client.Providers() .Facebook() .Account() .SetAccessToken(model.ProviderData.AccessToken) .Build(); break; } case "google": { providerRequest = client.Providers() .Google() .Account() .SetCode(model.ProviderData.Code) .Build(); break; } case "github": { providerRequest = client.Providers() .Github() .Account() .SetAccessToken(model.ProviderData.AccessToken) .Build(); break; } case "linkedin": { providerRequest = client.Providers() .LinkedIn() .Account() .SetAccessToken(model.ProviderData.AccessToken) .Build(); break; } default: providerRequest = null; break; } if (providerRequest == null) { return(await Error.Create(context, new BadRequest($"Unknown provider '{model.ProviderData.ProviderId}'"), cancellationToken)); } var loginResult = await socialExecutor.LoginWithProviderRequestAsync(context, providerRequest, cancellationToken); await socialExecutor.HandleLoginResultAsync( context, application, loginResult, cancellationToken); var sanitizer = new AccountResponseSanitizer(); var responseModel = new { account = sanitizer.Sanitize(loginResult.Account) }; return(await JsonResponse.Ok(context, responseModel)); } catch (ResourceException rex) { // TODO improve error logging (include request id, etc) _logger.Error(rex.DeveloperMessage, source: nameof(HandleSocialLogin)); return(await Error.Create(context, new BadRequest("An error occurred while processing the login"), cancellationToken)); } catch (Exception ex) { _logger.Error(ex, source: nameof(HandleSocialLogin)); return(await Error.Create(context, new BadRequest("An error occurred while processing the login"), cancellationToken)); } }