private Dictionary <string, string> GetHeaders(BasecampAuthorizationToken auth)
 {
     return(new Dictionary <string, string>
     {
         { "Authorization", $"Bearer {auth.AccessToken}" },
         { "User-Agent", $"Fr8.co ({_contactEmail})" }
     });
 }
        /// <summary>
        /// Performs OAuth authentication after receiving verification code from Basecamp. Additionaly performs a check of whether use has access to Basecamp2 projects
        /// </summary>
        public async Task <AuthorizationTokenDTO> AuthenticateAsync(ExternalAuthenticationDTO externalState)
        {
            try
            {
                var query    = HttpUtility.ParseQueryString(externalState.RequestQueryString);
                var code     = query["code"];
                var state    = query["state"];
                var url      = $"{_tokenUrl}?type=web_server&client_id={_clientId}&redirect_uri={HttpUtility.UrlEncode(_redirectUrl)}&client_secret={_clientSecret}&code={code}";
                var response = await _restfulServiceClient.PostAsync <OAuthResponse>(new Uri(url)).ConfigureAwait(false);

                var basecampAuthorizationDTO = new BasecampAuthorizationToken
                {
                    AccessToken  = response.AccessToken,
                    RefreshToken = response.RefreshToken,
                };
                //Retrieving info about username and project
                var userInfo = await GetCurrentUserInfo(basecampAuthorizationDTO).ConfigureAwait(false);

                if (userInfo.Accounts.TrueForAll(x => x.Product != Basecamp2Product))
                {
                    Logger.GetLogger().Error($"Authorized user doesn't have access to Basecamp2. Fr8 User Id - {externalState.Fr8UserId}");
                    return(new AuthorizationTokenDTO {
                        Error = "We couldn't authorize you as your account doesn't have access to Basecamp2 product"
                    });
                }
                basecampAuthorizationDTO.ExpiresAt = userInfo.ExpiresAt;
                return(new AuthorizationTokenDTO
                {
                    ExternalAccountId = userInfo.Identity.Id.ToString(),
                    ExternalAccountName = userInfo.Identity.DisplayName,
                    ExternalStateToken = state,
                    ExpiresAt = basecampAuthorizationDTO.ExpiresAt,
                    Token = JsonConvert.SerializeObject(basecampAuthorizationDTO)
                });
            }
            catch (Exception ex)
            {
                Logger.GetLogger().Error($"Failed to authorize with Basecamp. Fr8 User Id - {externalState.Fr8UserId}, Details - {ex}");
                return(new AuthorizationTokenDTO {
                    Error = "An error occured while trying to authorize you. Please try again later"
                });
            }
        }
 private async Task <TResponse> ApiGetAsync <TResponse>(string apiUrl, BasecampAuthorizationToken auth)
 {
     return(await _restfulServiceClient.GetAsync <TResponse>(new Uri(apiUrl), headers : GetHeaders(auth)).ConfigureAwait(false));
 }
 private async Task <Authorization> GetCurrentUserInfo(BasecampAuthorizationToken auth)
 {
     return(await ApiGetAsync <Authorization>(_authorizationUrl, auth).ConfigureAwait(false));
 }