public class MvcApplication : HttpApplication
{
protected void Application_Start()
{
FormsAuthentication.SetAuthCookie(1.ToString(), true);
}
}
An exception of type 'System.Web.HttpException' occurred in
System.Web.dll but was not handled in user code
Additional information: Request is not available in this context
How else can I automatically login a user without having to do a whole new page request?
What part is confusing you? Forms Auth requires a request in order to work. Part of what it does is send a cookie to the client, and it can't very well do that if there's no client. Application_Start runs outside of the request, so you can't access the request object from there. Even if you could, this isn't run for each request, so it would only work for the first user that caused it to activate.
If you want to do this in a global way, but within the request scope, you'll need to use something like a custom action filter or a custom membership provider. Not sure which would be best for something like or even if an action filter would work, but that's your options.
Related
I'm look at Web API 2 with a project that I created as a "proof of concept". I'm trying to see where I inject my own code for customer authentication. I have an internal auth/login service that I would like to call to determine if login credentials are valid and then get user values (id, roles, etc) if it was valid.
I created the project with "Individual Accounts" as the authentication type but I'm having a hard time figuring out where I'm going to call my service and then map the result to an IdentityUser (or some IUser) object.
In the generated ApplicationOAuthProvider class there is code that passes username and password from a context object like so:
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
using (UserManager<IdentityUser> userManager = _userManagerFactory())
{
IdentityUser user = await userManager.FindAsync(context.UserName, context.Password);
// ...
How do I hook into that call?
You should do this:
Create your own HTTP Message Handler to authenticate the user. You can put your custom code there. This will execute every request, then you can set the credential in the pipeline of the execution.
HTTP Message Handlers
Create or use the default filters to handle the Authorization
Authentication and Authorization in ASP.NET Web API
I have a super simple Authentication Attribute that I'm trying to implement in an ASP.NET MVC 5 application and I'm having some trouble. I want the attribute to be applied globally, except for specific actions within a controller (for example the login form and the home page).
I've tried decorating the action with the [OverrideAuthentication] attribute with no luck. It gives me a redirect loop error because the application is still running the authentication on the login form, and keeps trying to redirect back to the login form over and over.
Has anyone else seen this behaviour? Any idea what I've stuffed up here?
By way of example, I've created a super simple filter that is currently unimplemented:
public class BasicAuthenticationAttribute
: ActionFilterAttribute, IAuthenticationFilter
{
public void OnAuthentication(AuthenticationContext filterContext)
{
throw new NotImplementedException();
}
public void OnAuthenticationChallenge(AuthenticationChallengeContext filterContext)
{
throw new NotImplementedException();
}
}
If I decorate my controller/action like this:
[BasicAuthentication]
public class AccountController : Controller
{
[HttpGet]
[OverrideAuthentication]
public ActionResult Login()
{
return View();
}
}
I get a not implemented exception when I navigate to the Login action, even though that action shouldn't be running the authentication code at all. Have I misunderstood how overrides are supposed to work?
I think you have confused authentication with authorization (as many people do). It doesn't make sense to make a [BasicAuthenticationAttribute] and register it globally, because authentication only happens upon login, not on every request.
Authorization is what takes place after the user has logged in to check whether the user has the required privileges to do a specific action, and it makes sense to do authorization globally. Authorization in MVC is handled by the [AuthorizeAttribute] and you can inherit it if you need to customize the way the authorization check is done. You can also register it as a global filter.
The [AllowAnonymousAttribute] works in conjunction with [AuthorizeAttribute], and basically tells it to skip the authorization check. It should also be noted that the [AllowAnonymousAttribute] will have no effect unless it is used with the [AuthorizeAttribute].
Given that the FormsAuthentication module fires before a custom http module that handles the OnAuthenticateRequest, I'm curious if one can cancel or invalidate the forms authentication based on my own criteria.
Basically I have a process where the user logs in. After that they get a token. I get the token back after the forms authentication fires upon subsequent requests. What I want to do is then validate that the token hasn't expired against our back end server. If it's expired I need to do something so that they are forced to log back in. My thought was to do something in my OnAuthenticateRequest handler that would get picked up later in the pipeline and force a redirect back to login page or something. Is that possible?
In an ASP.NET MVC application in order to handle custom Authentication and Authorization people usually write custom Authorize attributes. They don't deal with any OnAuthenticateRequest events. That's old school. And by the way if you are going to be doing some custom token authentication why even care about Forms Authentication? Why not replace it?
So:
public class MyAuthorizeAttribute: AuthorizeAttribute
{
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
string token = GetTokenFromHttpContext(httpContext);
if (IsTokenValid(token))
{
// The user has provided a valid token => you need to set the User property
// Obviously here based on the token value you already know which is the
// associated user and potential roles, so you could do additional checks
var identity = new GenericIdentity("john.smith");
var user = new GenericPrincipal(identity, new string[0]);
httpContext.User = user;
return true;
}
// Notice that here we are never calling the base AuthorizeCore method
// but you could call it if needed
return false;
}
private string GetTokenFromHttpContext(HttpContextBase httpContext)
{
// TODO: you know what to do here: get the token from the current HTTP Context
// depending on how the client passed it in: HTTP request header, query string parameter, cookie, ...
throw new NotImplementedException();
}
private bool IsTokenValid(string token)
{
// TODO: You know what to do here: go validate the token
throw new NotImplementedException();
}
}
Now all that's left is to decorate your controllers/actions with this custom attribute instead of using the default one:
[MyAuthorize]
public ActionResult SomeAction()
{
// if you get that far you could use the this.User property
// to access the currently authenticated user
...
}
Is that possible?
This is definitely possible. You could even set your autehtication scheme to None so that forms module isn't there in the pipeline and have only your own module.
However, even if forms is there, your custom module can override the identity set for the current request. Note also that until the forms cookie is issued, forms module doesn't set the identity. This was quite common to use both forms module and the SessionAuthenticationModule - forms does the job of redirecting to the login page and the session auth module handles its own authentication cookie.
This means that you can safely mix the two: the forms module and your own custom module for a similar scenario.
Darin suggests another approach and this of course is valid too. An advantage of an authentication module (versus the authentication filter) is that the authentication module could support other ASP.NET subsystems (web forms / wcf / webapi).
I´m have a Car View with a list of car... So, I have a Create button that opens a Modal (UI JQuery Dialog) with Site/Car/Create content...
All works fine... But I´d like to block direct access to : Site/Car/Create...
Is that possible? How?
Thanks
It's not really possible to block it completely, but you can do some things to make it more difficult. First, require that it come from a POST request. That will prevent someone from simply entering the URL with request parameters. Second, use the antiforgery token helper. That will help prevent a third-party from doing a POST to the url since they will also require both the token input and the token cookie. Third, you could potentially check if the request has the X-HTTP-REQUESTED-WITH header and only do the POST (or GET) via AJAX. It's not that hard to get around but it would prevent an accidental access if you do use GET. Fourth, and it probably should have been first, make sure that only authorized users have access to the action using the AuthorizeAttribute. Fifth, use SSL to prevent unauthorized access using FireSheep and protect your cookies and data from snooping.
In short, you won't be able to prevent a determined person with legitimate authorization from crafting a request to the action if they a really want to without using your interface. They can always craft a request that will look exactly like the one you would send. You can make it more difficult and prevent accidental access, though, using the above methods.
[AttributeUsage(AttributeTargets.Method)]
public class AjaxOnlyAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (!filterContext.HttpContext.Request.IsAjaxRequest())
{
filterContext.HttpContext.Response.StatusCode = 404;
filterContext.Result = new HttpNotFoundResult();
}
else
{
base.OnActionExecuting(filterContext);
}
}
}
And then stick on your Create action like this:
[AjaxOnly]
public ActionResult Create()
{
...etc
}
Where do I get information about the currently connected user? That is, how does shibboleth pass the information?
Can I set some restrictions on actions using [Authorize] attribute based on data acquired from shibboleth?
Shibboleth publishes user attributes associated with
sessions into HTTP request headers, based on header names defined
in Attribute Acceptance Policy (1.3.x) or Attribute Mapping (2.x)
files. These headers are transformed into CGI variables based
on mapping rules defined by the CGI specification.
You should be aware of this security advisory:
http://shibboleth.net/community/advisories/secadv_20090615.txt
I have never user shibboleth, but you can get information about the user from Controller.User property. It will return a generic principal of current thread. Using this principal you can check whether the user is authenticated and get a login name of the user. This is due to the reason that after logon an authentication cookie is set and this cookie contains limited amount of information. And on each request after logon only this cookie is checked (if it exists and valid - user is authenticated).
So if you need in some specific information you can manually load a user (it's better to use cache here) and check whatever you want.
Also you can create and attach your own principal with necessary information to the thread on start of a request (e.g. on start of a request load the user from db/cache using user name from base principal, create and set your own principal to thread). After this you can check all properties of the user you need.
Where would you attach your own principal? You say on the start of the request but what if you don't want every request authorizing?
You'll want to create a method in Global.asax.cs that has the following signature
protected void Application_PostAuthenticateRequest()
{
//Your code here.
}
This will be called automatically before almost anything else is done (MVC will call this method if it exists, you don't have to "turn it on" anywhere), and this is where you need to set the Principal. For instance, let's assume you have a header called RolesHeader that has a comma separated value of roles and another header called UserId that has (duh) the user ID.
Your code, without any error handling, might look something like:
protected void Application_PostAuthenticateRequest()
{
var rolesheader = Context.Request.Headers["RolesHeader"];
var userId = Context.Request.Headers["UserId"];
var roles = rolesheader.Split(',');
var principal = new GenericPrincipal(new GenericIdentity(userId), roles);
Context.User = principal;
}
It's the Principal/Identity that the [Authorize] attribute uses, so setting it here at the beginning of the request lifecycle means the [Authorize] attribute will work correctly.
The rest of this is optional, but I recommend it:
I like to create my own custom classes that implement IPrincipal and IIdentity instead of using the GenericPrincipal and GenericIdentity, so I can stuff more user information in it. My custom Principal and Identity objects then have much more rich information, such as branch numbers or email addresses or whatever.
Then, I create a Controller called BaseController that has the following
protected new CustomPrincipal User
{
get
{
return (base.User as CustomPrincipal) ?? CustomPrincipal.GetUnauthorizedPrincipal();
}
}
This allows me to access all my rich, custom Principal data instead of just what's defined in IPrincipal. All of my real controllers then inherit from BaseController instead of directly from Controller.
Obviously, when using a custom Principal like this, in the Application_PostAuthenticateRequest() method, you'd set the Context.User to be your CustomPrincipal instead of a GenericPrincipal.