very simple question:
I have admin site in my web project. So, how can I make it safe?
What I have until now:
Database handled user with userID and userlevel
on the pageload of the admin master page (which includes all admin sites) there is a clause to check if userID is okay (get the user from database) and if userlevel is right
If Not, redirect to Default.aspx with normal master page
if yes, go trought
How safe is it really?
Edit:
The userID is saved in a session on the server.
There is no way to save the login (no cookies).
The user must login to get the userID in the session
The login is saved in a database table user_log with username, password, ip, loginsucceeded and userID
The basic idea looks ok. It all comes down to how you are getting that UserID to make the checks against. If the userID is being passed as a querystring, then that is very bad. If it is stored in a session via sometype of pre authorization then it is better. If you are using SSL, IP checking, etc it will improve your level of security.
The main thing is HOW you are getting the userID to verify against. That is where the exploit will occur. Secure that process and you should be ok with your setup.
Edit: Based on your update this looks ok but it also depends on how secure you really need this to be. How secure is your sign in page? Are you using SSL? Any worries about session highjacking? Why not store an IP with the userID and verify the request IP against the stored IP when doing the UserID fetch from the session?
There are so many security solutions out there. You need to decide how far you need to safely go to ensure the level of security that is necessary for your particular application.
We use integrated windows authentication.
In IIS manager, click the "Directory Security" tab
Uncheck "Anonymous Access"
Check "Integrated Windows Authentication"
This lets you administer who has rights to your admin site by modifying domain accounts instead of using a roll-your-own solution. You can still get the logged-in user's credentials via the Environment class, which can be used to associate any web-specific properties for each user that you want to store in your database. This also has the advantage of automatically handling timeouts, relogin requirement if browser was closed, etc.
Your solution looks almost fine, though it sounds as though you're adding individual user accounts to the SQL server instead of handling everything through the ASP.NET service account login. I'd avoid adding individual user accounts into your database. In ASP.NET, unless you're jumping through some useless hoops, the ASP.NET service account is what is authenticated for DB connectivity, not the user that's logged into the site.
Related
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.
Currently we have a typical web application, which all the clients access and login using their credentials.
One of the client does not want to login using their credentials, instead they will be passing username, fname, lname in the URL and they should be automatically be logged in if they have an acct or else we need create user account on the fly and log them in.
The web app should act the same way for the rest of the clients. How can this be achieved. Do we need to use any single sign on methodology (SAML, etc)?
Overview of requirement:
Request URL -> Determine if Client is A -> if yes then check the values passed in the url exists in the db -> if yes then log them in automatically -> if no create a record with the passed values and then log them in
---> if client is not A then take them to Login screen
If you are planning to base your decision only on some URL values to allow automatic login, you are creating a very biiig security loophole here.
Instead you should have some configurable mechanism, where system admin maps some IP addresses to specific user. This way when user requests for a page, you check if the IP from which request has come in, belongs to some specific client. If yes, then log him/her in else send them to login screen. This is also a bit of security hole, but a smaller one, because people will not gain access until they know which IPs are mapped to users and until they use some ip spoofing software.
Probably you can put a dual check of URL keys and IP mapping, that will make it tighter.
Best option is to use single sign on technologies like live id authentication. but it will require more efforts, and still requires users to login with live-id for the first time.
edit-->
If you are using your custom authentication mechanism, then you have 2 options
1. Change your login page to detect the request IP and have automatic login for selected users
2. Write a http handler which will check where the request is coming from and auto login the selected user accordingly.
I hope you understand what all things are involved in "Auto Login" which i am talking about. e.g setting the session variables/username, displaying the username on page etc.
Here is the scenario...
I have a site:
http://internet.com
and I set a token(cookie, something like that) from http://internet.com when a user has SUCCESSFULLY logged in.
I also have http://web.internet.com.
On http://web.internet.com I want to display data to users that have that token/cookie/etc available to them.
Here is the use-case
user logs into http://internet.com (asp.net framework hosted on different server - this is our primary product that requires a subscription / username & login )
user then has access to a section that is hidden from plublic view on http://web.internet.com (wordpress site hosted on goDadday - this site contains a knowledge base that we do not want to make public unless they have done [XXXXX] )
both sites are hosted independently of each other and do not share a common username and password
======
Another scenario is to set up wordpress to allow a specific section as a jsonp response. but only if the user is logged in at http://internet.com to allow the user to have access to the jsonp response located at http://web.internet.com
Any ideas from you beautiful people?
It really depends on the level of security you require. You can log a user in to a Wordpress site without a password by using wp_set_auth_cookie, however if you are just validating that a user is logged into the ASP.NET site and then using JSONP to load a page that set's the auth cookie, it will work, however you definitely have some security gaps.
A better solution would be to set a domain level cookie for .internet.com with a token that can be read by any server in your domain. The Wordpress site could then check is_user_logged_in(), and if not take that cookie value and make a back end call to the ASP.NET site to verify its authenticity, and then call wp_set_auth_cookie(). A simple web service would likely be the best option. You would still need some level of mapping between usernames on the ASP.NET and Wordpress site however to know which user_ID to pass.
I am using the provided ASP.NET SQL Membership & Role providers in my application.
How can I prevent that the same user does login from different workstations using the same credentials? I can imagine to use the IP address for this but I dont really know where to start from...
Also what about users behind the same router? Is there a way to prevent them access from different client PC's?
IP would not be a very good way as all users behind a typical company LAN would appear to you as connecting from the same IP. A workaround is to logout the user that is logged in with the same credential thus keeping only the latest one logged on. This can be achieved by keeping the logged in user's ID or name in Application or DB. As soon as a new user session is started, check if the user is present in Application/DB. If so, mark it dirty. In the pages, check the presence of UserID/Name in the Application and if the user is marked as dirty, invoke a logout. This can be implemented in a BasePage that all the pages within the site/app inherit from.
Perhaps you can store whatever you are using to uniquely identify the user like a UserId in ApplicationState and check to see if that value is not null. You add their UserId value to ApplicationState at the start of SessionState and then at the end of SessionState remove that value from ApplicationState.
ApplicationState is global to the web application meaning it is accesible to all users and sessions while SessionState is limited in scope to a single user and session.
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.