私は、.Net 4.5.2 Web サイト プロジェクトに実用的なソリューションを実装しようとしています。 私の目標は、Web フォーム アプリケーション (MVC ではない) である Web サイト プロジェクトを、(おそらく thinktecture の実装を介して) ID サーバー 3 を使用してユーザーを認証/承認するように変換することです。
これは可能ですか? サイトのライフ サイクルはどのように変化しますか、それともセッション オブジェクトでも同じことが言えますか? ID サーバーを使用してアクセス トークンを取得し、セッションをセットアップして、セッションの有効期限が切れたとき、またはアクセス トークンの有効期限が切れたときにのみ新しいアクセス トークンを要求することはできますか?
バックストーリー:
次の場所https://localhost:44399で動作するアイデンティティ サーバー 3 のセットアップがあります。これは、ストレートな html ファイルを使用すると、すべての適切な呼び出しと制限に応答しますが、ログイン ページ (portal.aspx) に同じことを実装しようとすると、ユーザーを忘れているようで、同じように動作しません。Web サイト (クライアント) はhttps://localhost:9898にセットアップされています。ログイン ページはhttps://localhost:9898/portal.aspxです。
portal.aspx ページで oidc-client.js を使用していますが、認証しようとすると CORS (クロスブラウザー オリジン スクリプト) エラーが発生し続けます。 これは Web フォームの問題ですか? 通常の HTML ページを使用している場合は発生しませんか?
これは、MVC ではなく Web フォームを使用する .net 4.5.2 の「Web サイト プロジェクト」(「Web アプリケーション プロジェクト」ではありません) です。私は正しく動作するデモ MVC アプリケーションをたくさん持っていますが、Web フォーム アプリケーションに知識を持ち込もうとすると、何が起こっているのかを本当に把握していないことがわかります。
次の nuget パッケージを追加しました。
Microsoft.Bcl v1.1.10
Microsoft.Owin v3.0.1
Microsoft.Bcl.Async v1.0.168
System.IdentityModel.Tokens.Jwt v5.1.0
Newtonsoft.Json v9.0.1
Owin v1.0.0
Microsoft.IdentityModel.Logging v1.1.0
Microsoft.Owin.Host.SystemWeb v3.0.1
System.IdentityModel.Tokens.Jwt v5.1.0
Microsoft.IdentityModel.Tokens v5.1.0
Microsoft.Bcl.Build v1.0.21
Thinktecture.IdentityModel v3.6.1
startup.cs クラスを追加しようとすると、これらのクラスは通常 App_Code ディレクトリに追加されると表示されますが、そこに配置しますか? ルートと App_Code ディレクトリの両方を試しましたが、呼び出されたときにどちらも登録されていないようです。これが呼び出しを行うものだと考えて、パッケージを追加しました:
Microsoft.Owin.Host.SystemWeb
しかし、スタートアップクラスが登録されていないようです。 では、これをパイプラインに登録するにはどうすればよいのでしょうか? 401 の承認されていないエラーがユーザーを ID サーバーに送信するようにするにはどうすればよいでしょうか?
これが私のスタートアップクラスです:
using ExpenseTracker.WebClient.Helpers;
using Microsoft.Owin;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Cookies;
using Microsoft.Owin.Security.OpenIdConnect;
using Newtonsoft.Json.Linq;
using Owin;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IdentityModel.Tokens;
using System.Linq;
using System.Security.Claims;
using System.Text;
using System.Web;
using System.Web.Helpers;
using Thinktecture.IdentityModel.Client;
[assembly: OwinStartup(typeof(ExpenseTracker.WebClient.Startup))]
namespace ExpenseTracker.WebClient
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
JwtSecurityTokenHandler.InboundClaimTypeMap = new Dictionary<string, string>();
AntiForgeryConfig.UniqueClaimTypeIdentifier = "unique_user_key";
app.UseResourceAuthorization(new AuthorizationManager());
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = "Cookies"
});
app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
{
ClientId = "mvc",
Authority = ExpenseTrackerConstants.IdSrv,
RedirectUri = ExpenseTrackerConstants.ExpenseTrackerClient,
SignInAsAuthenticationType = "Cookies",
ResponseType = "code id_token token",
Scope = "openid profile roles expensetrackerapi offline_access",
Notifications = new OpenIdConnectAuthenticationNotifications()
{
MessageReceived = async n =>
{
EndpointAndTokenHelper.DecodeAndWrite(n.ProtocolMessage.IdToken);
EndpointAndTokenHelper.DecodeAndWrite(n.ProtocolMessage.AccessToken);
//var userInfo = await EndpointAndTokenHelper.CallUserInfoEndpoint(n.ProtocolMessage.AccessToken);
},
SecurityTokenValidated = async n =>
{
var userInfo = await EndpointAndTokenHelper.CallUserInfoEndpoint(n.ProtocolMessage.AccessToken);
// use the authorization code to get a refresh token
var tokenEndpointClient = new OAuth2Client(
new Uri(ExpenseTrackerConstants.IdSrvToken),
"mvc", "secret");
var tokenResponse = await tokenEndpointClient.RequestAuthorizationCodeAsync(
n.ProtocolMessage.Code, ExpenseTrackerConstants.ExpenseTrackerClient);
var givenNameClaim = new Claim(
Thinktecture.IdentityModel.Client.JwtClaimTypes.GivenName,
userInfo.Value<string>("given_name"));
var familyNameClaim = new Claim(
Thinktecture.IdentityModel.Client.JwtClaimTypes.FamilyName,
userInfo.Value<string>("family_name"));
var roles = userInfo.Value<JArray>("role").ToList();
var newIdentity = new ClaimsIdentity(
n.AuthenticationTicket.Identity.AuthenticationType,
Thinktecture.IdentityModel.Client.JwtClaimTypes.GivenName,
Thinktecture.IdentityModel.Client.JwtClaimTypes.Role);
newIdentity.AddClaim(givenNameClaim);
newIdentity.AddClaim(familyNameClaim);
foreach (var role in roles)
{
newIdentity.AddClaim(new Claim(
Thinktecture.IdentityModel.Client.JwtClaimTypes.Role,
role.ToString()));
}
var issuerClaim = n.AuthenticationTicket.Identity
.FindFirst(Thinktecture.IdentityModel.Client.JwtClaimTypes.Issuer);
var subjectClaim = n.AuthenticationTicket.Identity
.FindFirst(Thinktecture.IdentityModel.Client.JwtClaimTypes.Subject);
newIdentity.AddClaim(new Claim("unique_user_key",
issuerClaim.Value + "_" + subjectClaim.Value));
newIdentity.AddClaim(new Claim("refresh_token", tokenResponse.RefreshToken));
newIdentity.AddClaim(new Claim("access_token", tokenResponse.AccessToken));
newIdentity.AddClaim(new Claim("expires_at",
DateTime.Now.AddSeconds(tokenResponse.ExpiresIn).ToLocalTime().ToString()));
n.AuthenticationTicket = new AuthenticationTicket(
newIdentity,
n.AuthenticationTicket.Properties);
},
}
});
}
}
}
さらに悪いことに、Microsoft.Owin.Host.SystemWeb を追加すると、次のような奇妙なエラーが発生してコンパイルされません。
The type or namespace name 'SessionState' does not exist in the
namespace 'System.Web' (are you missing an assembly reference?)