I'm trying to come up with a way to secure a set of Admin CRM pages that control a Meteor application I'm working on. There's just one codebase, with the server, customer facing website and admin facing website in one project.
I need a login page which can verify one username and password pair, and a simple way to check the status of the user on both the client and server side. I also need a way of the admin's authorization timing out if it hasn't been used for x minutes.
I've looked at the meteor accounts package and it's just way too much fluff for what I need. This website will only ever have one admin user, so there will only be one set of admin username and password to store. I don't want it stored in the database, rather loaded with a settings file on the server on application start. It doesn't need roles, emails, password reset functionality.
Any recommendations for a package or approach I could use to implement this?
I know you said that the accounts:password package seemed a little "overkill", but in reality it really isn't. What you are gaining there is pluggable UI (via accounts-ui and other packages that build off it). The approach I have taken is this (which happens to work well even for apps that do support multiple users, since ultimately you still need to bootstrap your start users).
First, I use a combination of accounts:password and alanning:roles. If you absolutely don't need the roles portion, you could probably get away without it, but in all my personal cases I have found it useful to have multiple levels of ACLs for the various users. We could get into a whole philosophical discussion on using roles/groups to lock down individual features, but that's sort of off topic for this discussion.
Next you need to boot-strap the user(s). Somewhere in your /server folder you will do something like:
if (Meteor.users.find({}).count() == 0) {
// No users created...create default users
Accounts.createUser({
username: 'myuser',
email: 'myuser#mydomain.com',
password: 'myp4ssw0rd!',
profile: { profileProp: 'propVal` }
});
// Add new user to whatever roles needed
}
There are some more things I usually do here, like checking to see if my roles exist, and if not, create them before I try to handle the users, but the key here is to do that when the server starts up.
Once you have your user(s) and role(s) created, it's a matter of checking/verifying the user/roles in your app. For menu items you can show/hide stuff based on whether the user is logged in and/or has a certain role, and you should also verify in your application routes that require ACLs, like your admin route. In addition, use the user id in all your publications as well to limit the data your users can see. Don't rely solely on hiding a menu option...security through obscurity just doesn't work.
Why do I suggest doing it this way? First off, it's really not THAT much code. You could literally do this in probably 20 lines, max, and have a full authentication setup. And the benefit of those lines of code greatly outweigh the 30min tops it would take you, as you will now have "real" user authentication in your app and have the ability to do things like OAuth if you ever decide to in the future. Most importantly, you unlock pre-build UI plugins that you don't have to code, built-in and add-on methods to help check ACLs, the ability to lock down data by user, and you don't have to try to implement your own solution.
Related
I'd like to start a website that provides users with photos editing/storing experience. The initial idea is that the user has his own account where we store the edited photos and some settings. I'm am a WordPress web developer and when I try to consider how to build such a website in WordPress I don't really understand how to provide such a services without having access to user photos. My idea was to create a custom post type and save it with the user as an author. But as an admin of the website, I will have access to all the created/saved photos and I would like to build it in a way that I don't have it. Is it possible?
I've used previously the app to write a diary that saved the data to my Google Drive and if I understand correctly, it never had access to my files.
So my question is: what are the best practices to build such a resource? Is it normal to have access to all of your user photos if you provide such a platform?
In your case, as you will use WordPress and you are the developer you will always have access to the data of everything.
You will always have a way of knowing which data is from user or which data belongs to another user.
You have two options to do this, but this will take some development work:
1 - You must recreate the way WordPress works where the user is not related to an email and not private data that can relate to the user.
Example: You ask the user to register only that only asks for a hash that can be any word, number, or any other information and a second field would be the password.
With this in the backend you get this two information and do some kind of hash I'll give the example using md5 but do not use it.
After that join these two data and this will be the user.
and to login the user needs to repeat this information and will be within the platform. With this you will be able to maintain the anonymity of the user and will not know who the user is.
In this option you will have for each hash and password a different user :)
But I recommend not using wordpress if you choose this option. You can use a framework like CodeIgniter for example which is super simple.
2 - The second way would be to use the normal wp User, not worrying about who the user is and their information. But one way to keep photo information "anonymous" is to generate a unique hash with each user and have some way of relating the user to it.
Example: When uploading a file to edit it will generate a passkey, you must warn the user that when they want to edit this photo or view they will need to type it into an input. With this you will not know which information is from which user. but it requires extra work for the user
This way you will always have anonymity of user information. I hope I helped you somehow.
I have an existing Wordpress site. The plan is to rebuild the site using the cakePHP framework. Due to time restrictions, I want to replace individual sections of the Wordpress site one at a time. This will mean that both apps will be running side by side for a certain period of time. I need to control access to the cakePHP app using the authorization provided by Wordpress. I'm not sure the best way to go about doing this. I've seen similar questions asked a lot, but I have not yet found a clear solution.
I'm thinking about two approaches:
Plan A:
Configure Cake to look for Wordpress's authorization cookies.
configure Cake to look at Wordpress's database.
Borrow some of Wordpress's authorization logic to teach Cake's Auth component how to authenticate WP users.
Plan B:
set up an authorization API on my Wordpress site.
set up separate auth component in cake.
ping the WP endpoint when a user hits a protected page in the cake app and then manually log in the user. (This would create a second set of auth cookies)
Do either of these sound like the right approach? Is there a better way to do this?
Helpful references: Article about Cake session handling, Cake Auth component documentation, Cake Auth tutorial, brief overview of WP authorization, a more in depth look at wordpress authorization
UPDATE
We've started working on this, and it seems like it will work, but there is a very tricky aspect involving password hashing that warrants its own question. If you're following this thread, you may want to have a look.
I once had a similar situation: Cross framework authentication zend + codeigniter which was few months ago...
Anyways, this is what I will prefer:
set up an authorization API on my Wordpress site.
set up separate auth component in cake.
ping the WP endpoint when a user hits a protected page in the cake app and then manually log in the user. (This would create a second set of auth cookies)
Here, I would suggest a slight change which is do-able.
Make sure, you have a token system of SSO. As in, when person is logged in on Wordpress, set another cookie which will have a token: Token will be username + password (hashed) + secret key, which will be same between Wordpress and CakePHP. On either site, look up for cookie and manually log the user in or just perform a database look up. Hashing is important for that cookie!
However, if the site is using different domains, you might need to re-strategize:
I had different domains once. At the login or unauthorized page, I would ping the other website and bring up their login box. On the other website if the user is logged in, they get post login page and if request URI has sent a token, we perform normal operation and return the authorized token to this (current) domain.
In simple words:
Site A = WordPress & Site B = CakePHP
Site B hits a page where authorization is required then, ping Site A for a login (as it happens when u do Login-with-Facebook sort), which will request via a Token (private key) and REQUEST_URI which will be part of SSO verification table on Site A, if person is already logged in then, Site A will return (via POST) a token, which further will be decrypted via (private key) of Site B and log the user in. Private key of B and A will be same.
Hope this was understandable.
Questions? :)
Answer to your questions in comment:
Ideally, why we use SSO? We use it because of many constraints. For example: You have a database of say... a million row with more than thousand tables, you need to add a module over ur huge app already... so, instead, you will use another database... SSO will return user information, which can further be replicated. For example, when you click on 'Login with Facebook', it returns requested information, like email address, or user's name or even profile picture. Which can further be added to our database... Keeping different databases is strongly recommended :)
To your 2nd and 3rd question: Should both sites reference the same users table in the database? different databases is recommended unless, you are using the same data. Or say changing the software platform.
Should I copy the site-specific user rows into separate user tables for each app? Yes, that should happen automatically. Once you are registered on a main site, nothing happens, things should happen once you are logged in already and then go to site B... Once logged in, user info can always be requested :) That way, new site will have active users ! 2 birds?
Don't complicate (bother) yourself with how what works but, concentrate on how, what is achievable in short period. SSO - Logged in - Restricted page - Look out for log ins - Either login - If already logged in - fetch user info - If user info exists - login via secondary site OR set the new user info . Done!
We developers love flow charts! Don't we? I just created one:
Further answers:
Does the "Fetch User Info" stage mean that we take the user info from the site which is logged in, and create a new user (row) automatically in the other site?
Ideally, you will ask permission from the user before they 'allow' their info to be used but, it varies how your privacy policies are.
In other words, one site handles all the registration/user-creation and the other site just waits for that user to show up and trigger automatic creation. OR at the moment a user registers on the one site, BOTH databases get a user row inserted?
one site handles all the registration/user-creation and the other site just waits for that user to show up and trigger automatic creation. You can have both. Sign up on your website and also a trigger based automatic creation. Depends on your strategy. OR at the moment a user registers on the one site, BOTH databases get a user row inserted? That would be a horrible practice! It will kill the motive of SSO. Motive of SSO is to create an auth family which can be used by users so that they do not have to register every now and then for different websites. update only one database at a time and other when required :)
Questions? :)
I have done this once. I don't have the snippets and/or any references to anything. But thought it might be helpful.
Configure WP and CakePHP both to use same session, you can do this by session id and session name,
When User registers for your website, register them using both WP and CakePHP,
Choose one framework that will handle login view from the front end. I had chosen CakePHP as I was more proficient with it, once the login is successful locate the same user in other framework's DB and authenticate the user using their authentication system.
Hope this helps !!!
Suggestions:
If you are building a closed system, meaning you have to be signed in to access anything useful in the site, then you can use CAS . I know it's used by mainly universities, but for closed systems it works.
( If you need to handle anonymous users the suggestions below might help)
Keep it simple and, similar to Part A of your plan, have a cookie ( visible by both cake and wordpress ) that simply states if a user is logged in. The cookie should be created/checked by both cake and WP. Cake does not need to look at WP's DB. The cookie can have information on how the users in each system are mapped.
Have a central login screen, this is similar to what CAS does. But please build your own. CAS does not handle anonymous users. I am currently creating a central login screen for work. It's simple. The central login screen will handle all authentication and create the cookie visible to both WP and cake. This would mean that the login link for WP and cake will redirect a user to a common page. The link will need to provide a callback URL so that after the user authenticates successfully, he is redirected back to the original service. You will need to decide on a central DB for user authentication.
The cookie approach has following bonus:
It's a lightweight solution and can be wrapped with an on/off switch. In WP, simply wrap the cookie logic with a wp_options value.
You can use WP's and cake's authentication system. no need to work with API's and/or sessions. No need to couple applications by looking at each other's DB.
You can keep roles and permissions native, meaning WP will work with it's own roles and permissions system and your cake application will work with it's system.
Adding a new "service" to your platform is as simple as "create/check for a cookie" then use the system out-of-the-box auth system to log the user in.
Single Sign On is as simple as creating a cookie. Single Sign Off would be deleting the cookie.
I can definitely go into more detail on each suggestion if you're interested.
I know this is a question that has been asked over and over but I'm attempting to implement permission based rather than role based authorization in an ASP.NET MVC application. So instead of just having high level roles like Manager, Admin, or User, I need to have permissions like ViewTask, AddTask, DeleteTask. I have read a ton of comments on this and it seems like the easiest solution is to just treat roles as permissions and define "roles" of ViewTask, AddTask, and DeleteTask.
Is such an approach really a good idea? Some of my concerns are that you could end up with over 100 roles depending on the size of the application which would then rule out the ability to do role caching in cookies and thus every call to User.IsInRole hits the database. If every action method is going to be decorated with [Authorize(Roles="XXXX")] am I going to see serious performance issues?
My other issue is that I still want to keep the concept of a role around so that an administrator can simply associate a user with a role that has a predefined set of permissions. Using the approach above my thought was to create a separate entity in my application named Group and that Group would be responsible for keeping track of the ASP.NET roles that are assigned to that Group. So, when a user is associated with a Group, I can retrieve the ASP.NET roles that need to be assigned to the user and add all the roles.
Has anyone implemented a system in such a way? Any opinions or thoughts on this approach would be appreciated.
Thanks
I agree with #jlew about caching the user's data and when the cache expires - just reload it. There's no use trying to force this data to stay persistent. Additionally, if you want to move away from the ASP.net role providers, you could roll your own security as I've described in this reply. This has the advantage of allowing very custom security solutions for roles/individual permissions.
The following is just an idea that I've been toying around with lately (just some food for thought). Why not use the RESTful urls of MVC to define "permissions". For example:
/tasks/add could define the permission for adding tasks. These could somehow be hierarchical so that giving a user permissions on /tasks/add also gives them permissions on /tasks. Then, you could use a global action filter that would build the URL given the route values. This would also allow really interesting approach for individual item security configurable via runtime. For example, /tasks/edit/23 could somehow grant edit permissions on task with id 23. Anyway, this might not even be helpful at at all... but it's just thought I thought you'd like to maybe consider.
Cheers!
We solve the problem by caching the principal on the server side, so that the "permission roles" do not need to be in the cookie and we do not have to re-load on every request. You can actually get around the cookie size limitation by chunking your cookie data into multiple cookies (Windows Identity Framework does this.) But, you may have bandwidth or other concerns with big cookies.
I'm thinking of creating a diagnostics page for an ASP.NET app, which would be mostly intended for admin use to get more information about the application for diagnosing problems.
Examples of the info the page might have :
System.Environment.MachineName (might be useful in web farm scenarios)
System.Environment.Version
Environment.UserName
database name
current user's session ID
Some of the info on this page might be sensitive from a security perspective.
If you've done this sort of page before, what sort of security did you put on access to this page ? .
EDIT :
I should add - occasionally it might be useful to see this page whilst logged in as a specific (i.e. real) end user. e.g. say a problem can only be reproduced when logged in as a particular user. Being able to see the diagnostics page for that user might be useful. e.g. knowing the current session ID might be helpful for debugging.
EDIT 2 :
I'm starting to think that this diagnostics page should in fact be two different pages. One to display stuff which is the same for all users (e.g. database name, CLR version), and another for stuff which can vary by session (e.g. browser info, session ID).
Then you could lock down security more for the first page.
Yes, I've added this sort of page before (and found it useful). The security was pretty simple: the page contained a password form. The server-side code checked this password against a configured value and, if correct, displayed the real content and set a value in the user's session to say that they've been authenticated as a developer, so that they're not prompted again next time.
I suppose there was also a little security by obscurity, since the URL of the page wasn't published anywhere.
I was also careful not to reveal anything really sensitive on the page. For example, it allowed viewing our application config values, but masked out anything with "password" in it - hey, if we really want to see the password we can open a remote desktop session to the server.
There's also a couple of other ways you could do this:
If your web application has user authentication, restrict access to this page by checking that the user is flagged as an administrator or belongs to some kind of admin role.
Use a simple if (Request.IsLocal) ... type check, though the downside of this is that you still have to connect to the server and browse the website locally - which might not always be possible. However, this does still have the benefit of being able to easily view key system settings.
Personally, I've used a combination of both methods where a local request always allows access, and non-local requests require an admin user - eg. if (!Request.IsLocal && !IsAdminUser()) throw new SecurityException().
Also, I'm in agreement with Evgeny - be careful not to reveal anything really sensitive on this page (such as application connection strings or passwords).
use forms authentication and setup a user or two with access to that page. that way you can change passwords and revoke access once the site is deployed.
It sounds like you want a robust solution for your error page. I would take a look at open source projects like Elmah (http://code.google.com/p/elmah/) for a good example of a robust error page which includes configurable security. To give you an idea, here is a post on configuring Elmah which takes you through setting up the security. The security I have tested allows me to use my domain credentials to login.
Encouraged by SO, I'm trying to write an ASP.NET site that uses OpenID for user authentication. It's a regular WinForms site (not MVC.NET), using the DotNetOpenId library for authentication.
Is it safe for me to permit/deny administrative functions on the site by simply comparing the current session's "ClaimedID" (as returned in the OpenIdLogin_LoggedIn event, as member DotNetOpenId.RelyingParty,OpenIdEventArgs.Response.ClaimedIdentifier) to a known administrator's OpenID (i.e. mine)?
If so, is it safe for this ID to be visible (e.g. in open source code), or should it be "hidden" in a configuration file or a database row? (I know it's better design to make it configurable, my question is just about safety.)
My solution is to follow the same idea of the Roles table. After you've authenticated the user, look up that user's roles. If the user has role "Administrator" in the UserRoles table, then they can do whatever the Administrator can do.
I don't broadcast open ID's in my app. They're stored in the table. On every action result, I'm hitting the Users table, since I have also modified mine to store various user state information. With the exception of the home page, there is going to be some user information that I need from that table. I'm using LINQ, so I include the .LoadWith() to load the User with his list of roles when it serializes.
Jarrett makes some good comments about using database tables.
Just to answer another one of your questions, no, it's not a confidentiality thing to put your OpenID in your code generally. If setting up roles seems overkill for your site, a simple equality check against your ClaimedIdentifier is just perfect.