.net Core 2.2多承载令牌认证方案

时间:2019-12-13 18:22:59

标签: .net-core jwt azure-active-directory bearer-token .net-core-2.2

我目前正在尝试在.net core 2.2应用程序中使用2个不同的承载令牌。我想使用Identity Server令牌和Azure AD承载令牌。根据Microsoft的说法,这是可能的(https://docs.microsoft.com/en-us/aspnet/core/security/authorization/limitingidentitybyscheme?view=aspnetcore-2.2),但我无法成功使其正常运行。

我将Identity Server令牌作为“默认”身份验证,后跟上述链接中记录的AzureAD令牌:

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(o =>
    {
        o.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateAudience = true,
            ValidateIssuer = true,
            ValidateLifetime = true,
            ClockSkew = ClockSkew
        };
        o.Audience = Audience;
        o.Authority = IdentityIssuer;
        o.RequireHttpsMetadata = true;
    })
    .AddJwtBearer("AzureAd",o =>
    {
        o.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer = true,
            ValidateAudience = true,
            ValidateLifetime = true,
        };
        o.Audience = AudienceUri;
        o.Authority = Authority
    });

Identity Server令牌验证符合预期;但是Azure AD令牌没有。它们似乎总是命中默认的Bearer令牌处理程序。

2 个答案:

答案 0 :(得分:0)

尝试类似这样的方法(我有2个身份验证方案。一个用于AAD,一个用于自定义Bearer身份验证)

+------+--------+--------+--------+--------+--------+
|userId| i-2    |  i-1   |   i    |    i+1 |     i+2|
+------+--------+--------+--------+--------+--------+
|37    |10005880|10005903|10005903|12458442|10005903|
|37    |10005903|10005903|12458442|10005903|12632813|

然后在您的Controller标记类或方法中将其标记为:

 var url = new MongoUrl(mongoSettings.ConnectionString); // I'm using MONGODB as databse ..but you can choose what you want 

            var client = new MongoClient(url);

            var database = client.GetDatabase(url.DatabaseName);

            services.AddIdentity<ApplicationUser, ApplicationRole>(options =>

            {
                options.Password.RequireDigit = true;

                options.Password.RequiredLength = 6;

                options.Password.RequireNonAlphanumeric = false;

                options.Password.RequireUppercase = true;

                options.Password.RequireLowercase = true;

                // Lockout settings

                options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(30);

                options.Lockout.MaxFailedAccessAttempts = 0;

                // ApplicationUser settings

                options.User.RequireUniqueEmail = false;

                //options.User.AllowedUserNameCharacters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789@.-_";
            }).RegisterMongoStores<ApplicationUser, ApplicationRole>(

                p => database.GetCollection<ApplicationUser>("AspNetUsers"),

                p => database.GetCollection<ApplicationRole>("AspNetRoles"))

              .AddDefaultTokenProviders();

            JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear(); // => remove default claims





            var signingKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(appConfiguration.Key));

            var tokenValidationParameters = new TokenValidationParameters

            {
                //RequireExpirationTime = true,

                //RequireSignedTokens = true,

                //ValidateIssuerSigningKey = true,

                IssuerSigningKey = signingKey,

                ValidateIssuer = false,

                ValidIssuer = appConfiguration.SiteUrl,

                ValidateAudience = false,

                ValidAudience = appConfiguration.SiteUrl,

                //ValidateLifetime = true,

                ClockSkew = TimeSpan.Zero
            };

            services.AddAuthentication(options =>

            {
                //options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme
                options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
            }).AddJwtBearer("AAD", options =>
              {
                  //options.Audience = appConfiguration.SiteUrl;

                  //options.ClaimsIssuer = appConfiguration.SiteUrl;
                  options.IncludeErrorDetails = true;
                  options.Authority = "https://sts.windows.net/800859e2-e8c3-4842-b31a-3b3727070cb6/v2.0";
                  options.Audience = "5e2ddaf2-2ed3-4829-bbe8-9aa127a754ef";
                  options.SaveToken = true;

                  options.Events = new JwtBearerEvents()
                  {
                      OnMessageReceived = context =>
                      {
                          if ((context.Request.Path.Value.StartsWith("/videohub")
                              //|| context.Request.Path.Value.StartsWith("/looney")
                              //|| context.Request.Path.Value.StartsWith("/usersdm")
                             )
                              && context.Request.Query.TryGetValue("token", out StringValues token)
                          )
                          {
                              context.Token = token;
                          }

                          return Task.CompletedTask;
                      },
                      OnAuthenticationFailed = context =>
                      {
                          //TODO:
                          return Task.FromResult(0);
                      },
                      OnTokenValidated = context =>
                      {
                          //At this point, the security token has been validated successfully and a ClaimsIdentity has been created
                          var claimsIdentity = (ClaimsIdentity)context.Principal.Identity;

                          //get username
                          var preferred_username = claimsIdentity.Claims.ToList().Where(c => c.Type == "preferred_username").Select(c => c.Value).FirstOrDefault();

                          var username = !string.IsNullOrEmpty(preferred_username) ? preferred_username : claimsIdentity.Claims.ToList().Where(c => c.Type == "upn").Select(c => c.Value).FirstOrDefault();

                          //add your custom claims here
                          var serviceProvider = services.BuildServiceProvider();
                          var userservice = serviceProvider.GetService<IUsersService>();

                          var us = userservice.Find(xx => xx.UserName == username);
                          if (us == null) return Task.FromResult(0);

                          // ADD SCHEMA (so we know which kind of token is .. from AZURE ACTIVE DIRECOTY .. OR CUSTOM)
                          // TO RETIRVE THE SCHEDA ..--> //var result = User.Claims.Where(c=>c.Type=="schema").FirstOrDefault().Value;
                          claimsIdentity.AddClaim(new Claim("schema", "AAD"));

                          //GET ROLES FROM DB
                          if (us != null && us.Roles.Any())
                          {
                              //add THEM
                              us.Roles.ForEach(rr =>
                               {
                                   claimsIdentity.AddClaim(new Claim(ClaimsIdentity.DefaultRoleClaimType, rr.ToUpper()));
                               });
                          }
                          else
                          {
                              //OR ADD A DEFAULT ONE
                              claimsIdentity.AddClaim(new Claim(ClaimsIdentity.DefaultRoleClaimType, Constant.ROLES.Dipendente));
                          }

                          // add MONGDB Id as ClaimTypes.NameIdentifier
                          claimsIdentity.AddClaim(new Claim(ClaimTypes.NameIdentifier, us.Id));

                          return Task.FromResult(0);
                      }
                  };
              }).AddJwtBearer("CUSTOM", options =>
               {
                   //options.Audience = appConfiguration.SiteUrl;

                   //options.ClaimsIssuer = appConfiguration.SiteUrl;

                   options.TokenValidationParameters = tokenValidationParameters;

                   options.SaveToken = true;
                   options.Events = new JwtBearerEvents()
                   {

                       OnAuthenticationFailed = context =>
                       {
                           //TODO:
                           return Task.FromResult(0);
                       },
                       OnTokenValidated = context =>
                       {
                           //At this point, the security token has been validated successfully and a ClaimsIdentity has been created
                           var claimsIdentity = (ClaimsIdentity)context.Principal.Identity;

                           //add your custom claims here

                           // ADD SCHEMA (so we know which kind of token is .. from AZURE ACTIVE DIRECOTY .. OR CUSTOM)
                           claimsIdentity.AddClaim(new Claim("schema", "CUSTOM"));

                           return Task.FromResult(0);
                       }
                   };
               });

希望对您有帮助!

答案 1 :(得分:0)

您可以尝试的事情:

1设置默认策略

services.AddAuthorization(options => { 
        options.DefaultPolicy = new AuthorizationPolicyBuilder(JwtBearerDefaults.AuthenticationScheme, "AzureAD")
           .RequireAuthenticatedUser()
           .Build();

2在jwtOptions.Events之一下的OnAuthenticationFailed>上,添加一个经过验证的条件,然后完成任务,并且不显示错误。 有时用户已经通过身份验证,但是来自一个提供者的错误阻止了正确的响应

 if (arg.HttpContext.User.Identity.IsAuthenticated)
    {
       return Task.CompletedTask;
    }

3如果不起作用。有黑客检查它是否已通过身份验证。为每个方案添加更多条件。

      app.Use(async (context, next) =>
            {
                if (!context.User.Identity.IsAuthenticated)
                {
                    var result = await context.AuthenticateAsync("AzureAD");
                    if (result?.Principal != null)
                    {
                        context.User = result.Principal;
                    }
                }

                await next.Invoke();
            });