第二次成功登录后,第二次登录会导致无限重定向循环MVC .NET 5 OWIN ADAL OpenIDConnect [英] Second sign-in causes infinite redirect loop after the first successful login MVC .NET 5 OWIN ADAL OpenIDConnect
问题描述
第一篇文章,请保持温柔! :)
first post so be gentle! :)
我正在为Office 365开发MVC .NET 5 Web应用程序,并且正在使用OpenIDConnect框架.我已经设置了OWIN(3)和ADAL(2)以及我的Azure AD应用程序.没有用户操作的登录名,主控制器附加了[Authorize]属性,强制将立即登录名重定向到Azure AD.我未在任何Authorize属性中使用角色.
I'm developing an MVC .NET 5 web app for Office 365 and am using the OpenIDConnect framework. I have set up OWIN (3) and ADAL(2) and my Azure AD Application. There is no user actioned login, the home controller has an [Authorize] attribute attached, forcing the immediate login redirect to Azure AD. I am not using roles in any of my Authorize attributes.
问题:我可以成功登录我的应用程序-一次!首次登录后,我关闭浏览器(或在其他计算机上打开新的浏览器),然后再次点击该应用程序.它将我重定向到我登录的Azure AD登录屏幕,然后连续在应用程序和Azure之间重定向,直到我收到臭名昭著的400个标题以解决长期问题.查看cookie存储区,我发现其中充满了随机数.我检查了缓存(Vittorio的EFADALCache配方,尽管发现此问题时我使用的是TokenCache.DefaultShared),并且它具有数百行缓存数据(只有成功登录后生成的一行).
The Problem: I can log in to my applications successfully - ONCE! After the first login, I close the browser (or open a new browser on a different machine) and I hit the app again. It redirects me to the Azure AD login screen which I sign into and then it continuously redirects between the app and Azure until I get the infamous 400 headers to long issue. Looking into the cookie store, I find that it's full of nonces. I check the cache (Vittorio's EFADALCache recipe, although I was using the TokenCache.DefaultShared when this problem was discovered) and it has hundreds of rows of cache data (Only one row generated with a successful sign in).
当重定向通过输出窗口发生时,我看到每次往返都在生成一个新的访问和刷新令牌:
I can see as the redirects occur via the output window that a new access and refresh token is being generated each round trip:
Microsoft.IdentityModel.Clients.ActiveDirectory Verbose: 1 : 31/07/2015 12:31:52: 15ad306e-e26d-4827-98dc-dea75853788a - AcquireTokenByAuthorizationCodeHandler: Resource value in the token response was used for storing tokens in the cache
iisexpress.exe Information: 0 : 31/07/2015 12:31:52: 15ad306e-e26d-4827-98dc-dea75853788a - AcquireTokenByAuthorizationCodeHandler: Resource value in the token response was used for storing tokens in the cache
Microsoft.IdentityModel.Clients.ActiveDirectory Information: 2 : 31/07/2015 12:31:52: - TokenCache: Deserialized 1 items to token cache.
iisexpress.exe Information: 0 : 31/07/2015 12:31:52: - TokenCache: Deserialized 1 items to token cache.
Microsoft.IdentityModel.Clients.ActiveDirectory Verbose: 1 : 31/07/2015 12:31:52: 15ad306e-e26d-4827-98dc-dea75853788a - TokenCache: Storing token in the cache...
iisexpress.exe Information: 0 : 31/07/2015 12:31:52: 15ad306e-e26d-4827-98dc-dea75853788a - TokenCache: Storing token in the cache...
Microsoft.IdentityModel.Clients.ActiveDirectory Verbose: 1 : 31/07/2015 12:31:52: 15ad306e-e26d-4827-98dc-dea75853788a - TokenCache: An item was stored in the cache
iisexpress.exe Information: 0 : 31/07/2015 12:31:52: 15ad306e-e26d-4827-98dc-dea75853788a - TokenCache: An item was stored in the cache
Microsoft.IdentityModel.Clients.ActiveDirectory Information: 2 : 31/07/2015 12:31:52: 15ad306e-e26d-4827-98dc-dea75853788a - AcquireTokenHandlerBase: === Token Acquisition finished successfully. An access token was retuned:
Access Token Hash: PN5HoBHPlhhHIf1lxZhEWb4B4Hli69UKgcle0w7ssvo=
Refresh Token Hash: 3xmypXCO6MIMS9qUV+37uPD4kPip9WDH6Ex29GdWL88=
Expiration Time: 31/07/2015 13:31:51 +00:00
User Hash: GAWUtY8c4EKcJnsHrO6NOzwcQDMW64z5BNOvVIl1vAI=
发生问题时,我的OpenIdConnectAuthenticationOptions中的AuthorizationCodeReceived通知被命中,因此我知道Azure认为登录成功(否则将不会重定向回应用程序):
The AuthorizationCodeReceived notification in my OpenIdConnectAuthenticationOptions is being hit when the problem is happening, so I know that Azure thinks the login was successful (or else the redirect back to the app wouldn't occur):
private static void PrepO365Auth(IAppBuilder app)
{
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
app.UseCookieAuthentication(new CookieAuthenticationOptions());
//Configure OpenIDConnect, register callbacks for OpenIDConnect Notifications
app.UseOpenIdConnectAuthentication(
new OpenIdConnectAuthenticationOptions
{
ClientId = ConfigHelper.ClientId,
Authority = authority,
PostLogoutRedirectUri = "https://localhost:44300/Account/SignedOut",
RedirectUri = "https://localhost:44300/",
Notifications = new OpenIdConnectAuthenticationNotifications
{
AuthorizationCodeReceived = (context) =>
{
ClientCredential credential = new ClientCredential(ConfigHelper.ClientId, ConfigHelper.AppKey);
string signedInUserID = context.AuthenticationTicket.Identity.FindFirst(ClaimTypes.NameIdentifier).Value;
AuthenticationContext authContext = new AuthenticationContext(authority, new EFADALTokenCache(signedInUserID)); // TokenCache.DefaultShared Probably need a persistent token cache to handle app restarts etc
AuthenticationResult result = authContext.AcquireTokenByAuthorizationCode(
context.Code, new Uri(HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Path)), credential, ConfigHelper.GraphResourceId);
return Task.FromResult(0);
},
AuthenticationFailed = context =>
{
context.HandleResponse();
context.Response.Redirect("/Error/ShowError?signIn=true&errorMessage=" + context.Exception.Message);
return Task.FromResult(0);
}
}
});
}
}
在发现问题后,我用继承自AuthorizeAttribute的Auth属性替换了Authorized属性,以便尝试进入Authorize代码并查看发生了什么.我从MVC 5的源代码的第5版构建了一个PDB文件,但是所有发生的是,它跳回到了我自己的代码中:(话虽如此,我已经覆盖了我所能找到的 filterContext .HttpContext.User.Identity.IsAuthenticated 为false,这是有道理的,因为这将导致重定向回Azure登录.
I have replaced (after discovering the problem) the Authorized attribute with my own Auth attribute, inheriting from AuthorizeAttribute, just so I could try and step into the Authorize code and see what's happening. I built a PDB file from the version 5 version of MVC 5's source code, but all that happens is that it jumps back into my own code :( That being said, I've overridden what I could and have found that filterContext.HttpContext.User.Identity.IsAuthenticated is false, which makes sense, as that would cause the redirect back to Azure sign in.
所以,我知道:
- Azure正在接受我的登录并返回相关令牌
- 在第二次登录时,在OnAuthorization之前,filterContext.HttpContext.User.Identity.IsAuthenticated返回false
- 我的Azure应用程序配置很好,或者根本无法进行身份验证
我认为:
- MVC身份设置中存在某些错误. Azure运行正常,或者根本无法进行身份验证.
- 这不是Cookie的问题,因为如果您在其他计算机上进行第二次登录,则会出现问题
对不起,这有点麻烦,但是其中有很多无限重定向问题,我需要解释一下为什么我的情况与众不同!
I'm sorry this is a bit long winded, but there are so many of these infinite redirect issues out there, I needed to explain why my situation was different!
我正在寻找(如果没有答案!)正在朝着正确的方向推动我如何进一步调试.
What I'm looking for (if not an answer!) is a push in the right direction as to how I can debug further.
感谢您可以提供的任何帮助!
Appreciate any help you can give!
安迪
推荐答案
找到了有兴趣的人的答案.这是Katana中的一个已知错误,其中Katana cookie管理器和ASP .NET cookie管理器会相互冲突并覆盖彼此的cookie.完整的详细信息和解决方法在这里:
Have found the answer for anyone interested. It's a known bug in Katana where the Katana cookie manager and the ASP .NET cookie manager clash and overwrite each other's cookies. Full details and workaround here:
现在可以在 Microsoft.Owin.Host中找到下面显示的SystemWebCookieManager. .SystemWeb Nuget程序包.
The SystemWebCookieManager shown below can now be found in the Microsoft.Owin.Host.SystemWeb Nuget package.
添加CodePlex死亡时的代码:
Adding the code for when CodePlex dies:
//stick this in public void ConfigureAuth(IAppBuilder app)
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
// ...
CookieManager = new SystemWebCookieManager()
});
//And create this class elsewhere:
public class SystemWebCookieManager : ICookieManager
{
public string GetRequestCookie(IOwinContext context, string key)
{
if (context == null)
{
throw new ArgumentNullException("context");
}
var webContext = context.Get<HttpContextBase>(typeof(HttpContextBase).FullName);
var cookie = webContext.Request.Cookies[key];
return cookie == null ? null : cookie.Value;
}
public void AppendResponseCookie(IOwinContext context, string key, string value, CookieOptions options)
{
if (context == null)
{
throw new ArgumentNullException("context");
}
if (options == null)
{
throw new ArgumentNullException("options");
}
var webContext = context.Get<HttpContextBase>(typeof(HttpContextBase).FullName);
bool domainHasValue = !string.IsNullOrEmpty(options.Domain);
bool pathHasValue = !string.IsNullOrEmpty(options.Path);
bool expiresHasValue = options.Expires.HasValue;
var cookie = new HttpCookie(key, value);
if (domainHasValue)
{
cookie.Domain = options.Domain;
}
if (pathHasValue)
{
cookie.Path = options.Path;
}
if (expiresHasValue)
{
cookie.Expires = options.Expires.Value;
}
if (options.Secure)
{
cookie.Secure = true;
}
if (options.HttpOnly)
{
cookie.HttpOnly = true;
}
webContext.Response.AppendCookie(cookie);
}
public void DeleteCookie(IOwinContext context, string key, CookieOptions options)
{
if (context == null)
{
throw new ArgumentNullException("context");
}
if (options == null)
{
throw new ArgumentNullException("options");
}
AppendResponseCookie(
context,
key,
string.Empty,
new CookieOptions
{
Path = options.Path,
Domain = options.Domain,
Expires = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc),
});
}
}
我也做了一个要点: https://gist.github.com/irwinwilliams/823f43ef8a5e8019a95874049dbb8b00
这篇关于第二次成功登录后,第二次登录会导致无限重定向循环MVC .NET 5 OWIN ADAL OpenIDConnect的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!