根據您使用的ADFS版本,您應該能夠使用OAuth或OIDC中間件從ASP.NET Core應用程序進行連接(假設您使用的是ASP.NET Core,因爲您是使用Bluemix)。如果您至少使用ADFS 3.0(Windows Server 2012+),則可以使用ASP.NET Core的通用OAuth中間件進行連接。
首先,創建一個配置文件來存儲您的ADFS服務器設置或修改現有配置文件(如appsettings.json)。
樣本 「ADFS-settings.json」 文件:
{
"ADFS": {
"ClientId": "Your ClientId as set on ADFS server",
"ResourceUrl": "url of this application (ex: http://mywebapp.mybluemix.net)",
"ServerUrl": "url of ADFS (ex: https://dc.your.domain)"
}
}
如果您創建一個新的文件,如 「ADFS-settings.json」,爲您的ADFS配置,它添加到您的Configuration
對象Startup.cs文件的構造函數。
public Startup(IHostingEnvironment env)
{
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("adfs-settings.json");
Configuration = builder.Build();
}
在你Startup.cs的Configure
方法創建一個OAuthOptions
對象:
var options = new OAuthOptions();
options.AutomaticChallenge = true;
options.AuthenticationScheme = "ADFS";
指定您從您的Configuration
對象中讀取它配置您的服務器ADFS這個應用程序時創建的ClientId
。通用OAuth中間件也要求您在這裏提供ClientSecret
,即使該值實際上並未被ADFS 3.0使用。
options.ClientId = Configuration["ADFS:ClientId"];
options.ClientSecret = "ADFS 3.0 does not support confidential client, but OAuth middleware requires it";
設置ADFS服務器將在您的應用程序中重定向到的回調url。
options.CallbackPath = new PathString("/signin-adfs");
現在配置OAuthEvents
。 OnRedirectToAuthorizationEndpoint
定義了當應用程序確定需要授權用戶時傳遞給ADFS授權端點的參數。這將需要至少一個resource
參數指向您的應用程序的URL。當ADFS服務器完成對客戶端的授權並將包含聲明數據的JWT令牌返回給應用程序時,會觸發OnCreatingTicket
。在這種方法中,您需要處理向HttpContext
對象添加角色和聲明。
options.Events = new OAuthEvents {
OnRedirectToAuthorizationEndpoint = context =>
{
var parameter = new Dictionary<string, string>
{
["resource"] = Configuration["ADFS:ResourceUrl"]
};
var query = QueryHelpers.AddQueryString(context.RedirectUri, parameter);
context.Response.Redirect(query);
return Task.CompletedTask;
},
OnCreatingTicket = context => {
JwtSecurityTokenHandler tokenHandler = new JwtSecurityTokenHandler();
JwtSecurityToken validatedToken = tokenHandler.ReadJwtToken(context.AccessToken);
IEnumerable<Claim> a = validatedToken.Claims;
foreach (var claim in a)
{
// role claim needs to be mapped to http://schemas.microsoft.com/ws/2008/06/identity/claims/role
// for IsInRole() to work properly
if (claim.Type == "role")
{
context.Identity.AddClaim(new Claim(ClaimTypes.Role, claim.Value));
}
else if (claim.Type == "unique_name")
{
// map name to Identity.Name
context.Identity.AddClaim(new Claim(context.Identity.NameClaimType, claim.Value));
}
else
{
// this is optional, if you want any other specific claims from Active Directory
// this will also include some information about the jwt token such as the issue
// and expire times
context.Identity.AddClaim(new Claim(claim.Type, claim.Value));
}
}
return Task.CompletedTask;
}
};
接下來,設置ClaimsIssuer
到ADFS URL,並設置SignInScheme
到CookieAuthenticationDefaults.AuthenticationScheme
和您的ADFS服務器上配置AuthorizationEndpoint
和TokenEndpoint
到合適的端點。
options.ClaimsIssuer = Configuration["ADFS:ServerUrl"];
options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.AuthorizationEndpoint = Configuration["ADFS:ServerUrl"] + "/adfs/oauth2/authorize/";
options.TokenEndpoint = Configuration["ADFS:ServerUrl"] + "/adfs/oauth2/token/";
最後,使用您剛纔創建的選項添加OAuth的中間件:
app.UseCookieAuthentication(new CookieAuthenticationOptions());
app.UseOAuthAuthentication(options);
現在,你應該能夠在[Authorize]
屬性適用於任何控制器或動作需要授權與ADFS。有關完整的示例應用程序,請參閱this GitHub repo。
非常感謝,這對通用的ADFSv3/OAuth非常有用。缺少的一件事就是爲什麼'signInManager.GetExternalLoginInfoAsync'返回null。 –
對於記錄:在我的情況下,'signInManager.GetExternalLoginInfoAsync'返回,因爲缺少索賠。 ADFSv3聲明類型似乎不遵循標準聲明(因此我們必須進行轉換),但即使這樣也會混淆。所以,而不是以下內容: 'context.Identity.AddClaim(new Claim(context.Identity.NameClaimType,claim.Value));' 我必須使用: 'context.Identity.AddClaim(new Claim(ClaimTypes .NameIdentifier,claim.Value));' –