拦截asp.net核心授权操作以在成功授权后执行自定义操作

时间:2018-04-06 10:05:08

标签: c# asp.net-mvc asp.net-core identityserver4 asp.net-core-middleware

我的网络应用控制器上有[授权]属性,因此任何端点都会确保用户首先被重定向登录OAuth服务器(如果尚未登录)。

我现在想要在每次用户登录时开始将用户声明写入Web应用程序数据库。为此,我需要在每次用户成功登录/授权时在Web应用程序上运行一些代码。< / p>

我得到了一个线索,它涉及添加自定义中间件。

My Startup ConfigureServices代码目前如下:

public class Startup
{
    public Startup(IConfiguration configuration, IHostingEnvironment env)
    {
        Configuration = configuration;
        Env = env;
    }

    public IHostingEnvironment Env { get; }
    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {

        services.AddMvc();

        // Adds a default in-memory implementation of IDistributedCache.
        services.AddDistributedMemoryCache();

        services.AddSession(options =>
        {
            options.Cookie.HttpOnly = true;
        });

        JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();

        services.AddAuthentication(options =>
        {
            options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
        })
            .AddCookie()
            .AddOpenIdConnect(options =>
            {
                options.SignInScheme = "Cookies";
                options.Authority = Configuration["auth:oidc:authority"];                    

                options.RequireHttpsMetadata = !Env.IsDevelopment();
                options.ClientId = Configuration["auth:oidc:clientid"];
                options.ClientSecret = Configuration["auth:oidc:clientsecret"];
                options.ResponseType = "code id_token"; 

                options.Scope.Add(Configuration["auth:oidc:clientid"]);
                options.Scope.Add("offline_access");

                options.GetClaimsFromUserInfoEndpoint = true;
                options.SaveTokens = true;

            });

    }

... []

所以我的问题是:我需要添加哪些代码,以及在何处调用将包含自定义操作的方法?

2 个答案:

答案 0 :(得分:6)

OpenIDConnectOptions类具有Events属性,适用于此类情况。此Events属性(OpenIdConnectEvents)具有OnTokenValidated属性(Func<TokenValidatedContext, Task>),您可以覆盖该属性,以便在令牌得到验证时得到通知。这是一些代码:

options.Events.OnTokenValidated = ctx =>
{
    // Your code here.
    return Task.CompletedTask;
};

在示例代码中,ctxTokenValidatedContextultimately包含Principal属性(ClaimsPrincipal):您应该能够使用此属性获得您需要的索赔等财产,例如ctx.Principal.FindFirst(...)

正如@Brad在评论中提到的那样,每个请求都会调用OnTokenValidated,并且(根据您自己的评论),不会包含您需要的UserInfo。为了实现这一点,您可以使用OnUserInformationReceived,如下所示:

options.Events.OnUserInformationReceived = ctx =>
{
    // Here, ctx.User is a JObject that should include the UserInfo you need.
    return Task.CompletedTask;
};
此示例中的

ctxUserInformationReceivedContext:它仍然包含Principal属性,但也有User属性(JObject),正如我所说的那样带有评论的代码。

答案 1 :(得分:0)

你应该看看OpenIdConnectOptions.Events。我没有举手示例,但这是挂钩OIDC中间件的地方。