I have an application that should be open to the Internet at the time of development. The application has its own authorization (forms).
We can not restrict access to the server over a range of IP addresses. We also need the site to behave similarly as in the absence of global access check (QA test application in this environment).
How to access can be arranged at IIS?
User steps:
Go to site.com
User sees a pop-up window (global user name; global password - the same for all users)
Redirect to site (as anonymous user)
Go to login page and enter local user name and password (specific for current user)
I will be grateful for any advice
Thanks
Create filter (inherit from ActionFilterAttribute)
Override OnActionExecuting method (check custom cookie). If custom auth cookie absent:
filterContext.HttpContext.Response.Clear();
filterContext.HttpContext.Response.StatusDescription = "Unauthorized";
filterContext.HttpContext.Response.AddHeader("WWW-Authenticate", "Basic realm=\"Secure Area\"");
filterContext.HttpContext.Response.Write("401, please authenticate");
filterContext.HttpContext.Response.StatusCode = 401;
filterContext.Result = new EmptyResult();
filterContext.HttpContext.Response.End();
base.OnActionExecuting(filterContext);
Register filter in Global.asax in Application_Start()
Related
We have a web app that runs on our corporate intranet. I get the following error when I try to access a network path in my MVC controller:
Access to the path '\Server001\SharedFiles\CA' is denied.
The App is hosted on IIS and app pool is set to ApplicationPoolIdentity. I do not want to set it with an account that has access right to all the directories. I'd like each user to only access the folders they're allowed to.
After some research I figured the only way is to programmatically impersonate the user when it's needed. To test this out, I created a New ASP.NET Core 6 MVC project with Authentication set to Windows(Also enabled Windows Authentication in IIS site). Then I added the following code to my controller:
public async Task<IActionResult> Index()
{
// The user used as Log On as for the Windows Service
var serviceUser = WindowsIdentity.GetCurrent();
// returns "IIS APPPOOL\MvcTest"
// The user to be impersonated
// COMPANYDOMAIN\MyName
var userToImpersonate = (WindowsIdentity)HttpContext.User.Identity;
await WindowsIdentity.RunImpersonatedAsync(userToImpersonate.AccessToken, async () =>
{
var ImpersonatedUser = WindowsIdentity.GetCurrent();
_logger.LogInformation(ImpersonatedUser.ImpersonationLevel.ToString());
// returns "impersonate"
_logger.LogInformation(ImpersonatedUser.Name);
// Here we are getting "COMPANYDOMAIN\MyName"
try
{
var files = Directory.GetFiles("\\\\Server001\\SharedFiles\\CA");
return View(files);
}
catch (Exception ex) { }
});
}
Although this shows that WindowsIdentity.GetCurrent().Name has changed to my domain account(what I logged in as) but for some reason it is not accepting the impersonated user. I still get access denied error. Is this permission issues?
I am able to browse the "\Server001\SharedFiles" using my domain account(COMPANYDOMAIN\MyName), Also when I change the app pool identity to my domain account, the app still works.
If WindowsIdentity.GetCurrent().Name shows the correct user, then your impersonation is likely working correctly.
File shares in Windows have two sets of permissions that define what a user can do:
The share permissions. This defines who is allowed to access the folder remotely. These are set in the same place where you initially setup the share.
File system permissions. These are the normal file permissions that you would think of.
Make sure that both the share permissions and the file system permissions allow the user access. It is possible for the file system permissions to allow someone full control, but the share permissions to deny them any access. In that case they could access and modify any files locally, but couldn't do anything through the share.
I would usually set the share permissions to Read/Write for Everyone and then use the file system permissions to restrict access.
I have a Blazor website (IdentityApp) that includes scaffolded ASP.NET identity integration. That website is processing logins and setting a shared cookie that my other localhost Blazor application (LogicApp) can see.
When I access LogicApp (https://localhost:9876), I check the context for a recognised user (using the shared cookie) and then manually redirect anonymous users to the scaffolded IdentityApp login page: https://localhost:1234/identity/account/login.
I also pass through the fully encoded URL of LogicApp home page in the returnUrl, for example; https://localhost:1234/identity/account/login?returnUrl=https%3A%2F%2Flocalhost%3A9876%2F
The login process is working OK (the shared cookie is set correctly), but then I get an exception;
InvalidOperationException: The supplied URL is not local. A URL with an absolute path is considered local if it does not have a host/authority part. URLs using virtual paths ('~/') are also local.
Within ASP.NET Identity (.NET Core 3.1);
How can I configure IdentityApp to allow full urls within returnUrl?
or,
How can I override the scaffolded Login logic to take control of the redirect and use my returnUrl value?
So I found an answer to my own problem (but still interested to hear of alternative solutions)..
Within the scaffolded pages locate Login.cshtml.cs and replace the reference to LocalRedirect(...) in in the OnPostAsync(string returnUrl = null) method, for example;
...
if (result.Succeeded)
{
_logger.LogInformation("User logged in.");
//return LocalRedirect(returnUrl); // remove this.
return Redirect(returnUrl); //TODO: define a list of acceptable return Urls (localhost / yourdomain.com etc)
}
...
You may also need to do this in Login2FA.cshtml.cs as well as other places that deal with this ReturnUrl value.
NOTE: LocalRedirect is used to prevent malicious redirects occurring so it would be wise to also add some logic to check the returnUrls that have been passed in.
I have installed "Domino Sample REST Service Feature" from 901v00_11.20141217-1000 version of XPages Extension Library. OpenNtfSample service (com.ibm.domino.services.sample.service.SampleService) works as it should in general and the only problem with it that it completely ignores authentication settings of the server.
I have tried both Basic and Session Authentication as described in Authenticating Domino REST Service Requests and the result I get is the following - the service returns data always and does not ask for any user name and password.
The server is configured with Session Authentication now and I get password prompt when I try to access
{my_server}/api/data
but does not get it when I open
{my_server}/api/sample
After I had added this Web Site Rule
Description: DAS service
Type of rule: Override Session Authentication
Incoming URL pattern: /api/
the server changed password prompt for
{my_server}/api/data
but
{my_server}/api/sample
remained open.
Has anybody experienced this kind of error? Can anybody help me password protect this sample service so that I could start developing my own once based this example?
The /api/sample resource is wide open on purpose. That just returns a link to the contacts resource -- /xpagesext.nsf/api/sample/contacts.
If you really want to prevent anonymous access to the /api/sample resource, there are two possible solutions: 1) Disable anonymous access for all HTTP requests, or 2) Make a change to the RootResource class. The first solution is a server config change. I'm sure you can find details about that elsewhere. Since this is StackOverflow, I'll focus on the second solution.
As you have already noticed, we don't allow anonymous access to the /api/data resource. You can mimic that behavior in the /api/sample resource with a simple change to RootResource.getLinks(). Near the top of the method, just add these lines of code:
boolean authenticated = false;
Session session = ContextInfo.getUserSession();
if ( session != null ) {
String userName = session.getEffectiveUserName();
if ( userName != null && !userName.equals("Anonymous")) {
authenticated = true;
}
}
if ( !authenticated ) {
throw new NoAccessSignal("Need user context");
}
By the way, you won't need to make the same change to the contacts resource class (ContactsListResource.java). Because the contacts resource URL includes a database name (xpagesext.nsf), the web server will attempt to open the database before forwarding the request to the REST service. You can prevent anonymous access to the contacts resource by changing the ACL of xpagesext.nsf. Just make sure the default access is "No access".
I'm trying to have a MVC5 webapp which partially uses Windows Auth.
What I mean by that is, it's effectively forms/cookie based auth, but with the requesting user's Windows principal forming a part of their login credentials.
For example, the login page will say, "You have been identified as somedomain\kierenj. Please enter the secret code to log in." If they enter the correct code, the cookie is set and they're logged in.
If Windows auth fails, then the login page would still appear, but be disabled.
I've experimented with a WindowsPrincipalHanlder like this: https://github.com/JabbR/JabbR/blob/master/JabbR/Middleware/WindowsPrincipalHandler.cs
The gist of it is, if I enable Windows Authentication and disabled Anonymous Authentication, then Owin (or presumably the cookie auth part of it) redirects to the login page - which redirects to the login page - it's a redirect loop.
Note I'm using a very simplified Owin setup. UseCookieAuthentication with ApplicationCookie type and a LoginPath specified; then I call SignIn like this from my account controller:
var claims = new[] {
new Claim(ClaimTypes.Name, "Username"),
new Claim(ClaimTypes.Role, "AuthenticatedUser")
};
AuthenticationManager.SignIn(new ClaimsIdentity(claims, DefaultAuthenticationTypes.ApplicationCookie));
(Having first checked WindowsIdentity.GetCurrent() for example)
Do I really need to write my own version of the Owin cookie auth middleware? Can I get the source so I can debug/derive?
To avoid the redirect loop, in the constructor of the controller that serves the Login page, try setting current HttpContext's Response.SuppressFormsAuthenticationRedirect to true
Is it possible to Impersonate a user when using Forms Authentication?
The thing is that I want an external login for users and an internal site that just uses integrated windows security and the users need to be impersonated.
I've looked around and found that John's answer here is really good, but I don't quite get how I can mix it up with my Forms authentication.
Suggestions?
Edit
I want to have an <asp:Login /> control and this control will authenticate against an Active Directory which has the same set of users as the Windows Machine that I want to use impersonation on.
My problem is that I don't get how I can impersoante with the same username and pasword that is provided to the <asp:Login /> control.
In order for that solution to work, you'll need access to the user's id and password. I don't believe that you can get this using the Login user control; you'll need to create your own login form and handle the login actions yourself. Keep the user's id and password, preferably in a secure string, in the session once you've authenticated and when you need to access the internal site on their behalf, use the Impersonator class from the referenced example to impersonate them using the credentials.
using (var context = Impersonator.LogOn( username, password ))
{
try
{
....
}
finally
{
context.Undo();
}
}