我想知道为什么我的客户端重定向到身份服务器。
我采取以下步骤:
此时,身份服务器,客户端和api已部署到共享主机提供程序,我正在使用EF来存储配置和操作。
身份服务器配置
services.AddIdentityServer(options =>
{
options.Authentication.CookieSlidingExpiration = true;
options.Authentication.CookieLifetime = TimeSpan.FromDays(1);
})
.AddDeveloperSigningCredential()
.AddAspNetIdentity<ApplicationUser>()
.AddConfigurationStore(options =>
{
options.ConfigureDbContext = builder =>
builder.UseSqlServer(connectionString,
sql => sql.MigrationsAssembly(migrationsAssembly));
})
.AddOperationalStore(options =>
{
options.ConfigureDbContext = builder =>
builder.UseSqlServer(connectionString,
sql => sql.MigrationsAssembly(migrationsAssembly));
options.EnableTokenCleanup = true;
options.TokenCleanupInterval = 30;
});
services.AddAuthentication("custom")
.AddCookie("custom", options =>
{
options.Cookie.Name = "custom";
options.ExpireTimeSpan = TimeSpan.FromDays(1);
});
services.AddAuthentication()
.AddFacebook(options =>
{
options.AppId = "1";
options.AppSecret = "2";
});
Config.cs中的客户端
new Client
{
ClientId = "mvc-client",
ClientName = "Mvc Client",
AllowedGrantTypes = GrantTypes.HybridAndClientCredentials,
RequireConsent = false,
ClientSecrets =
{
new Secret("secret".Sha256())
},
RedirectUris = { $"{address}signin-oidc" },
PostLogoutRedirectUris = { $"{address}Client/" },
AllowedScopes = new List<string>
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
"api"
},
RefreshTokenUsage = TokenUsage.OneTimeOnly,
RefreshTokenExpiration = TokenExpiration.Sliding,
SlidingRefreshTokenLifetime = (3600 * 24 * 30),
IdentityTokenLifetime = (60 * 15),
AccessTokenLifetime = 300,
AllowOfflineAccess = true,
}
MVC客户端配置
services.AddAuthentication(options =>
{
options.DefaultScheme = "Cookies";
options.DefaultChallengeScheme = "oidc";
})
.AddCookie("Cookies", options =>
{
options.Cookie.Expiration = TimeSpan.FromDays(30);
})
.AddOpenIdConnect("oidc", options =>
{
options.SignInScheme = "Cookies";
options.Authority = $"{_config["Server"]}";
options.RequireHttpsMetadata = false;
options.ClientId = "mvc-client";
options.ClientSecret = "secret";
options.ResponseType = "code id_token";
options.Scope.Add("api");
options.Scope.Add("offline_access");
options.GetClaimsFromUserInfoEndpoint = true;
options.SaveTokens = true;
options.TokenValidationParameters = new TokenValidationParameters
{
NameClaimType = JwtClaimTypes.Name,
RoleClaimType = JwtClaimTypes.Role,
};
});
令牌续订服务过滤器
var accessToken = await context.HttpContext.GetTokenAsync("access_token");
var introspectionClient = new IntrospectionClient(_ipoint, "api", "api_secret");
var response = await introspectionClient.SendAsync(new IntrospectionRequest { Token = accessToken });
if (!response.IsActive)
{
var issuer = _config["Server"].ToLower();
var client = new DiscoveryClient(issuer);
client.Policy.RequireHttps = false;
var disco = await client.GetAsync();
if (disco.IsError) throw new Exception(disco.Error);
var tokenClient = new TokenClient(disco.TokenEndpoint, "mvc-client", "secret");
var rt = await context.HttpContext.GetTokenAsync("refresh_token");
var tokenResult = await tokenClient.RequestRefreshTokenAsync(rt);
if (!tokenResult.IsError)
{
var info = await context.HttpContext.AuthenticateAsync("Cookies");
var old_id_token = await context.HttpContext.GetTokenAsync("id_token");
var new_access_token = tokenResult.AccessToken;
var new_refresh_token = tokenResult.RefreshToken;
var tokens = new List<AuthenticationToken>();
tokens.Add(new AuthenticationToken { Name = OpenIdConnectParameterNames.IdToken, Value = old_id_token });
tokens.Add(new AuthenticationToken { Name = OpenIdConnectParameterNames.AccessToken, Value = new_access_token });
tokens.Add(new AuthenticationToken { Name = OpenIdConnectParameterNames.RefreshToken, Value = new_refresh_token });
var expiresAt = DateTime.UtcNow + TimeSpan.FromSeconds(tokenResult.ExpiresIn);
tokens.Add(new AuthenticationToken { Name = "expires_at", Value = expiresAt.ToString("o", CultureInfo.InvariantCulture) });
info.Properties.StoreTokens(tokens);
await context.HttpContext.SignInAsync("Cookies", info.Principal, info.Properties);
}
else
{
await context.HttpContext.SignOutAsync("Cookies");
}
}
await next();
注意:我试图在IS上覆盖的Cookie中间件不起作用。 (例如:登录后,我在开发人员工具中看不到“自定义” cookie)
所以我的逻辑是刷新令牌是30天(并且在滑动),客户端上的cookie是30天(并且在服务过滤器中更新),这意味着用户最多可以在30天后返回天,并且仍然可以使用客户端重定向到身份服务器。
我正在尝试实现尽可能少的登录,因此,如果用户正在积极使用该应用程序,我希望他永远不会重定向到登录页面。
我认为发生的事情是cookie丢失了,并且[Authorize]
属性在我的过滤器之前被调用,因此发生了重定向。我不确定id_token
到期是否会导致重定向,请告知我。
虽然我可能会导致此问题:
答案 0 :(得分:1)
我正在使用的托管服务每天凌晨4:00刷新其应用程序池,因此删除了计算机密钥。
将机器密钥存储在文件系统中是解决方案:
services.AddDataProtection()
.SetApplicationName("Server")
.PersistKeysToFileSystem(new DirectoryInfo(_config["MachineKeys"]));
警告:此解决方案不会使用x509证书对密钥进行加密。