I don't understand some code in the Microsoft.Web.WebPages.OAuth namespace, specifically the OAuthWebSecurity class.
It's this method here:
internal static void RequestAuthenticationCore(HttpContextBase context,
string provider, string returnUrl)
{
IAuthenticationClient client = GetOAuthClient(provider);
var securityManager = new OpenAuthSecurityManager(context,
client, OAuthDataProvider);
securityManager.RequestAuthentication(returnUrl);
}
The first line is fine => grab the provider data, for this authentication request. Let's pretend this is a TwitterClient(..).
Now, we need to create a SecurityManager class .. which accepts three args. What is that 3rd arg? An OAuthDataProvider? That's defined as a static, here:
internal static IOpenAuthDataProvider OAuthDataProvider =
new WebPagesOAuthDataProvider();
And this creates a WebPagesOAuthDataProvider. This is my problem. What is this? And why does it have to be tightly coupled to an ExtendedMembershipProvider? What is an ExtendedMembershipProvider? Why is this needed?
In my web application I'm trying to use a RavenDb database and my own custom principal and custom identity. Nothing to do with Membership or SimpleMembership that comes with ASP.NET.
What is that class and why is it used, etc? What's it's purpose? Is this something that DNOA requires? and why?
I didn't write the code you mention, so I could be wrong here, but I believe the ASP.NET code you refer to is indeed bound to their Membership provider.
If you aren't using the ASP.NET membership provider, I would suggest you simply use DotNetOpenAuth directly (as opposed to through the facade that Microsoft added), which has no such tight coupling.
If you don't need the ASP.NET Membership system to provide local login accounts (accounts stored in your local membership database) on your system I wouldn't go down the Route of using any WebMatrix based bits (WebSecurity / OAuthWebSecurity).
They actually make it harder to interact with DNOA and more or less hide all the interesting bits at the same time anyway ...
As I needed local acounts I ended up pulling all the source code for this into my source code and then editing it from there (I had other reasons for doing this as well, not just to enrich the interaction with DNOA).
If you need local accounts - use WebMatrix
If you don't need local accounts - use DNOA directly.
Related
So I'm wondering, what are the pro's & cons of the various ways to pass data between pages in your project.
I know of:
Sessions: I can't use this because my project needs to be deployed on something like Azure, sessions aren't good for multi-server deployment.
Passing parameters between the various actionresults: This works good, but it can be very tedious to do this...
Cookies: I was planning to use this for my project, but I have read that this isn't the best practice?
So I'm wondering what technique you guys are using (and why), so I can make a decision on what technique I will use.
For example: my user is logged in and for several ActionResults I need the UserId to access the userRepository, what is the best way to do this. Or maybe there is even a good way to hold the user as an object (then I wouldn't have to acces the db all the time)? I have set up a login system and its working fine, but doesn't the user get stored somewhere? Or does only some data of the user gets stored? I'm using this for instance:
FormsAuthentication.SetAuthCookie(user.Email, false);
Thanks in advance!
Passing usernames around sounds a lot like authentication. Take a look at ASP Membership https://msdn.microsoft.com/en-us/library/yh26yfzy(v=vs.140).aspx
Depending on your requirements you could also look at TempData although this is only really useful for redirecting between actions. Using Tempdata in ASP.NET MVC - Best practice
Edit - based on the fact you are using authorization cookies, you should consider MVC authorized attributes https://msdn.microsoft.cohm/en-us/library/system.web.mvc.authorizeattribute%28v=vs.118%29.aspx
Or another good approach is to use a Base controller class that handles your authorization
public BaseController: Controller
{
protected string username ;
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
// Do authorization here
username = // code to get username
{
}
Sessions:
pros : nice and easy
cons : eats memory
Parameters:
pros : its the way forms are 'meant' to work
cons : you can end up passing alot of stuff around or redoing work on the server
Cookies:
pros : access from client and server
cons : they have quirks, esp when dealing with them server side and passing them back. effectivly global variables with locking issues
my call : parameters. you can always have a big json blob
I have a bit of a unique situation here. I'm making a web application that is going to have
the ability to login with different web applications credentials. For example you can login/register with my site or you can login/register with your YouTube account. I'm not using OpenID because I need to have access to YouTube's data in this case.
I'm using ASP.NET MVC 3 EF4 with custom Membership, role, profile providers.
The problem is user names can't be unique because someone with a YouTube user name could have the same user name as someone that registered with my site. So I got around with by specifying a user type in my user table. This is pretty much a composite key (user id and user type).
I have a custom authorize attribute that is checking for the role that the user is in but now I need to implement a custom IPrincipal because I need to pass a user type. Only problem is where do I store that? the session?
Originally I thought this is what the Application table was for, and I had momentary success with that but read there is threading issues, and I was getting session faults all over the place it wasn't that great :(
I'm wondering what the best way to do with is because I can't use the overridden methods in the providers because I have to add a UserType parameter to some of the methods, but then this breaks the functionality of the provider.
EDIT:
I basically need to have the ability to change the ApplicationName at runtime pro-grammatically. I tried doing this, the only problem was when I stopped my development server but left my browser open then ran my dev server again it wouldnt keep the application name.
EDIT:
I've changed my application to use OAuth, I never found a good solution.
I basically need to have the ability
to change the ApplicationName at
runtime pro-grammatically. I tried
doing this, the only problem was when
I stopped my development server but
left my browser open then ran my dev
server again it wouldnt keep the
application name.
If you need to change the ApplicationName, this means you need to select a provider at runtime.
The only way to do this is to NOT use the singleton "Membership" as it uses the provider defined in web.config.
Instead each time you need your provider use :
MembershipProvider userProvider = Membership.Providers[UserProviderName];
Just set UserProviderName the way you want. I would go with a custom global authorization or preAction filter which detect the provider from some cookie or other session variable and put the provider in the HttpContextBase.Items collection which lives for one and only one request.
The best answer to this problem is answered on stackoverflow here: Membership provider with different ApplicationName in area
Here's the code they used:
Membership.Providers["MyOtherProvider"].ValidateUser(username, pwd);
Ryan,
Hmmm... can you work-around the problem by prepending the issuing-authority (local or YouTube) to the username field itself... Example usernames: "LOCAL/corlettk", "YOUTUBE/corlettk"???
Ok, you'll need a custom Authenticator in order to split the complex-string, and flick-pass the login-request to appropriate underlying Authenticator... but once that's done, (I guess) you're all set to deal EASILY with the much bigger problem (from your perspective) of Authorisation.
I percieve that you're a smart guy... have you considered-and-dismissed this approach allready?
Cheers. Keith.
PS: Yes, I'm a hacker... but I have bad habit of hacking stuff up that WORKS... so they've given-up trying to educate me.
Similar but not the same:
How to securely store database connection details
Securely connecting to database within a application
Hi all, I have a C# WinForms application connecting to a database server. The database connection string, including a generic user/pass, is placed in a NHibernate configuration file, which lies in the same directory as the exe file.
Now I have this issue: The user that runs the application should not get to know the username/password of the general database user because I don't want him to rummage around in the database directly.
Alternatively I could hardcode the connection string, which is bad because the administrator must be able to change it if the database is moved or if he wants to switch between dev/test/prod environments.
So long I've found three possibilities:
The first referenced question was generally answered by making the file only readable for the user that runs the application.
But that's not not enough in my case (the user running the application is a person. The database user/pass are general and shouldn't even be accessible by the person.)
The first answer additionally proposed to encrypt the connection data before writing it to the file.
With this approach, the administrator is not able anymore to configure the connection string because he cannot encrypt it by hand.
The second referenced question provides an approach for this very scenario but it seems very complicated.
My questions to you:
This is a very general issue, so isn't there any general "how-to-do-it" way, somehow a "design pattern"?
Is there some support in .NET's config infrastructure?
(optional, maybe out of scope) Can I combine that easily with the NHibernate configuration mechanism?
Update:
In response to the first answers: There are several reasons why I would want to connect to the database directly and not use a web service:
(N)Hibernate can only be used with a database, not webservices (am I right?)
We plan to provide offline capability, i.e. if the database or network should be down, the user can continue his work. To manage this, I'm thinking of having a local, in-proc database, e.g. SQL Server Compact, and using MS Sync framework to synchronize it with the server database as soon as it is up again.
Do you have any further ideas taking this into account?
First of all, letting untrusted users connect to a database is generally not a good idea. So many things can go wrong. Put a web service inbetween.
If you absolutely have to do it, make it so that it doesn't matter even if they get the username and password. Limit their privileges in the database so that they can only execute a few stored procedures that have built-in security checks.
Whatever you do, you can't give the username/password of a privileged user to an untrusted person. It's just asking for trouble. No matter how well you try to hide your credentials within an encrypted string inside a binary file or whatnot, there's always a way to find them out. Of course whether anyone'll actually do it depends on how interesting your data is, but silently hoping that mean people with debuggers will just leave you alone is not a very good security measure.
Actually the WebService approach (mentioned in some other answer) means that you move NHibernate and its logic to the web-service. The WebService then, exposes the db functionality available to the application using the WebService's methods.
There is practically only one user for the database, the one the WebService uses and if you want the application user to have different db privileges you abstract it from the WebService layer
In the end, the WinForms application is only aware of the location of the WebService where it requests data through the WebService's methods and you can apply any required security measure between these two endpoints.
For off-line capability it all boils down to making a secure way to persist your data to local storage and providing a synchronization method via the WebService
I have actually done this using a webservice that communicated with the DB and a WinForm application (.NET Compact Framework) that only talked to the webservice and in case of no cellular network coverage it would serialize the changes to the memory card (the data was not important so for my case obscure/obscene security measures where not taken)
UPDATE with a small example as requested (i do find it strange though to ask for an example on this)
you have set up your domain classes and nhibernate configuration and (for example) your repository stuff in a project of type ASP.NET WebService Application. For the sake of simplicity i'm only going to have a single web-service class Foo (in Foo.asmx.cs) and well as a single Bar domain class
so you get this (actual implementation varies):
namespace FWS
{
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
// To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line.
// [System.Web.Script.Services.ScriptService]
public class FooService : WebService
{
private readonly ILog errorLogger = LogManager.GetLogger("ErrorRollingLogFileAppender");
private readonly IDaoFactory daoFactory = new DaoFactory();
private readonly ISession nhSession = HibernateSessionManager.Instance.GetSession();
}
[WebMethod]
public Bar[] GetFavoriteBars(string someParam, int? onceMore){
return daoFactory.GetBarDao().GetFavoriteBars(someParam, onceMore); //returns a Bar[]
}
}
and we abstract the daobehaviour, or just use the nhsession directly, exposed as a webmethod.
Now from the WinForm application all you need to do is Add a WebReference which makes all necessary changes to configuration but also generates all necessary classes (in this example, it will create a Bar class as the web-service exposes it).
namespace WinFormK
{
public class KForm(): System.Windows.Forms.Form
{
public void Do()
{
var service = new FWS.FooService();
string filePath = "C:\\temp\FooData.xml";
Bar[] fetched = service.GetFavoriteBars("yes!", null);
//lets write this to local storage
var frosties = new XmlSerializer(typeof(Bar));
TextReader reader = new StreamReader(filePath);
try
{
var persisted = (T)frosties.Deserialize(reader);
}
catch(InvalidOperationException)
{
//spock, do something
}
finally
{
reader.Close();
reader.Dispose();
}
}
}
}
there are certain things you have to take note to:
You essentially lose lazy stuff, or at least you lose it in your winform application. The XML serializer cannot serialize proxies and as such you either turn of lazy fetching on those collections/properties or you use the [XmlIgnore] attribute which in turn do what it implies on serialization.
You cannot return interfaces on the WebMethod signatures. They have to be concrete classes. So, returning IList<Bar> will have to be transformed to List<Bar> or something of the like
The webservice is executed by IIS and is visible from a web browser. By default, only local browser requests will be served (but that can be changed) so you can test your data access layer separately of what your winform does.
The receiving end (winform app) has no knowledge of NHibernate whatsoever.
In the example above i've kept the same name for the dao-methods for the web-methods; As long as you didn't keep nhibernate--specific methods in your dao's (lets say like a NHibernate.Criterions.Order parameter) you will probably find no problem. In fact you can have as many .asmx classes in your webservice as you want, probably even 'map' them to the corresponding dao's (like public class FooService : WebService, public class BarService : WebService, public class CheService : WebService where each corresponds to a DAO).
You will probably have to write some kind of polling method between your endpoints to keep your presented data fresh.
WebService data is verbose; extremely so. It is advisable to zip them or something before sending them over the wire (and maybe encrypt them as well)
the win application only knows a configuration entry: http://server/FWS/FooService.asmx
Webservices have Session disabled by default. remember that before starting using the session for user data.
You will probably have to write some kind of authentication for the webservice
In the example above i am returning a Bar[] with Bar being mapped with nhibernate. More often than not this may not be the case and you may be required to write an auxiliary class WSBar where it adapts the original Bar class to what the webservice and the winform application can consume. This class is actually just a data carrier. Again this depends on how much integration exists with your domain classes and nhibernate as well as how muxh complicated your classes are: Certain data structures cannot be serialized by default.
This model may not suit what you have already done with your application
I think it's hard to do : it's like you don't want a user of stackoverflow to know his password.
A user can always trace his network traffic and see the user/password (you can had an encoding, but it still won't be 100% sure I think).
I think that you should add a webservice between your user and your database with a unique id for each user.
This is why database desktop apps suck. There is no good way to slice it. Best bet would be to use stored procedures or web services. Basically, another layer that can be locked down and control access to the database.
Simple question. I know that in the default MVC application in Visual Studio, you can register a user. So I want to be able to put that info in a database and use ADO.net or LINQ to SQL to be able to communicate. How do I do this?
Do you have a database or do you want to create a new one?
If you have one just create a connection in server exploer, add new Model in Visual studio, select LinqToSql Classes, select tables from your connection and drag and drop the tables you need to the design surface. Then you can access your model from your controller where the user data is posted to.
Check this thread for example of saving.
If you don't have a database you obviously have to design and create it first
Some might argue, but you probably do not want to use the built-in membership provider. The reason is that it generates its own default schema which is good to start with, but it's better to just bite the bullet and design your own. That way, you're in control of your application, and do not have to migrate your database whenever some change is required.
The sample stuff in ASP.NET MVC uses the built-in membership and forms authentication in ASP.NET. In the Web.config, you can configure it to store the data in SQL Server rather than the default which I think might is SQLExpress. MSDN has an article on how to do this:
How To: Use Forms Authentication with SQL Server in ASP.NET 2.0
You basically just run a sql script and it generates a bunch of tables and stored procedures in whatever database you are already using. You can then access the database directly or through the membership API.
Alternatively, you can roll your own implentation of IMembershipService which just has a few methods to handle:
public interface IMembershipService
{
int MinPasswordLength { get; }
bool ValidateUser(string userName, string password);
MembershipCreateStatus CreateUser(string userName, ...);
bool ChangePassword(string userName, ...);
}
I have an existing community backend and I like to use Umbraco for my presentation layer. How can I implement login/logout with .Net forms authentication? (I don't want to use the Member functionality). I have different type of users that get's access to different type of pages. How can I control this? User control?
Umbraco uses the ASP.NET member / role provider model for it's membership system, and it's a pretty straightforward step to swap the default one out for your own implementation. I've done this in the past where I wanted to authenticate members against an Active Directory store but I can't imagine it being much more difficult to authenticate against a custom database.
The benefit from this is you get full integration with the Umbraco membership system, and by using a custom role provider, editors will be able to restrict pages using the built in page-editing facilities as opposed to you having to hook in your own security controls.
You should be able to create a simple membership provider by extending the UmbracoMembershipProvider class and overriding the ValidateUser method. I haven't done this myself, but I know of others who have.
To authenticate against a custom role provider, you'll need to create a class derived from RoleProvider. The methods you'll be interested in overriding are - IsUserInRole, FindUsersInRole, GetAllRoles and GetRolesForUser.
Here's a link to a Scott Guthrie blog post which has more information on the provider API than you'll ever need to know, including the source code for the default providers.
I've used two approaches on my umbraco sites. Both approaches include user controls for login and logout that are responsible for authenticating a user with a custom solution and clearing credentials respectively. I also add, for both approaches, an umbracoMembersOnly attribute to any document types that I want to protect.
In the first approach, I had each individual template check to see whether or not the user was restricted from access. To abstract this, I created a siteuser class with an isMember or isLoggedIn method that was available site-wide and could be called from either an XSLT or User Control macro. The benefit to this approach is that I could tailor custom messages on each template rather than merely providing the same access denied page.
The second approach - which is the one I favor now - if to create a Permissions macro that is responsible for checking the user's right to access any page (i.e. checks for an umbracoMembersOnly attribute and, if true, checks for a session variable). This macro gets included in the master template, and so executes on every template. If the user doesn't have permission to access the current page, I redirect to the same page but with an ?alttemplate=RestrictedPage or similar appended to the query string. (Make sure that your Permissions macro checks for an alttemplate=RestrictedPage in the query string, or you'll end up in an infinite loop of redirects.)
You can checkout http://osMemberControls.codeplex.com