I'm reviewing an application currently experiencing problems with authentication (forms authentication is used combined with a custom way to retrieve the current user's profile) and I've noticed that the user's identity is retrieved using different methods:
Thread.CurrentPrincipal.Identity (on some http modules)
HttpContext.Current.User.Identity (on some http modules and also pages)
Page.User.Identity (on pages)
Is it safe to assume that the same value will always be returned by all methods?
HttpContext.Current.User.Identity (on some http modules and also pages)
Page.User.Identity (on pages)
Both of them return an Instance of IPrincipal
Page.User uses the HttpContext object's User property to determine where the request originates
The best methos is HttpContext.Current.User
Thread.CurrentPrincipal.Identity won't show the right user if you use the Impersonation
and it will give you the windows user details instead
The one we usually use is HttpContext.Current.User.Identity
Related
Using Owin External Authentication in an MVC application, how can a user Sign Out of my application and sign back in with a different external account? AuthenticationManager.SignOut() successfully signs the user out of my application, however, if they visit the external login page again they are just instantly signed back in as the same user.
In a system where one person may have multiple external accounts, how can this be accomplished without having to close the browser? Are there some sort of Cookie or authentication options that will let the user choose a different account on the external sign in page?
You have to specify the Authentication Type in the Sign Out method, otherwise only the browser cookie will be destroyed.
If the user could have multiple external logins, you can loop through the Authentication Types you have configured in your Startup.Auth.cs and add them to a list that is then provided to the AuthenticationManager SignOut method.
var authTypes = AuthManager.GetAuthenticationTypes().ToList();
var authTypeNames = new List<string>();
foreach (var authType in authTypes)
{
if (!authTypeNames.Contains(authType.AuthenticationType))
authTypeNames.Add(authType.AuthenticationType);
}
AuthManager.SignOut(authTypeNames.ToArray());
Here I am getting all Authentication Types from the Authorisation Manager (I'm using AutoFac to get the instances provided to the controller). Since this method gives you several duplicate authentication types (eg. Bearer) I am looping the types and adding each distinct one to a list. I then convert the list to an array and call the Authentication Manager SignOut method which will sign the user out of all authentication types, including local and external cookies, and external providers.
I have in my first ZF1 application two controllers : AuthController et ProductController.
My code for the authentication work perfectly by using Zend_Auth.
But the user still can access in the application in the browser without authentication. For example if the user enter :
http://localhost/apptest/public/product/action
he can access directly. Must I use Zend_Session or Zend_Acl to block access if the user is not login?
Thanks.
Zend_Auth is concerned only with authentication and not with authorization. Authentication is loosely defined as determining whether an entity actually is what it purports to be (i.e., identification), based on some set of credentials. Authorization, the process of deciding whether to allow an entity access to, or to perform operations upon, other entities is outside the scope of Zend_Auth. For more information about authorization and access control with Zend Framework, please see Zend_Acl.
I want to create a WebAPI service for use in my single page application but I also want it to be available for a mobile application too.
When users are using the SPA they are signed in using forms authentication and have a session cookie but if they're using the mobile application this wont be the case.
Is it possible to expose the same API controller as 2 different endpoints where one is authenticated using mutual SSL, a token or as a last resort basic auth and the other uses the session cookie?
For example take the following controller:
public class TodoController :
{
public IQueryable<TodoModel> GetTodos()
{
...
}
}
Can I add multiple routes that map to the same method?
https://myapp.example.org/api/todo
https://myapp.example.org/mutual-auth/api/todo
I want to configure IIS to use mutual SSL for the mutual auth endpoint and use forms authentication for the other endpoint.
Short answer: yes
This is a very broad question, so I won't go into excessive detail about every aspect. I think you should also take a look at BreezeJS because it makes things building these applications significantly easier.
DESIGN
Do you want to build in pure HTML and JavaScript or incorporate CSHTML? The decision is yours, but if you want to eventually create native-based applications using something such as PhoneGap Build, you'll want to stick to pure HTML and JavaScript so that you can compile the code later.
Do you want to use another JS library such as BreezeJS to make life a little easier when designing your controllers? Out of the box, your Web API controllers will be prefixed with api/{controller}/{id} in WebApiConfig. You may want to add {action} routing if you don't go with something like BreezeJS so that you can have more flexibility with your controllers.
Lastly, let's talk about the Repository Pattern and Unit of Work Pattern. This is a bit of hot-topic, but I find that usually creating a repository allows you a great deal of flexibility and it's great for dependency injection. Adding an additional repository layer to your controllers allows you to differentiate between different users or means of access such as a SPA or mobile application very easily. You can use the exact same controllers, but simply draw from different repositories.
SECURITY
You'll want to touch up a bit on [Authorize], [ValidateHttpAntiForgeryTokenAttribute], [Roles("")], and several other data annotations for starters. This is a huge topic which has a ton of reading material online -- invest in some research. Your controller can have multiple actions which have varying limitations on them, such as preventing CSRF on the SPA, but be less restricted on Mobile by either utilizing varying actions on the controller or drawing from separate repositories.
Can I add multiple routes that map to the same method?
https://myapp.example.org/api/todo
https://myapp.example.org/mutual-auth/api/todo
Yes, absolutely. You'll just have to do some extra work with your routing configuration files. With BreezeJS, you get access to not only /api/ but /~breeze/ which works very similarly.
You can secury your Web API using the way you want. For exemple, you can provide a custom Message Handler or a custom Authorization Filter to provide external authentication via token.
There's a full session from the ASP.NET Team that covers this, you just need to choose which one you will pick up:
Security issues for Web API.
Assuming you are hosting web API in IIS, if you enable the forms authentication, FormsAuthenticationModule establishes the identity. That is, if you look at HttpContext.Current.User or Thread.CurrentPrincipal after a successful authentication, the object of type IPrincipal will have the identity (which is FormsIdentity) and the IsAuthenticated property will be set to true. You can do the same thing for any other credential using a custom DelegatingHandler. All you need to do is to validate the credential (token, user id and password in basic scheme in HTTP authorization header or whatever) and set the HttpContext.Current.User and Thread.CurrentPrincipal to an object of type GenericPrincipal with GenericIdentity. After this, the same action method of a controller which is decorated with Authorize will work for both types of requests.
I have an MVC 3 application which is to be used for both anonymous and authenticated users.
This is accomplished by configuring IIS authentication mode to enable both anonymous and windows authentication, and then setting the authentication mode web.config setting to "Windows" and applying a custom authorization attribute selectively to actions that require the authentication check.
The issue is that in some actions I don't need to apply the attribute (so anonymous users can access it too), but in the case that an admin user is browsing it, then I want to retrieve his User.Identity.Name value.
The application is behaving unpredictably, in some instances, once the user has been authenticated in a previous action, then the User.Identity.Name property remains available for the rest of the user's session. However, in other instances, it's coming up as an empty string.
So, how do I actually tell the application to "go and authenticate this user"? If the Authorize attribute can force the authentication of the user, then how can I achieve this same effect on demand within an action?
thanks for you help,
M
If the Authorize attribute can force the authentication of the user,
then how can I achieve this same effect on demand within an action?
By doing the same as the AuthorizeAttribute does:
return new HttpUnauthorizedResult();
I'm new to the whole client-side SPA world. I'm using the above technologies, which seem quite promising. However, one huge snag that I can't get over easily is the lack of built-in security. I had to manually roll out the user authorization, which IMHO should be part of the framework.
Now that I have that sorted, I'm getting major headaches with vertical security: where one user is logged in but can easily access other users' info by changing a few parameters in the browser console. I could pass the userId with every call and then compare it with the one on the server, but I was hoping that there would be an overarching solution that doesn't pollute the breeze data calls with user ids.
For example, let's say there's a call from the data service like this:
function getItems(){
var query = breeze.EntityQuery.from('Items').expand("Person");
return manager.executeQuery(query);
}
this will get all the items, not good. So let's limit by userId:
function getItems(userId){
var query = breeze.EntityQuery.from('Items').where("userId", "==", authentication.userId).expand("Person");
return manager.executeQuery(query);
}
in the second example, we get the userId from the authentication service, which stored the userId when the user was logged in. However, a malicious user can easily go the browser console and change that value.
Of course, I could pass the userId using withParameters(...) and compare it with the current one on the server, but I'd have to do that for every call, which doesn't seem right. Is there a better way to secure calls with the trusted user id?
#Ali - I understand your pain and your concern. You are right to fear any form of so-called security that relies on information passed in the URL. Fortunately there are excellent answers to your concerns and Breeze apps work well with them.
For example, have you studied the ASP.NET Breeze/Knockout Template? It uses Forms Auth for authentication and guards the Web API controller with an [Authorize] attribute. Only logged-in users can access any of the controller methods.
That authentication also sets the IPrincipal which the Web API controller makes available through its User property. You'll see User passed to the constructor of the TodoRepository. In that repository you'll find guard logic to restrict query and saves to just the Todo information belonging to the requesting user.
Look at the network traffic. You won't find any user identifying information in the URL or the request/response bodies. You will see an encrypted authentication cookie in a header.
An obvious flaw in the example is that the client/server traffic takes place in the clear. You must add transport level security (HTTPS) before you go to production. But this is a demo after all.
Why not just do this in the controller?
If the Web Api is secured with [Authorize] then you can get the users ID in the controller and make sure that the data returned is for the currently logged in user.