我目前正在尝试在.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令牌处理程序。
答案 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();
});