asp.net c# web app with active directory and windows authentication - c#

i'm currently developing an intranet web app, with a homepage and several departmental pages, the web app is merely for viewing information so everyone will have the same privileges. i've reached a point that i must worry about the app's access and authentication, my company has an active directory with several groups that i can use, after searching for a while i got the following questions:
in the webconfig file, i forced windows authentication and blocked users that are not authenticated (deny users = ?)
i saw somewhere that i need several webconfig files, one for each page, is that so? how do it make each page connect to the corresponding webconfig?
after looking at some examples i can't figure out my AD connection string (i'm currently on a development machine), our AD groups are on our domain controller, the physical location is "DCserver.company_name.local\city folder\groups"
do i need to create a login page? i mean doesn't that kinda go against the point of having windows authentication?
i don't need to manage anything within the AD, i simply want to read the groups and ensure that, for example, the marketing people only have access to the homepage and the marketing departmental page
as i've mentioned up there, there will be no special special privileges, the user from, for example, marketing will be able to click everything within his departmental page
i'm sorry for all the questions, but i'm relatively new to c# and .net development

Following are the answers to your latest set of questions:
-In the webconfig can i specify the groups that have access to each departmental page as well as the homepage? kinda like the following code, if so, i need my ldap connection string to be placed before assigning which groups have access to which page, right?
[Dipra] You are probably better off doing the authentication without using the roles in web.config, as this will also require the roles to be defined. We are talking about AD groups here, of which users will be a part. So, in the Page_Load(), simply call the authentication method, probably passing the username and the AD group allowed access to the page as parameters. If you want to make your solution configurable, store the allowed AD group for a particular page as 'keys' in your web.config and then read them in your code. Pass the group to your authentication method along with the username.
-when a user opens the web site, he will be prompted to insert his windows credentials, this is automatic, right? he will then be able to see the homepage and then go to his departmental page, right?
[Dipra] Yes, this is automatic. No separate code required for this. He can go to whichever page he wants, provided he is authenticated.
-if i understood correctly, in every page_load event i need to do a search taking the user's name and checking to which groups he belongs to, is that right?
[Dipra] Yes, you need to do that check in every Page_Load() method. As an approach, you can try getting all the groups of which the user is a part, and then check whether the allowed AD group for that page is one of those groups. If it is, the user can be authenticated.
-i the above is true, and now i'm gonna explain the navigation of the page 'cause i think that messing with the page_load might bring me some issues
will the check to see to which groups the user belongs to occur with every page load? won't that make the app slow?
[Dipra] Every server side control, e.g asp buttons, will cause a postback. To ensure the authentication code in Page_Load() doesn't run every time a postback happens on the page, enclose that bit in if(!Page.IsPostBack) {}. This means any code within this block will run when the page is not being 'posted back', i.e., being rendered for the first time. Any subsequent postbacks from server side controls on this page will ignore the code inside this block.
-finally, to check the membership of each user i need a similar code to the second answer on this The Link that Dipra posted i pasted below but in c#, right?
[Dipra] You can refer to the accepted answer on the above post, probably with a couple of tweaks of your own. It's already in C#.

Yes, your web.config would be like what you said.
You don't need to 'grant' access to specific groups for pages. In the web.config, store the groups allowed access to specific pages as keys and read the configuration in your code like this. For example, if you have a key named 'Marketing', then you can store the name of the corresponding AD group, which is allowed access to Marketing pages in the value field. Yes, once you have got it working for one page, others will be easier.
No, the authentication method that I talked about is a custom method you will write for yourself, which will use logic similar to the one in the link I had posted.
The entire authentication code should be enclosed in a try...catch block. If there are issues while doing the authentication against your AD (for e.g., connection problems), then your code will throw an exception. Catch (and ideally log) the exception and redirect the user to an error page, probably saying there were some problems which prevented authentication. You should not be granting access to the user in such a scenario.

Related

Web Site Security - 1 main site, 1 secondary site hosted within the main site

Scenario:
ASP.NET 5 / Razor Pages / C#
We have one main site, with very good security. In the background, all passwords are encrypted. Also, a log is made of all logon usernames, from which IP addresses, at whatever time accessed.
We have a second site that is hosted within the main site visually on the front end via iframes mostly, but not on the server. They won't live together in the same web app.
Problem:
I need to ensure that the secondary site access is secure, whilst relying on the fact that the user already logged on successfully via the main website. I don't want the user to need to logon twice to two systems, rather I want the single logon to fluidly allow access to the secondary site.
I have a method I am using now. It works, but I really want to delve in and see if I can improve this given I'm not heavy on experience in terms of website security. I'm sure there is a better way.
Options?
From a security point of view, using iframes, the two site are independent.
So you need to guarantee that the security process is issued on both sides.
You have several possibilities, but the best, I think, is to revalidate the user in the "iframed" website.
You can use a token, generated from the main website and stored in a backend DB, and pass it to the iframe URL.
The endpoint of the iframe has to read the token, call a backend API to validate it and allow the access.
The main problem you have is to refresh the token after a reasonable time, in order to ensure the validity during the use of the "iframed" website.

two anonymous user at a time

We are using anonymous identification in asp.net. Anonymous identification creates cookie whenever user lands on our application first time. according to the value of cookie we identify our user and made our business check whenever user lands on our application. It works fine with one cookie/user/anonymous user at a time.
Now i want two parallel anonymous user in one browser at a time. Can you please help me regarding this? How can i do that in Asp.NET MVC? How will I manage two cookies at a time?
let suppose two tabs are open in browser so it mean two user are present. How will system behave when user enters same URL in 3rd tab?
Note: This is a bad idea, and users sharing a browser session seems really fishy to me. You could also use Chrome named users or an incognito session, or different browsers. However, I will present a solution assuming that the strange requirement stands.
You are looking for cookieless sessions. Add this to your web.config in the system.web section:
<sessionState cookieless="UseUri" regenerateExpiredSessionId="true" />
Note that you may find that this is not officially supported anymore in MVC, but does work in many cases. It worked in my simple test.
This will use the URL as the session identifier with each user getting a unique session upon hitting the site without a session in the URL. This is not secure at all because users like to share links and in this case they will be sharing a link to their session.
For your case, this may be sufficient.
More info here.

Add Session Management to ASPX pages with Minimum Code Changes

I have an ASP .NET application which has a number of aspx pages. These pages were not having any login or session management features and any user could directly type the url and visit any page.
Now I want to add state management feature to all the pages. I created a new signup and a basic login page which accepts username and password and has necessary database for it. It is fine to use any server or client state management features, but how can I implement it with very minimum code changes.
One straight forward solution here is to implement session variable in server side to store logged in user details and check for it in the Page_Load event handler of each and every page. But here, code change has to be made in all the pages and I don't want that as there are so many pages. Any easier way will help.
Any ideas please??
Well, first of all it was good that you haven't implemented authentication in Page_Load on every page. Whenever approach you think of requires that you copy-paste code in multiple places - you are doing something wrong.
That being said, you will probably need to create base class for your Pages and by doing that you could have authentication restricted to one spot / class.
However, it would be better if you combine that with what ASP.NET framework offers. From stuff you are talking about it seems you are using ASP.NET Forms - here is article that should provide you with fine overview on everything you need to do:
How to modify web.config to use Forms authentication
Login and Logout user (create authentication cookie)
Necessary code for authenticating requests that needs to be added to Global.asx
Restricting access to pages by entering appropriate values in web.config (although better approach would be with base class I mentioned)
Role-based Security with Forms Authentication

Set up STS but keep formsauthentication in webapp

I'm enabling an windows identity foundation on an existing webapp.
I want to mess as little as possile with the existing code so I would like to the login page which uses formsauthentication left in the application and I just connect with the STS if the user enters the application via a specific page e.g "im_comming_from_some_other_site.aspx".
in the "im_comming_from_some_other_site.aspx" the code would be like:
Page_Load(...)
{
if(verifyAgainstSTS()
{
FormsAuthentication.SetAuthCookie(<some_STS_Userid), ...)
Response.Redirect("default.aspx")
}
else
{
Response.Redirect("http://<STS_server_name/<STS_service...etc>")
}
}
Is there someone who knows if this may be done and how? Any links to example code (if available) deeply appreciated.
(Of course some code would be needed when to determine what to do when the authentication is timed out; either go to local login page or goto STS-login page)
I know this may seem like a bad design, not going all the way with STS, but I need to implement this ASAP and I want to keep the original site as untouched as possible.
It is not a bad design, it's your requirement and you try to fulfill it. We have working system built like that and it's not a rocket science. The only difference is that we switch it to forms/sam statically (via global settings), not dynamically.
Anyway, you keep your forms authentication in web.config so that when there's no authorization for current user, forms redirects the request to the login page.
In the login page you have two options. One creates the forms cookie somehow.
The other option involves WIF's FederatedPassiveSignIn control.
If a user follows forms authentication, the cookie is set and you are done.
If a user follows the STS login control, sooner or later he/she will come back with valid SAML token. The FederatedPassiveSignIn will pick it up automatically and you just handle the redirect in the SignedIn event.
You will even not need the if you mention in your question.
There's one caveat from what I remember. When a user is authenticated by STS, the WS-Federation cookie is created, you can read claims etc. Everything works.
However, if a user is authenticated by forms, the SAM (SessionAuthenticationModule) will REPLACE forms cookie by the WS-Federation cookie in ASP.NET pipeline upon EACH request (I guess it's because the SAM is later in the pipeline that forms authentication module).
This will NOT blow up your context.User.Identity.IsInRole(...) also authorization works correctly because SAM will copy user roles to corresponding claims.
However, if at any place in your code you try to extract information directly from the forms cookie (instead of using general APIs), you could find out that the forms cookie is not present even if the user was authenticated by forms in first place (and the cookie is not present because it will be replaced by the WS-Federation cookie).

global admin page for multiple applications in ASP.Net

I was wondering if anybody could give advice on a secure way to implement a global login. I have an admin page that accesses active directory admin groups after typing in your username and password.
current logged in account (on computer) does not matter
user in web browser goes to web app, redirects to global login page with query string of app name
types user name and password of an account in AD (not necessarily current computers logged in user)
authenticates (looks up user, pass etc and authentication is valid)
redirects back to original web app.
Once redirection happens, how do I securely tell the original web app that this user is ok until the original web session dies?
The way I'm thinking of implementing it:
My original thought was to pass the session ID of original app to the login page as well as the app
name. Store that session in a DB once authentication is checked. Master page of the other app validates on page load that the session ID matches. On session close, remove current session ID from DB.
You cannot depend on sessionID accurately in some cases. SessionID only becomes a constant value after a (any) page makes a request for a session variable, if you dont have Session_Start not defined in global.asax. If you log the user in and the default page does not access session, you will end up with a different session id for the subsequent requests until a request to session is made. Usually it is always constant as there is a default empty session_start event in global.asax.
But similar to your model, you could generate a GUID (or make sure you access session on login/authentication) and store it in the user table with an expiration. Your web sites can check this key and if currently valid, auto sign the user in.
You also cannot depend on session_end event since there is no real accurate way of detecting it (eg: user closing browser). So, you should store this ID with an expiration time along with it, preferably the same as session timeout. Just like session, you will need to extend this, something like a sliding expiration. This way, this id will be expired after a period of inactivity.
also, this Claims-Based Single Sign-On for the Web may be of interest to you.
What you're describing sounds like it would be better implemented using Windows Identity Foundation and Active Directory Federation Services 2.0. I don't know the extent of all your requirements, but it might be valuable to check out what these will give you out of the box.
You could use a cookie. If you pass the name of the application to the login page, you can set that application name to the PATH property of the formsauthentication cookie. By setting the PATH property, you're effectively limiting the readability of the cookie to the pages within that path. Because it's a common login interface, this may require some code being done perhaps in a common page base class that handles the parsing of the cookie information.
You can share authentication tokens between .NET applications, even between .NET CLR's if you want to. I think this will give you the single sign on you're looking for.
At a high level you need to share a machine key between the applications. You can generate the machine key using the key generator app code example found on this link, and providing you then reference the same key in each application the sign on can be shared:
http://msdn.microsoft.com/en-us/library/ms998288.aspx
There are some consideration when looking at things across domains or accross machines/web farms etc, but if all apps are on the same box it's not too hard.
The harder side of things is sharing things like session state which I don't believe can be done accross app pools. (I ended up recreating the session object on the new app manually last time I did it :( but that was between 1.1 and 2.0 apps )
EDIT: I did a rough write up of it last year and was using it as a test for a demo article on my site, might be worth a read through if you want things broken down a bit more (Ignore the unfinished site!):
http://www.dougmcdonald.co.uk/test/html5/v5/articles/2010/05/10/Sharing-forms-authentication-between-applications/

Categories