.Net Framework多租户OIDC身份验证



我们有3个应用程序(Desktop、Mobile、Excel Addon(,这意味着需要调用我们的API的3个客户端ID。

是否可以将我们的API配置为使用这3个客户端ID?以下是当前配置:

string OidcAuthority = Config.OidcAuthority;
string OidcRedirectUrl = Config.OidcRedirectUrl;
string OidcClientId = Config.OidcClientId;
string OidcClientSecret = Config.OidcClientSecret;
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
app.UseCookieAuthentication(new CookieAuthenticationOptions());
var oidcOptions = new OpenIdConnectAuthenticationOptions
{
Authority = OidcAuthority,
ClientId = OidcClientId,
ClientSecret = OidcClientSecret,
PostLogoutRedirectUri = OidcRedirectUrl,
RedirectUri = OidcRedirectUrl,
ResponseType = OpenIdConnectResponseType.Code,
Scope = OpenIdConnectScope.OpenId                    
};
app.UseOpenIdConnectAuthentication(oidcOptions);

编辑:

以下是我们使用oauth2和Auth0服务时的代码。

var domain = Config.Domain;
var apiIdentifier = Config.ApiIdentifier;
var keyResolver = new OpenIdConnectSigningKeyResolver(domain);
app.UseJwtBearerAuthentication(
new JwtBearerAuthenticationOptions
{
AuthenticationMode = AuthenticationMode.Active,
TokenValidationParameters = new TokenValidationParameters()
{
ValidAudience = apiIdentifier,
ValidIssuer = domain,
IssuerSigningKeyResolver = (token, securityToken, kid, parameters) => keyResolver.GetSigningKey(kid)
}
});

我知道我必须使用类似的东西,但我有3个可能的应用程序可以生成令牌,这意味着3个可能受众。。。我该怎么做?

第2版:

以下是在桌面应用程序(ExtJS(中获取访问令牌的代码:

userLogin: function(){
let deferred = new Ext.Deferred();
let self = this;
if (window.location.href.indexOf("#id_token") >= 0) {
return self.processLoginResponse(deferred, self);
}

var settings = {
authority: 'https://' + ONELOGIN_SUBDOMAIN + '.onelogin.com/oidc/2',    
client_id: ONELOGIN_CLIENT_ID,
redirect_uri: window.location.origin,
response_type: 'id_token token',
scope: 'openid profile',

filterProtocolClaims: true,
loadUserInfo: true
};
var mgr = new Oidc.UserManager(settings);
mgr.signinRedirect({state:'some data'}).then(function() {
deferred.resolve("signin redirect");
}).catch(function(err) {
deferred.reject(err);
});
return deferred.promise;
},
processLoginResponse: function(deferred, self){            
var settings = {
authority: 'https://' + ONELOGIN_SUBDOMAIN + '.onelogin.com/oidc/2',    
client_id: ONELOGIN_CLIENT_ID,
redirect_uri: window.location.origin,
response_type: 'id_token token',
scope: 'openid profile',

filterProtocolClaims: true,
loadUserInfo: true
};
var mgr = new Oidc.UserManager(settings);
mgr.signinRedirectCallback().then(function(user) {
Ext.Ajax.setDefaultHeaders({ 'Authorization': 'Bearer ' + user.id_token });
deferred.resolve("user signed in");
}).catch(function(err) {
console.log(err);
deferred.reject(err);
});
return deferred.promise;
}

网站与API技术堆栈

你正在使用的技术堆栈是为网站设计的。加载HTML页面时,如果没有有效的身份验证cookie,则用户会突然重定向到登录。

相反,本机客户端通过直接的HTTP请求调用API,而上面的堆栈将试图重定向这些请求,这将是错误的行为。

相反,本机应用程序应该各自实现自己的OIDC流,以使用自己的客户端ID来获得访问令牌。RFC8252标准描述了这些流。API不需要知道其调用者的客户端ID。

API技术堆叠行为

对于多个相关的客户端,使用相同的API是可能的,并且通常建议使用。如果使用C#,API通常使用以下选项,其中API在每个请求上验证JWT访问令牌:

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.Authority = Config.Authority;
options.Audience = Config.Audience;
});

这是您为了使用它而包含的Microsoft软件包:

<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="6.0.10" />

通常,权限是授权服务器的基本URL,受众是您定义的一个值,用于表示一个或多个相关API:

authority: https://login.example.com
audience: api.example.com

如果需要,具有相同受众的API可以相互转发JWT,这样它们就可以以相同的方式对请求进行授权。Microsoft安全堆栈将从授权服务器下载并缓存令牌签名公钥,然后使用它对接收到的访问令牌进行数字验证,并构建ClaimsPrincipal。

JWT经过验证后,您还可以信任它发布的声明,并根据这些声明进行授权,例如通过定义以下授权策略:

services.AddAuthorization(options =>
{
options.AddPolicy("myPolicy", policy =>
policy.RequireAssertion(context =>
context.User.HasClaim(claim => 
claim.Type == "myClaim" && claim.Value == "myValue
)
)
);
});

在逻辑级别对授权进行编码的一种方法是,控制器应用Authorize属性以应用策略:

[HttpGet("/api/resource")]
[Authorize(Policy = "myPolicy")]
public IActionResult GetResource()
{
return Ok(new { data = "My data" });
}

JWT在.NET框架中的验证

在旧的.NET框架中,概念是相同的,唯一的区别是授权属性的工作方式可能略有不同。以下是JWT的验证方法,其中发卡机构/授权机构仍然代表授权服务器的基本URL:

app.UseJwtBearerAuthentication(
new JwtBearerAuthenticationOptions
{
TokenValidationParameters = new TokenValidationParameters()
{
ValidateIssuer = true,
ValidateAudience = true,
ValidIssuer = Config.Issuer;
ValidAudience = Config.Audience;
}
});

最新更新