public async Task <UserInformation> GetUserInformation( string accessToken, CancellationToken cancellationToken = default) { _logger.LogInformation("Getting user information"); return(await _cache.GetOrCreateAsync(new UserInfoKey(accessToken), cacheEntry => { cacheEntry.AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(15); return Execute(); })); async Task <UserInformation> Execute() { _logger.LogInformation("Fetching fresh user info..."); GitHubAuthenticationOptions options = _options.CurrentValue; IGitHubClient client = _gitHubClientFactory.CreateGitHubClient(accessToken); User user = await client.User.Current(); _logger.LogInformation("Successfully fetched user data"); ImmutableArray <Claim> .Builder claims = ImmutableArray.CreateBuilder <Claim>(); void AddClaim(string type, string value) { if (!string.IsNullOrEmpty(value)) { claims.Add(new Claim(type, value, ClaimValueTypes.String, options.ClaimsIssuer)); } } AddClaim(ClaimTypes.NameIdentifier, user.Id.ToString()); AddClaim(ClaimTypes.Name, user.Login); AddClaim(ClaimTypes.Email, user.Email); AddClaim("urn:github:name", user.Name); AddClaim("urn:github:url", user.Url); AddClaim(AccessTokenClaim, accessToken); var userInformation = new UserInformation(claims.ToImmutable(), user); return(userInformation); } }
private async Task <T> GetResponseJsonPayloadAsync <T>( string url, string accessToken, GitHubAuthenticationOptions options, Func <HttpResponseMessage, Task <T> > parseResponse, CancellationToken cancellationToken) { using (var request = new HttpRequestMessage(HttpMethod.Get, url) { Headers = { Accept = { new MediaTypeWithQualityHeaderValue("application/json") }, Authorization = new AuthenticationHeaderValue("Bearer", accessToken) } }) { using (HttpResponseMessage response = await options.Backchannel.SendAsync( request, HttpCompletionOption.ResponseHeadersRead, cancellationToken)) { if (response.IsSuccessStatusCode) { return(await parseResponse(response)); } string body = await response.Content.ReadAsStringAsync(); if (body.Length > 1024) { body = body.Substring(0, 1024); } _logger.LogError( "An error occurred while retrieving the user profile: the remote server returned a {Status} response with the following payload: {Headers} {Body}.", response.StatusCode, response.Headers.ToString(), body); throw new HttpRequestException("An error occurred while retrieving the user org membership."); } } }
public async Task <IEnumerable <Claim> > GetMembershipClaims( string accessToken, CancellationToken cancellationToken = default) { _logger.LogInformation("Getting user membership information..."); return(await _cache.GetOrCreateAsync(new GroupInfoKey(accessToken), cacheEntry => { cacheEntry.AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(15); return Execute(); })); async Task <ImmutableArray <Claim> > Execute() { _logger.LogInformation("Fetching fresh membership info..."); GitHubAuthenticationOptions options = _options.CurrentValue; ImmutableArray <Claim> .Builder claims = ImmutableArray.CreateBuilder <Claim>(); void AddClaim(string type, string value) { if (!string.IsNullOrEmpty(value)) { claims.Add(new Claim(type, value, ClaimValueTypes.String, options.ClaimsIssuer)); } } { JArray orgPayload = await GetResponseJsonPayloadAsync("https://api.github.com/user/orgs", accessToken, options, async r => JArray.Parse(await r.Content.ReadAsStringAsync()), cancellationToken); _logger.LogInformation("Fetched {orgCount} orgs", orgPayload.Count); foreach (JToken org in orgPayload) { string orgLogin = org.Value <string>("login")?.ToLowerInvariant(); AddClaim(ClaimTypes.Role, "github:org:" + orgLogin); AddClaim("urn:github:org", orgLogin); } } { JArray teamPayload = await GetResponseJsonPayloadAsync("https://api.github.com/user/teams", accessToken, options, async r => JArray.Parse(await r.Content.ReadAsStringAsync()), cancellationToken); _logger.LogInformation("Fetched {teamCount} teams", teamPayload.Count); foreach (JToken team in teamPayload) { string teamName = team.Value <string>("name")?.ToLowerInvariant(); string orgName = team["organization"]?.Value <string>("login")?.ToLowerInvariant(); string fullName = orgName + "/" + teamName; AddClaim(ClaimTypes.Role, "github:team:" + fullName); AddClaim("urn:github:team", fullName); } } return(claims.ToImmutable()); } }