コード例 #1
0
        private async Task UpdateUserAsync(ApplicationUser user,
                                           BuildAssetRegistryContext dbContext,
                                           UserManager <ApplicationUser> userManager,
                                           SignInManager <ApplicationUser> signInManager,
                                           GitHubClaimResolver gitHubClaimResolver)
        {
            using (IDbContextTransaction txn = await dbContext.Database.BeginTransactionAsync())
            {
                string token = await userManager.GetAuthenticationTokenAsync(user, GitHubScheme, "access_token");

                var newClaims = (await gitHubClaimResolver.GetUserInformationClaims(token)).Concat(
                    await gitHubClaimResolver.GetMembershipClaims(token)
                    ).Where(AccountController.ShouldAddClaimToUser);
                var currentClaims = (await userManager.GetClaimsAsync(user)).ToList();

                // remove old claims
                await userManager.RemoveClaimsAsync(user, currentClaims);

                // add new claims
                await userManager.AddClaimsAsync(user, newClaims);

                user.LastUpdated = DateTimeOffset.UtcNow;
                await dbContext.SaveChangesAsync();

                txn.Commit();
            }
        }
コード例 #2
0
ファイル: Startup.cs プロジェクト: mmitche/arcade-services
        private void AddServices(IServiceCollection services)
        {
            services.AddMvc().WithRazorPagesRoot("/Pages").AddRazorPagesOptions(o => o.Conventions.AuthorizeFolder("/", MsftAuthorizationPolicyName).AllowAnonymousToPage("/Index"));
            services.AddApplicationInsightsTelemetry(Configuration.GetSection("ApplicationInsights").Bind);
            services.AddAuthentication()
            .AddGitHubOAuth(Configuration.GetSection("GitHubAuthentication"), GitHubScheme)
            .AddScheme <UserTokenOptions, GitHubUserTokenHandler>("github-token", o => { })
            .AddCookie(IdentityConstants.ApplicationScheme,
                       o =>
            {
                o.ExpireTimeSpan     = TimeSpan.FromDays(7);
                o.SlidingExpiration  = true;
                o.Cookie.IsEssential = true;
                o.LoginPath          = "/signin";
                o.LogoutPath         = "/signout";
                o.ReturnUrlParameter = "r";
                o.Events             = new CookieAuthenticationEvents
                {
                    OnValidatePrincipal = async ctx =>
                    {
                        GitHubClaimResolver resolver =
                            ctx.HttpContext.RequestServices.GetRequiredService <GitHubClaimResolver>();
                        ClaimsIdentity identity = ctx.Principal.Identities.FirstOrDefault();
                        identity?.AddClaims(await resolver.GetMembershipClaims(resolver.GetAccessToken(ctx.Principal)));
                    }
                };
            })
            ;
            services.AddAzureTableTokenStore(o => Configuration.GetSection("AzureTableTokenStore").Bind(o));
            services.AddAuthorization(
                options =>
            {
                options.AddPolicy(
                    MsftAuthorizationPolicyName,
                    policy =>
                {
                    policy.RequireAuthenticatedUser();
                    if (!Env.IsDevelopment())
                    {
                        policy.RequireRole("github:team:dotnet/dnceng", "github:team:dotnet/bots-high");
                    }
                });
            });

            services.AddScoped <SimpleSigninMiddleware>();
            services.AddGitHubTokenProvider();
            services.AddSingleton <IInstallationLookup, InMemoryCacheInstallationLookup>();
            services.AddContextAwareAuthenticationScheme(o =>
            {
                o.SelectScheme = p => p.StartsWithSegments("/api") ? "github-token" : IdentityConstants.ApplicationScheme;
            });
            services.AddSingleton <GitHubJwtFactory>();
        }
コード例 #3
0
        protected override async Task <AuthenticateResult> HandleAuthenticateAsync()
        {
            string protectedToken = null;

            if (Request.Headers.TryGetValue("Authorization", out var authHeader) &&
                AuthenticationHeaderValue.TryParse(authHeader.ToString(), out var auth) &&
                auth.Scheme == "Bearer")
            {
                protectedToken = auth.Parameter;
            }

            if (string.IsNullOrEmpty(protectedToken) &&
                Request.Query.TryGetValue("token", out var tokenQuery))
            {
                protectedToken = tokenQuery;
            }

            if (string.IsNullOrEmpty(protectedToken))
            {
                return(AuthenticateResult.NoResult());
            }

            if (!TryDecodeToken(protectedToken, out GitHubTokenData token))
            {
                return(AuthenticateResult.Fail("Invalid token"));
            }

            if (await _revocation.IsTokenRevokedAsync(token.UserId, token.TokenId))
            {
                Logger.LogWarning("Revoked token used, user {user}, token {token}", token.UserId, token.TokenId);
                return(AuthenticateResult.Fail("Invalid token"));
            }

            (IEnumerable <Claim> userClaims, IEnumerable <Claim> groupClaims) = await Task.WhenAll(
                _resolver.GetUserInformationClaims(token.AccessToken, Context.RequestAborted),
                _resolver.GetMembershipClaims(token.AccessToken, Context.RequestAborted)
                );

            var identity  = new ClaimsIdentity(userClaims.Concat(groupClaims), Scheme.Name);
            var principal = new ClaimsPrincipal(new[] { identity });
            var ticket    = new AuthenticationTicket(principal, Scheme.Name);

            return(AuthenticateResult.Success(ticket));
        }
コード例 #4
0
        private void AddServices(IServiceCollection services)
        {
            services.AddRazorPages(o =>
            {
                o.Conventions
                .AuthorizeFolder("/", MsftAuthorizationPolicyName)
                .AllowAnonymousToPage("/Index")
                .AllowAnonymousToPage("/Status")
                .AllowAnonymousToPage("/Error");
                o.RootDirectory = "/Pages";
            });

            services.AddControllers()
            .AddGitHubWebHooks();

            services.AddApplicationInsightsTelemetry(Configuration.GetSection("ApplicationInsights").Bind);
            services.Configure <LoggerFilterOptions>(o =>
            {
                // This handler is added by 'AddApplicationInsightsTelemetry' above and hard limits
                // and reporting below "warning", which basically kills all logging
                // Remove it, we already configured the filters in Program.cs
                o.Rules.Remove(o.Rules.FirstOrDefault(r =>
                                                      r.ProviderName ==
                                                      "Microsoft.Extensions.Logging.ApplicationInsights.ApplicationInsightsLoggerProvider"));
            });

            services.AddAuthentication("contextual")
            .AddPolicyScheme("contextual", "Contextual Scheme",
                             o => { o.ForwardDefaultSelector = context =>
                                    {
                                        if (context.Request.Path.StartsWithSegments("/api"))
                                        {
                                            return("github-token");
                                        }

                                        return(IdentityConstants.ApplicationScheme);
                                    }; })
            .AddGitHubOAuth(Configuration.GetSection("GitHubAuthentication"), GitHubScheme)
            .AddScheme <UserTokenOptions, GitHubUserTokenHandler>("github-token", o => { })
            .AddCookie(IdentityConstants.ApplicationScheme,
                       o =>
            {
                o.ExpireTimeSpan     = TimeSpan.FromDays(7);
                o.SlidingExpiration  = true;
                o.Cookie.IsEssential = true;
                o.LoginPath          = "/signin";
                o.LogoutPath         = "/signout";
                o.ReturnUrlParameter = "r";
                o.Events             = new CookieAuthenticationEvents
                {
                    OnValidatePrincipal = async ctx =>
                    {
                        GitHubClaimResolver resolver =
                            ctx.HttpContext.RequestServices.GetRequiredService <GitHubClaimResolver>();
                        ClaimsIdentity identity = ctx.Principal.Identities.FirstOrDefault();
                        identity?.AddClaims(await resolver.GetMembershipClaims(resolver.GetAccessToken(ctx.Principal)));
                    },
                };
            })
            .AddExternalCookie()
            ;
            services.AddAzureTableTokenStore(o => Configuration.GetSection("AzureTableTokenStore").Bind(o));
            services.AddAuthorization(
                options =>
            {
                options.AddPolicy(
                    MsftAuthorizationPolicyName,
                    policy =>
                {
                    policy.RequireAuthenticatedUser();
                    if (!Env.IsDevelopment())
                    {
                        policy.RequireRole(GitHubClaimResolver.GetTeamRole("dotnet", "dnceng"), GitHubClaimResolver.GetTeamRole("dotnet", "bots-high"));
                    }
                });
            });
            services.AddKustoIngest(options => Configuration.GetSection("Kusto").Bind(options));

            services.AddScoped <SimpleSigninMiddleware>();
            services.AddGitHubTokenProvider();
            services.AddSingleton <IInstallationLookup, InMemoryCacheInstallationLookup>();

            services.AddSingleton <ZenHubClient>();
            services.AddSingleton <IGitHubApplicationClientFactory, GitHubApplicationClientFactory>();
            services.AddSingleton <IGitHubClientFactory, GitHubClientFactory>();
        }
コード例 #5
0
        private void AddServices(IServiceCollection services)
        {
            services.AddRazorPages(o =>
            {
                o.Conventions
                .AuthorizeFolder("/", MsftAuthorizationPolicyName)
                .AllowAnonymousToPage("/Index")
                .AllowAnonymousToPage("/Status")
                .AllowAnonymousToPage("/Routes")
                .AllowAnonymousToPage("/Error");
                o.RootDirectory = "/Pages";
            });

            services.AddControllers()
            .AddGitHubWebHooks();

            services.AddApplicationInsightsTelemetry(Configuration.GetSection("ApplicationInsights").Bind);
            services.Configure <LoggerFilterOptions>(o =>
            {
                // This handler is added by 'AddApplicationInsightsTelemetry' above and hard limits
                // and reporting below "warning", which basically kills all logging
                // Remove it, we already configured the filters in Program.cs
                o.Rules.Remove(o.Rules.FirstOrDefault(r =>
                                                      r.ProviderName ==
                                                      "Microsoft.Extensions.Logging.ApplicationInsights.ApplicationInsightsLoggerProvider"));

                // These two categories log a lot of noise at "Information", let's raise them to warning
                o.Rules.Add(new LoggerFilterRule(null, "Microsoft.AspNetCore.Mvc.ViewFeatures.Filters.ValidateAntiforgeryTokenAuthorizationFilter", LogLevel.Warning, null));
                o.Rules.Add(new LoggerFilterRule(null, "Microsoft.AspNetCore.Mvc.ViewFeatures.Filters.AutoValidateAntiforgeryTokenAuthorizationFilter", LogLevel.Warning, null));
            });

            services.AddAuthentication("contextual")
            .AddPolicyScheme("contextual", "Contextual Scheme",
                             o => { o.ForwardDefaultSelector = context =>
                                    {
                                        if (context.Request.Path.StartsWithSegments("/api/webhooks"))
                                        {
                                            return("nothing");
                                        }
                                        if (context.Request.Path.StartsWithSegments("/api"))
                                        {
                                            return("github-token");
                                        }

                                        return(IdentityConstants.ApplicationScheme);
                                    }; })
            .AddGitHubOAuth(Configuration.GetSection("GitHubAuthentication"), GitHubScheme)
            .AddScheme <NothingOptions, NothingHandler>("nothing", o => { })
            .AddScheme <UserTokenOptions, GitHubUserTokenHandler>("github-token", o => { })
            .AddCookie(IdentityConstants.ApplicationScheme,
                       o =>
            {
                o.ExpireTimeSpan     = TimeSpan.FromMinutes(30);
                o.SlidingExpiration  = true;
                o.Cookie.IsEssential = true;
                o.LoginPath          = "/signin";
                o.LogoutPath         = "/signout";
                o.ReturnUrlParameter = "r";
                o.Events             = new CookieAuthenticationEvents
                {
                    OnValidatePrincipal = async ctx =>
                    {
                        GitHubClaimResolver resolver =
                            ctx.HttpContext.RequestServices.GetRequiredService <GitHubClaimResolver>();
                        ClaimsIdentity identity = ctx.Principal.Identities.FirstOrDefault();
                        identity?.AddClaims(await resolver.GetMembershipClaims(resolver.GetAccessToken(ctx.Principal)));
                    },
                };
            })
            .AddExternalCookie()
            ;
            services.AddAzureTableTokenStore(o => Configuration.GetSection("AzureTableTokenStore").Bind(o));
            services.AddAuthorization(
                options =>
            {
                options.AddPolicy(
                    MsftAuthorizationPolicyName,
                    policy =>
                {
                    policy.RequireAuthenticatedUser();
                    if (!Env.IsDevelopment())
                    {
                        policy.RequireRole(GitHubClaimResolver.GetTeamRole("dotnet", "dnceng"), GitHubClaimResolver.GetTeamRole("dotnet", "bots-high"));
                    }
                });
            });
            services.AddKustoIngest(options => Configuration.GetSection("Kusto").Bind(options));

            services.AddScoped <SimpleSigninMiddleware>();
            services.AddGitHubTokenProvider();
            services.AddSingleton <IInstallationLookup, InMemoryCacheInstallationLookup>();

            services.AddSingleton <ZenHubClient>();
            services.AddSingleton <IGitHubApplicationClientFactory, GitHubApplicationClientFactory>();
            services.AddSingleton <IGitHubClientFactory, GitHubClientFactory>();
            services.AddSingleton <ITimelineIssueTriage, TimelineIssueTriage>();
            services.AddSingleton <ExponentialRetry>();
            services.AddSingleton <ISystemClock, SystemClock>();
            services.AddSingleton <Microsoft.Extensions.Internal.ISystemClock, Microsoft.Extensions.Internal.SystemClock>();
            services.AddHttpClient();
            services.AddHealthReporting(
                b =>
            {
                b.AddLogging();
                b.AddAzureTable((o, p) => o.WriteSasUri = p.GetRequiredService <IConfiguration>()["HealthTableUri"]);
            });

            services.AddScoped <ITeamMentionForwarder, TeamMentionForwarder>();
        }
コード例 #6
0
        protected override async Task <AuthenticateResult> HandleAuthenticateAsync()
        {
            string protectedToken = null;

            if (Request.Headers.TryGetValue("Authorization", out StringValues authHeader) &&
                AuthenticationHeaderValue.TryParse(authHeader.ToString(), out AuthenticationHeaderValue auth) &&
                !string.IsNullOrEmpty(auth.Parameter) &&
                auth.Parameter.Length < 1000)
            {
                switch (auth.Scheme.ToLowerInvariant())
                {
                case "basic":
                    protectedToken = ParseBasicAuth(auth.Parameter);
                    break;

                case "bearer":
                    protectedToken = auth.Parameter;
                    break;
                }
            }

            if (string.IsNullOrEmpty(protectedToken) &&
                Request.Query.TryGetValue("token", out StringValues tokenQuery))
            {
                protectedToken = tokenQuery.ToString();
            }

            if (string.IsNullOrEmpty(protectedToken))
            {
                Logger.LogInformation("No token found in 'Authorization: Bearer <token>', 'Authorization: Basic <base64(ignored:<token>)>', or '?token=<token>'");
                return(AuthenticateResult.NoResult());
            }

            if (!TryDecodeToken(protectedToken, out GitHubTokenData token))
            {
                string reportToken = protectedToken;
                if (reportToken.Length > 10)
                {
                    reportToken = reportToken.Substring(0, 5) + "..." + reportToken.Substring(reportToken.Length - 5);
                }

                Logger.LogWarning("Token failed to decode correctly, token signature... {token}", reportToken);
                return(AuthenticateResult.Fail("Invalid token"));
            }

            if (await _revocation.IsTokenRevokedAsync(token.UserId, token.TokenId))
            {
                Logger.LogWarning("Revoked token used, user {user}, token {token}", token.UserId, token.TokenId);
                return(AuthenticateResult.Fail("Invalid token"));
            }

            (IEnumerable <Claim> userClaims, IEnumerable <Claim> groupClaims) = await Task.WhenAll(
                _resolver.GetUserInformationClaims(token.AccessToken, Context.RequestAborted),
                _resolver.GetMembershipClaims(token.AccessToken, Context.RequestAborted)
                );

            var identity  = new ClaimsIdentity(userClaims.Concat(groupClaims), Scheme.Name);
            var principal = new ClaimsPrincipal(new[] { identity });
            var ticket    = new AuthenticationTicket(principal, Scheme.Name);

            return(AuthenticateResult.Success(ticket));
        }