I have configured a .NET MVC application to authenticate against a separately running Identity Server (IdentityServer3). I have configured OpenIdConnectAuthenticationNotifications.SecurityTokenValidate() to place the user's claims into the AuthenticationTicket. Everything seems to be working as expected. The first time I access a page in the MVC app I get the Log In screen and after logging in I am redirected to the requested page.
But, when I look at the HttpContext.User (using a breakpoint in my override of CheckAccessAsync()) it has 2 identities. Looking closer I can see that both identities are the same, and that accessing the Claims property returns all of the claims twice.
Any ideas what I might be doing wrong?
I believe I have figured out what this issue is. I had configured the Authentication Server and the MVC app to use the same client, which actually caused other problems.
When I changed the Authentication Server to use its own client, the HttpContext.User in the MVC app still has 2 Identities but the Claims collection are not duplicated. I'm guessing that the Claims collection only contain the claims for the client that is accessing the collection. But I be totally sure since both clients return the same Claims collections.
Related
I would like to add additional Azure AD attributes as Claims to a ClaimsPrincipal created by the "out-of-the-box" ASP.NET MVC template (i.e. app.UseOpenIdConnectAuthentication(...))
I tried implementing something similar in the SecurityTokenValidated notification as shown in this article, however it seems I'm running into a bit of a chicken-and-egg problem with my scenario:
I need to call the Graph API to get the additional user attributes for the Claims, but I don't have the token yet (I don't think) at this point in the process to be able to call the API.
Seems like I'm missing something obvious here.
You have many solutions here, but two stand out:
In securitytokenvalidated you do have a token, the one sent to your app for sign in purposes. You can use it in an onbehalfof flow to get a token for the graph, and use it right within that notification. You can refer to the sample here, it's for web API but the concept is the same
You can configure your app to access the graph with its own application identity. You can get that token at any time, then. See here
I am running an MVC site along side Umbraco. The MVC site handles its own authentication completely separate to Umbraco, and ASP.NET Forms authentication for that matter. It sets a cookie and uses that internally to keep track of things.
Everything works fine for the most part, but if I am logged into my MVC site with the aforementioned cookie set, I try to login to the Umbraco admin section using the correct Umbraco credentials, it authenticates me and redirects me to the admin section but the WebAPI calls start to fail. The first is a call to: /umbraco/backoffice/UmbracoApi/UpdateCheck/GetCheck which returns a 417 Missing token null HTTP error response.
If I delete my custom cookie and refresh the page everything works fine.
I don't understand how my cookie can interfere with Umbraco's. It's not using ASP.NET Forms authentication or anything.
This error occurs because your request is not sending up the required angular CSRF headers + cookie. I'm not sure why this would be the case but it does seems strange if it is a fault of your custom cookie. Perhaps you can tell us some more information about your issue: Cookie name/value, steps to reproduce, specific version of Umbraco, hosting environment, etc....
Some info as to what is going on, the code that returns this error is here:
https://github.com/umbraco/Umbraco-CMS/blob/dev-v7/src/Umbraco.Web/WebApi/Filters/AngularAntiForgeryHelper.cs#L94
This is where the CSRF cookies are set:
https://github.com/umbraco/Umbraco-CMS/blob/dev-v7/src/Umbraco.Web/WebApi/Filters/SetAngularAntiForgeryTokensAttribute.cs
and this attribute is applied to two actions, one for login and one when we retrieve the current user data:
https://github.com/umbraco/Umbraco-CMS/blob/dev-v7/src/Umbraco.Web/Editors/AuthenticationController.cs#L103
https://github.com/umbraco/Umbraco-CMS/blob/dev-v7/src/Umbraco.Web/Editors/AuthenticationController.cs#L84
This is where the header is set in the JS:
https://github.com/umbraco/Umbraco-CMS/blob/5b9a98ad6ae9e63322c26f7b162204e34f7fcb54/src/Umbraco.Web.UI.Client/src/init.js#L11
Depending on your hosting environment/setup there has been strange reports of some firewalls stripping/changing data, for example:
http://our.umbraco.org/forum/umbraco-7/using-umbraco-7/47340-Umbraco-7-plus-ISA-Server-2006
Hopefully given the info above you might be able to pinpoint where the problem starts.
My initial thought is that you by accident used a key value for your cookie that is reserved by Umbraco, which could result in the wrong cookie being read, causing issues. The solution to this would be to simply rename your cookie.
If this is not the case I have another theory:
HTTP requests will always include all cookies which path/domain matches the domain of the resource you are requesting. They are sorted by path length primarily, and secondarily by creation time. If Umbraco backend for some reason finds the cookie used for authentication by its index number (wouldn't even be surprised) in the list, rather than key value, your custom cookie would cause the index to shift, thus making Umbraco look at the wrong cookie
So, if renaming the cookie didn't do anything, a fun thing to try could be to set path of the cookie to the shortest possible path, which would make your browser put the cookie further down the list, so the index won't shift.
It's just a theory though, so I'm interested in hearing how it goes :)
I've got an MVC app that normally works fine, but on a particular server, it's returning a 401.0 "The authenticated user does not have access to a resource needed to process the request" error.
Normally it works like this:
User logs into a separate application, gets a user ID and token, clicks a link into this application. User ID and token go into the URL.
User gets into my application with Anonymous auth, and then in our LogonAuthorize filter, we get the ID and token from the query string to authenticate the user.
I have logging in the filter, and I can see the user getting authenticated. So, they're making it at least that far. However, instead of the page they're supposed to see, there's a 401.0 Unauthorized error from IIS.
Things I have tried:
Giving IUSR access to the directory
Running mirate.exe (it's an Entity Framework app)
Removing all [Authorize] attributes in the solution... I know that we make it as far as the Initialize() event of my BaseController object. We don't seem to make it into the specific controller actions, such as Home/Index, which inherits BaseController. I don't see any logging after BaseController.Initialize().
Giving Network Service access to the directory
Switching the App Pool from Integrated to Classic (I get a blank screen instead of a 401.0 error, which is odd. Same authentication stuff in the logs.)
Using a local user account instead of Network Service with the app pool, giving that account access to the directory
Setting different accounts to be used by "Anonymous"
Rebuilding and redeploying the app (several times)
Different authentication schemes: Turning on Windows auth gives a 401.1, turning off all of them gives a 401.2
Making sure Global.asax is in the right place
aspnet_regiis -i
Tearing all my hair out (counterproductive)
I set up a tracing rule for this error, and I have a trace, but I have no idea how to read it. I would paste it here, but it's a pretty long XML file.
The error comes from module ManagedPipelineHandler, notification ExecuteRequestHandler, handler System.Web.Mvc.MvcHandler, with error code 0x00000000.
One detail: This server is configured to use port 90 instead of port 80. I'm not sure why that would cause problems, but maybe it would?
One other detail: The app in question is running as an application in a virtual directory underneath the "main" application, which is configured as the root website.
One new detail: This server is Windows Server 2008 R2, and was upgraded from Windows Server 2003. I believe something in the upgrade process may account for the issue, as none of the "usual suspect" solutions to this type of problem have helped.
So you have found the solution but seeking clarification why it worked. This can be one of the scenario.
Seems your website/web application was hosted through specific user credentials that was expired. Next time when you remove & add windows authentication through new credentials or application pass through it worked.
I face similar situation in one of our test web application that is hosted using specific user Path Credentials. Each time user password is changed/expired. Web application stops working.
Windows authenticates first with Kerberos. Next it attempts other authentication methods. Your requirement was NTLM. Turning off all but Windows Authentication forced the application to attempt NTLM which succeeded.
It seems that the solution here was to turn on Windows auth and turn off every other form of authentication, which is counterintuitive. But there you go... that's what made it work.
If someone wants to post an answer explaining WHY that was the answer for me, I'll award them the bounty.
I've got an app built using asp.net mvc and deployed over 2 Amazon EC2 instances. I'm using forms authentication to authenticate users. I simply make a quick look up on the given username and password and if I found a match I set an authentication cookie, like so:
if(_repository.Login(username, password))
FormsAuthentication.SetAuthCookie(username, false);
This works fine as long as the application on one machine, but, once I leveraged Amazon Elastic Load Balancing to deploy the site on two machines, the site behaves in a very weird way. When a user logs in, the site recognizes a logged in user, after a refresh or two, the site no longer see the user as a logged in user. If the user keeps refreshing again for some time, the app sees the user as a logged in user again, and this goes forever.
I'm aware that such a problem might occur if I'm storing SessionState inproc. I'm not using SessionState at all.
What am I missing here guys?
Ps: I've edited the session state to be stored on a state server [Though i'm not using neither sessions nor TempData anywhere on my app] and the same weird behavior is there.
You need to synchronize your <machinekey> between all servers in your farm. Otherwise the forms authentication ticket is only good for the machine which issued it. I doubt this has anything to do with Session/TempData.
I'm trying to use forms.signout but sometimes it does not log out the user and he still can navegates through the website.
How can I resolve this? I also configured web.config forms authentication, but it's still not working.
I'm using FormsAuthentication to autenticate an user passing he's login.
Thanks!!
I don't know what the cause is but a few things you might consider/try
are they actually able to still visit pages generated by the server or are they just going back to locally cached versions? What happens when they cause a postback that has code to check if they are authenticated does that work or does it fail? I think the later meaning they are signed out but viewing cached versions of the logged in page in which case you want to instruct the client not to cache the pages using for instances:
Response.Cache.SetExpires(DateTime.UtcNow.AddMinutes(-1));
Response.Cache.SetCacheability(HttpCacheability.NoCache);
Response.Cache.SetNoStore();
You can try manually setting the cookie to be expired but this is a hack
FormsAuthentication.SignOut();
Context.Response.Cookies.Item(FormsAuthentication.FormsCookieName).Expires = Date.Now;
Response.Redirect("~/Somewhere.aspx");
Does the user have the domain (or a parent domain) in their trusted sites or intranet sites? I've run into some issues recently where a user is authenticated, but anonymous under circumstances where this is true. In my case it could also be that a parent site was, at one time, configured to allow windows integrated authentication. I've removed since removed that, but it didn't seem to help the problem. I haven't yet restarted IIS to see if this would have an effect. I've resorted to checking both that the user is authenticated and non-anonymous to ensure that the proper parts of the view are rendered. This is actually more accurate even though my login code should prevent having an anonymous login.