場合によっては ADFS 認証を使用するプロジェクトがあります。構成はデータベースから読み取られ、URL は顧客ごとに異なるため、.com にハードコーディングできない多くの構成オプションがありますWeb.config
。
問題は、次のエラーが発生することです。
ID1032: AudienceUriMode が「Always」または「BearerKeyOnly」に設定されている場合、SamlSecurityTokenRequirement で少なくとも 1 つの「audienceUri」を指定する必要があります
しかし、私はいつもそれを得るわけではなく、再現することはできません. 再現できない限り、実際にデバッグすることはできないので、これはかなり面倒です。そして、私がすべて正しいことをしたかどうかはわかりません。たぶん、ADFSの専門家がそれを見ることができます。
(もちろん、証明書利用者と対応する ADFS サーバーとの間の信頼は確立されています。)
これが私のコードです (興味深い部分のみ)。不足しているものや不明な点がある場合はお問い合わせください。
私のからのいくつかのスニペットWeb.config
:
<system.webServer>
<modules>
<add name="WSFederationAuthenticationModule" type="Microsoft.IdentityModel.Web.WSFederationAuthenticationModule, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" preCondition="managedHandler" />
<add name="SessionAuthenticationModule" type="Microsoft.IdentityModel.Web.SessionAuthenticationModule, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" preCondition="managedHandler" />
<add name="ClaimsPrincipalHttpModule" type="Microsoft.IdentityModel.Web.ClaimsPrincipalHttpModule, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" preCondition="managedHandler" />
<!-- ... -->
</modules>
<!-- ... -->
</system.webServer>
<microsoft.identityModel>
<service>
<securityTokenHandlers>
<remove type="Microsoft.IdentityModel.Tokens.SessionSecurityTokenHandler" />
<add type="MyProject.MachineKeySessionSecurityTokenHandler" />
</securityTokenHandlers>
<federatedAuthentication>
<wsFederation passiveRedirectEnabled="false"
issuer="https://fail/IssuerEndpoint"
realm="https://fail/FederationResult"
homeRealm="https://fail"
requireHttps="true" />
</federatedAuthentication>
</service>
</microsoft.identityModel>
これらの失敗値はリクエストごとにオーバーライドさLogin()
れます (以下の私の方法を参照) Web.config
。SessionSecurityTokenHandler
私のサービスは DNS ラウンド ロビン (同じマシン キーを共有する) を使用して複数のマシンで実行されるため、既定値を置き換える必要がありました。
AdfsTrustFilter
次に、実装するクラスを呼び出しましたIAuthorizationFilter
。少しオーバーヘッドがあることは承知していますが、プロジェクトの構造上、このフィルターはすべてのリクエストでグローバル フィルターとして使用されます (順序はプロジェクト全体で最小の値です)。メソッドではOnAuthorization
、次のように構成を完了します。
public sealed class AdfsTrustFilter : IAuthorizationFilter
public void OnAuthorization(AuthorizationContext filterContext)
// ...
var fam = FederatedAuthentication.WSFederationAuthenticationModule;
fam.ServiceConfiguration = new ServiceConfiguration
{
AudienceRestriction = new AudienceRestriction(AudienceUriMode.Always),
CertificateValidationMode = X509CertificateValidationMode.PeerOrChainTrust,
// MyIssuerNameRegistry checks whether a fingerprint is known and some other stuff
IssuerNameRegistry = new MyIssuerNameRegistry()
};
// config.OwnPath contains something like "https://my.app.com/AppRoot/"
fam.ServiceConfiguration.AudienceRestriction.AllowedAudienceUris.Add(new Uri(config.OwnPath));
}
}
これは、認証を開始するコードです。
public ActionResult Login()
{
// ...
// again something like "https://my.app.com/AppRoot/"
string baseUrl = Config.OwnPath.TrimEnd('/') + "/";
// adfs endpoint for this customer: i.e. "https://identity.provider.net/adfs/ls/"
string endpoint = Config.AdfsConfig.IdentityProvider.Endpoint;
// the code behind FederationResult is shown below
var signIn = new SignInRequestMessage(new Uri(endpoint), baseUrl + "/Adfs/FederationResult")
{
Context = baseUrl
};
var url = signIn.WriteQueryString();
return Redirect(url);
}
最後にFederationResult
コールバック:
public ActionResult FederationResult()
{
WSFederationAuthenticationModule fam = FederatedAuthentication.WSFederationAuthenticationModule;
HttpRequest request = System.Web.HttpContext.Current.Request;
if (fam.CanReadSignInResponse(request, true))
{
var id = (IClaimsIdentity) User.Identity;
// do something
}
// ...
}
PS: ADFS サーバーは最近 2008 R2 から 2012 にアップグレードされましたが、何も変わりませんでした。ADFS のバージョンは常に 2.0 でした。