My MVC application is secured using Forms Authentication. I have a global filter to which applies the AuthorizeAttribute.
I have a controller called Development with an action called Report. I can access this fine by authenticating in the normal way and going to http://localhost:8080/Development/Report. If I am not authenticated then it redirects me to the Forms Authentication login.
I am trying to embed this page into an iOS app so that a user can view the information without having to manually authenticate themselves. To confuse things the iOS app uses a different authentication system, however it holds a device ID and a unique token which my MVC app also store.
What I am trying to do is make the Report action available both via Forms Authentication and from the iOS app using basic authentication where the username will be the device ID and the password will be the token. It's really important that when authenticated using this method the user can only access the Report action. What's the best way to implement this whilst keeping everything secure?
I was thinking of marking the Report action with the AllowAnonymous attribute and then creating a custom authentication just for this action. Is this the best way?
Authentication strategies are just that: strategies. They're not intended to be mixed and matched; you pick one that best suits your application and go with it.
That said, I see two ways forward. Either way, however, will not allow you to use the same action for everything. Your best bet is to factor out shared code into a utility class or similar.
Put the two actions in separate projects. Then each project can implement its own auth strategy. Again, similar code can be factored out into a utility class, and in this case, shared via a class library that both projects may reference.
Create a separate action in the same project and don't use Authorize on it or use AllowAnonymous if it's part of a controller that is authorized. This will essentially turn off the standard auth for this action and provide no protection. However, you're now freed up to do your own "authorization" manually. You can either check the values of device ID and token directly in the action or create an action filter that does so. Which you choose depends on how frequently you need to do this. If this is a one-off you might just want to check directly in the action as that will be quicker and easier. However, if it is one-off you may still want to use an action filter just so you're prepare should its use become more widespread.
Related
I'm mid-way through a task to migrate a legacy .NET MVC app to use Single Sign On (SSO) to make integration with a to-be-developed mobile app possible. I'm planning on using Azure AD B2C to facilitate this and based on my researched, I need to use custom policies to achieve the required functionality.
Work on this migration is proceeding very slowly. I'm finding the custom policy XML very clunky to work with. It's going to take quite some time to achieve parity with the existing system given the current velocity. I'm wondering whether it would be wise to sidestep a lot of the migration headaches by using the Microsoft Graph API in place of custom policies.
Take registration for example. It appears common to redirect the user to a SignUp.xml custom policy (or the integrated SignUpOrSignIn.xml) to handle adding the user record in the AD B2C data store. Part of this policy would involve calling a REST API to create a corresponding record for this user in the app's database (stores email settings and such). Instead of using these custom policies, my plan would be to instead take the existing registration process and simply add a step which creates the user record on the B2C side using the Microsoft Graph API.
It appears like most things I need may be achieved using the Microsoft Graph API. Things I'd need that I can see are not available are:
logging in to a user account and;
sending verification emails
Are there any other common authentication-related tasks I'm likely to need that couldn't be achieved using the Graph API?
As far as downsides, the fact I'd be handling user passwords (even if it was just to create the user and nothing else) is an obvious concern, but perhaps acceptable. The main thing I'm after is a simple SSO solution that generates secure access tokens (incl. handling reset tokens, etc). I hope then, that this could be a feasible option.
You will miss out on password reset, profile edit, SSO and token expiration etc.
A better way may be to use the base custom policies and achieve a lot of what you need by having the policy call REST API's.
What is your use case?
I have a shopping cart application built using Javascript (ReactJS). The app will all listing products, adding them to cart and performing a checkout.
When a user arrives at the site, the APIs will be invoked by the Javascript client to obtain Product Listing, Categories etc. When someone clicks on a Product, the APIs will also provide Product details.
At no point do I require the User to log on to the system. I cannot also keep my API open. We are using IdentityServer4 to manage the APIs.
I can't use Client Credentials flow here (which is suited for Machine-to-Machine flows) because I can't keep secrets in Javascript.
I can't use Implicit Flow because it works on the principal of User Login, whereas I don't need the User to login at all.
What flow should I use? Is there a way to change the implicit flow to work without requiring a user login?
Would using an API Key be a better approach?
Any feedback would be awesome.
You can't change the implicit flow, it is literaly an user login flow.
I think you need to think about what you want to protect here.
You need to allow everybody ( anonymous) to call some methods: f.e. GetProduct.
You need to secure the sensitive methods with login requirements like checkout.
This is one MVC application and we are using FormsAuthentication
FormsAuthentication.SetAuthCookie(userName, model.RememberMe);
We would to maintain log of the users who are accessing the system (For analysis how often one user is accessing the system)
We can catch it while authorizing them through the login page. But as application provides “Remember Me” option which remember the password so in-case one user press it today and access the system tomorrow again we won’t capture.
There are some alternatives which we are thinking (Except removing remember me) but I wonder is there any best way for it?
We just to need to capture day wise data. Like User A last time access on date?
Best Regards.
A better place to log authenticate requests is either in a Httpmodule or ActionFilter in ASP.Net MVC. You can get User information from the HttpContent.User and also his cookies information from HttpContext.Request.Cookies
In the following example, even though the user checks the remember me, this HttpModule will invoke and checks for HttpContext. This is a good place to keep track of returning users - ASP.Net HttpModule for Security
The similar feature can be achieved using ActionFilters which is specific to MVC - Authentication using ActionFilter
I'm using ASP.NET MVC and I am trying to separate a lot of my logic. Eventually, this application will be pretty big. It's basically a SaaS app that I need to allow for different kinds of clients to access. I have a two part question; the first deals with my general design and the second deals with how to utilize in ASP.NET MVC
Primarily, there will initially be an ASP.NET MVC "client" front-end and there will be a set of web-services for third parties to interact with (perhaps mobile, etc).
I realize I could have the ASP.NET MVC app interact just through the Web Service but I think that is unnecessary overhead.
So, I am creating an API that will essentially be a DLL that the Web App and the Web Services will utilize. The API consists of the main set of business logic and Data Transfer Objects, etc. (So, this includes methods like CreateCustomer, EditProduct, etc for example)
Also, my permissions requirements are a little complicated. I can't really use a straight Roles system as I need to have some fine-grained permissions (but all permissions are positive rights). So, I don't think I can really use the ASP.NET Roles/Membership system or if I can it seems like I'd be doing more work than rolling my own. I've used Membership before and for this one I think I'd rather roll my own.
Both the Web App and Web Services will need to keep security as a concern. So, my design is kind of like this:
Each method in the API will need to verify the security of the caller
In the Web App, each "page" ("action" in MVC speak) will also check the user's permissions (So, don't present the user with the "Add Customer" button if the user does not have that right but also whenever the API receives AddCustomer(), check the security too)
I think the Web Service really needs the checking in the DLL because it may not always be used in some kind of pre-authenticated context (like using Session/Cookies in a Web App); also having the security checks in the API means I don't really HAVE TO check it in other places if I'm on a mobile (say iPhone) and don't want to do all kinds of checking on the client
However, in the Web App I think there will be some duplication of work since the Web App checks the user's security before presenting the user with options, which is ok, but I was thinking of a way to avoid this duplication by allowing the Web App to tell the API not check the security; while the Web Service would always want security to be verified
Is this a good method? If not, what's better? If so, what's a good way of implementing this. I was thinking of doing this:
In the API, I would have two functions for each action:
// Here, "Credential" objects are just something I made up
public void AddCustomer(string customerName, Credential credential
, bool checkSecurity)
{
if(checkSecurity)
{
if(Has_Rights_To_Add_Customer(credential)) // made up for clarity
{
AddCustomer(customerName);
}
else
// throw an exception or somehow present an error
}
else
AddCustomer(customerName);
}
public void AddCustomer(string customerName)
{
// actual logic to add the customer into the DB or whatever
// Would it be good for this method to verify that the caller is the Web App
// through some method?
}
So, is this a good design or should I do something differently?
My next question is that clearly it doesn't seem like I can really use [Authorize ...] for determining if a user has the permissions to do something. In fact, one action might depend on a variety of permissions and the View might hide or show certain options depending on the permission.
What's the best way to do this? Should I have some kind of PermissionSet object that the user carries around throughout the Web App in Session or whatever and the MVC Action method would check if that user can use that Action and then the View will have some ViewData or whatever where it checks the various permissions to do Hide/Show?
What you propose will not work. Actions can be cached, and when they are, the action (and hence your home-rolled security) does not run. ASP.NET membership, however, still works, since the MVC caching is aware of it.
You need to work with ASP.NET membership instead of trying to reinvent it. You can, among other things:
Implement a custom membership provider or role provider.
Subtype AuthorizeAttribute and reimplement AuthorizeCore.
Use Microsoft Geneva/Windows Identity Foundation for claims-based access.
Also, I completely disagree with ChaosPandion, who suggests making structural changes in your code before profiling. Avoiding exceptions for "performance" reasons is absurd -- especially the idea that the mere potential to throw an exception for invalid users will somehow tank the performance for valid users. The slowest part of your code is likely elsewhere. Use a profiler to find the real performance issues instead of jumping on the latest micro-"optimization" fad.
The correct reason to avoid exceptions for authorizations is that the correct way to indicate an attempt at unauthorized access in a web app is to change the HTTP status code to 401 Unauthorized, not throwing an exception (which would return 500).
Define your authorisation requirements as a domain service so they are available to both the web and web service implementations.
Use an authorisation filter to perform your authorisation checks within the web application, this should be as simple as creating an auth request object and then passing it to your auth domain service.
If the authorisation fails, return the correct error - a 401 as indicated by Craig Stuntz.
ALWAYS authorise the action. If you can hide the link to unauthorised users - thats nice.
Simplify your views / view logic by writing a HtmlHelper extension method that can show / hide things based on a call to the auth domain service.
To use your authorisation service from the web service is simply a matter of constructing the auth request object from something passed in via the service message instead of from a cookie passed by the users browser.
I'm building a .Net MVC app, where I'm using one particular view to generate an internal report. I don't want the users of the site to gain access to this page at all.
I've a console app that fires every so often which will scrape some of the details from this page by hitting it's URL.
I don't like the idea of having the URL hanging out there but I'm not sure of another way to go about it.
Thoughts on what might be the best practice way for tackling this?
Edit:
Here's what I ended up doing, created a new WCF Service project in the solution. I also copied basically what was the MVC view page into a new standard web forms page in this project. On top of adding security via the regular .net Authentication methods (eg set only valid windows users can access the page), I can also lock down the vhost to only be accessed by certain IP's.
The best practice would be to expose a wcf service for this, and set up a security model that is different than website.
If you must use MVC the best approach use forms authentication with mvc and set
[Authorize(Roles = "SecureUser")]
On the View.
If the view never needs to be rendered at all except to provide data for the console app, then why not have the console app simply connect to your database to get the data directly instead of going through the web app? You could still do this for the console app even if the view does need to be available for some users, then control access to the view using the Authorization attribute, which could suitably restricted now that an external app need not have access to it.