How to do rule-based authorization with Spring Security in Grails? - grails

Spring Security is great for doing role-based authorization, but it seems to fall short when it comes to rule-based authorization. Sure, there are ways to do it via SpEL, but going that route seems to lock your authorization logic inside the annotations when it would be much better to pull that logic out into a service so that multiple places can use the same logic.
There seem to be some ways to go about adding in your own SpEL expressions, but noting is particularly clear, and even those that make sense to me seem to fall short. I would think, given how flexible Groovy is, that there must be some way to not have to hard-code the dependencies together, but to have the security rules (or SpEL extensions) picked up at run-time.
While not ideal, even something as seemingly simple as defining all of the desired new rules and injecting the as mixins (ie. SecurityExpressionRoot.mixin MyRule1) would be a good start, but that doesn't seem to work.
Does anyone know of an example that does this? If not, how might I go about doing this myself?
One (simplified) example : A user can only take a particular action (ie. execute a service method) with an object if 3 of 4 fields have values over a particular threshold, but only if the object is less than 3 days old:
class MyRule {
boolean canTakeAction(Person person, MyThing myThing) {
int numFieldsWithValues = 0
if (myThing.field1 != null) { numFieldsWithValues++ }
if (myThing.field2 != null) { numFieldsWithValues++ }
if (myThing.field3 != null) { numFieldsWithValues++ }
if (myThing.field4 != null) { numFieldsWithValues++ }
return (numFieldsWithValues > 3) && (ageInDays(myThing) < 3)
}
int ageInDays(MyThing myThing) {
...
}
}
And that is one of the simpler rules.

Role based authorization is the easiest but less flexible way. The contrast to this is the Spring security ACL system. ACLs are let you define exaclty who is allowed to do what on which object at runtime. On the other side this requires a much more complicated setup. There is also a grails plugin for this.
The way of using annotions with SpEL expressions is somewhere between these both alternatives. They are more flexible than simple roles and easier than ACLs. If you are looking for an introduction to method security in Grails maybe this blog post I wrote some time ago can help you.

You can manage your rule in Requestmap, which provides dynamic configuration capability.
For instance, define security type as requestmap in config.groovy first:
grails.plugins.springsecurity.securityConfigType = "Requestmap"
Then you may have Requestmap domain class similar to User and Role, like this:
package com.app.auth
class Requestmap {
String url
String configAttribute
static mapping = {
cache true
}
static constraints = {
url blank: false
configAttribute blank: false
}
}
Now since User, Role, and Reqestmap are all persisted in database, you can easily change your rules by CRUD actions in some controller without need to redeploy or restart your service. Like this:
class RequestmapController {
def springSecurityService
...
def save = {
def requestmapInstance = new Requestmap(params)
if (!requestmapInstance.save(flush: true)) {
render view: 'create', model: [requestmapInstance: requestmapInstance]
return
}
springSecurityService.clearCachedRequestmaps() //This is important: to refresh the requestmap. Without it the rules remain unchanged.
flash.message = "${message(code: 'default.created.message', args: [message(code: 'requestmap.label', default: 'Requestmap'), requestmapInstance.id])}"
redirect action: show, id: requestmapInstance.id
}
}
In the view layer, you can manage your menus, buttons, and other elements need authorization by using spring security tag like:
<sec:access url="foo/bar">
<li><g:link class="list" controller="foo" action="bar">Bar action</g:link></li>
</sec:access>
Therefore, the views are also comply with the authorization rule.
Furthermore, there is a Hierarchical Roles feature which can be leveraged to reduce clutter in your request mappings.

From the example you posted, GContracts might be what you're looking for. You'd just have to figure out how to access the Principal when running a GContract closure, but that might be just as simple as passing it as a parameter to the contracted method.

Related

HTTP Method Security

I'm working on building a simple HATEOAS REST service with Spring Boot.
I have a MongoDB repository and resource where I would like to allow GET, but disallow all else. (POST, UPDATE DELETE, etc.)
The general idea is to allow a "USER" to do as it wishes with the resoure and allow "PUBLIC" read-only access.
#RepositoryRestResource(collectionResourceRel = "people", path = "people")
public interface PersonRepository extends MongoRepository<Person, String>
{
#Secured("ROLE_USER")
public void delete(Person person);
#Secured("ROLE_USER")
public Person save(Person person);
#Secured("ROLE_USER, ROLE_PUBLIC")
public Person findOne(String id);
}
I don't feel I'm approaching this at the right angle. What's the preferred way of doing this?
I'm guessing you're using spring-data-rest and skipping controllers entirely.
First thing you're having a problem with is that #Secured takes an array of roles...so i think your check on findOne is looking for a role ROLE_USER, ROLE_PUBLIC not either of those roles. Changing it to:
#Secured({"ROLE_USER", "ROLE_PUBLIC"})
might solve your problems.
After that you have a few options to consider
Option 1: Switch to ROLE_ANONYMOUS instead of ROLE_PUBLIC which is the default role anonymous users are assigned in Spring Web w/ spring security.
Option 2: Make sure anonymous users have the ROLE_PUBLIC (which they won't by default, they have ROLE_ANONYMOUS by default). There's a lot of ways to do this, see http://docs.spring.io/spring-security/site/docs/3.0.x/reference/anonymous.html
Option 3: Switch to #PreAuthorize annotations for securing methods and use the EL expression like:
#PreAuthorize("hasRole('ROLE_USER') or isAnonymous()")
see http://docs.spring.io/spring-security/site/docs/3.0.x/reference/el-access.html note you have to enable pre-post annotation processing.
Final note, ROLE_USER is not a default role...it's DEFAULT_USER for most stuff.
this is a very open ended question and there's a lot of solutions, you'd have to give more context as to your desires to narrow it down.

Do I have to use webflows?

I want to collect the data for a domain class over a few forms. I'd like to initialise an instance of the domain, carry it through the form pages (assigning the collected data to the properties of the instance) and save the instance after the last form is completed successfully.
Is there a way to do this without webflows?
Is there a way to do this without webflows?
You can use hidden fields to accomplish this. But I may prefer you to use Webflows.
Here are some advantages of using Webflows:
1)You got two new scopes flow and conversation allows you to store variables, which are accessed within your flow
2)You have simple DSL to keep things tidy
3)Since there is a flow scope, you can do something like this:
flow.someThing = new YourClassName(params) //places object in flow scope
Keep in Mind:
1)If you use flow-scoped objects your class need to be implemented Serializable class.
2)And from Grails 1.2, you need to install Webflow plugin explicitly. Document says this:
From Grails 1.2 onwards Webflow is no longer in Grails core, so you
must install the Webflow plugin to use this feature: grails
install-plugin webflow
(see here).
As an alternative to Ant's comment, you could use the session, but storing a non-domain object or a simple Map. This will definitely lead to a lot of extra complexity, and the webflows do provide a lot of protection against accidental back-buttons, etc.
Rough idea:
in grails-app/domain
class Widget {
String name
int id
// constraints, etc
}
in grails-app/controllers
class WidgetCommand {
// setup your command
}
class WidgetController {
def savePage1 = { WidgetCommand cmd ->
// validate, etc
def widget = session.tempWidget ?: [:]
widget.putAll(cmd.properties)
session.tempWidget = widget
[widget: widget]
}
def savePage2 = { WidgetCommand cmd ->
// etc
}
def savePage3 = {
// or something similar here
def finalWidget = new Widget(session.tempWidget)
finalWidget.save()
}
}
You could try storing an actual domain object directly in memory, but I believe that will automatically be saved at session close if you are editing the object (as opposed to new ones), and you'll have to re-link it to the Hibernate session.

Grails Plugins Requiring External Relationships

I posted this on the Grails mailing list yesterday and haven't had any hits. Figured I'd try here as well today.
I'm considering writing a grails plugin but this plugin would require some sort of relationship to an account / user object. However, I don't want to force a particular security model on the plugin. For example, say was writing a comment system plugin (I'm not). I'd have a comment object...
class Comment {
String comment
Date dateCreated
// etc etc
}
The comment is missing a couple of things:
Who added the comment
What the comment was added to.
I'd like to first focus on #1. So someone might be using the Spring security plugin and use the default Person object, or maybe they changed that to User. Who knows. Is there any way that anyone can think of to configure that relationship without hard coding it in the plugin?
One thing I've thought about was to have the grails app extend the plugin's domain classes to add this relationship. so I might do something like...
class ArticleComment extends Comment {
static belongsTo = [user:User]
}
But in a larger plugin, that might be a lot of inheritance requirements. Not the end of the world, but just looking for other possible options.
You can use the same technique employed by the Commentable plugin:
The user of your plugin will need to declare a closure in Config.groovy to evaluate the logged user:
grails.myplugin.user.evaluator = { session.user }
And you can use something like this in your plugin's code to call the user configured closure:
def evaluateUser() {
def evaluator = grailsApplication.config.grails.myplugin.user.evaluator
def user
if(evaluator instanceof Closure) {
evaluator.delegate = this
evaluator.resolveStrategy = Closure.DELEGATE_ONLY
user = evaluator.call()
}
if(!user) {
throw new Exception("No [grails.myplugin.user.evaluator] setting defined or the evaluator doesn't evaluate to an entity. Please define the evaluator correctly in grails-app/conf/Config.groovy")
}
if(!user.id) {
throw new Exception("The evaluated user is not a persistent instance.")
}
return user
}
I think you can do it like SpringSecurity do. Instead of let people extend your Comment class, You can write 2 class CommentUser & CommentPlace; then let others extends them. I think it's more simple.

Access Control in ASP.NET MVC depending on input parameters / service layer?

Preamble: this is a bit of a philosophical question. I'm looking more for the "right" way to do this rather than "a" way to do this.
Let's imagine I have some products, and an ASP.NET MVC application performing CRUD on those products:-
mysite.example/products/1
mysite.example/products/1/edit
I'm using the repository pattern, so it doesn't matter where these products come from:-
public interface IProductRepository
{
IEnumberable<Product> GetProducts();
....
}
Also my Repository describes a list of Users, and which products they are managers for (many-many between Users and Products). Elsewhere in the application, a Super-Admin is performing CRUD on Users and managing the relationship between Users and the Products they are permitted to manage.
Anyone is allowed to view any product, but only users who are designated as "admins" for a particular product are allowed to invoke e.g. the Edit action.
How should I go about implementing that in ASP.NET MVC? Unless I've missed something, I can't use the built-in ASP.NET Authorize attribute as first I'd need a different role for every product, and second I won't know which role to check for until I've retrieved my Product from the Repository.
Obviously you can generalise from this scenario to most content-management scenarios - e.g. Users are only allowed to edit their own Forum Posts. StackOverflow users are only allowed to edit their own questions - unless they've got 2000 or more rep...
The simplest solution, as an example, would be something like:-
public class ProductsController
{
public ActionResult Edit(int id)
{
Product p = ProductRepository.GetProductById(id);
User u = UserService.GetUser(); // Gets the currently logged in user
if (ProductAdminService.UserIsAdminForProduct(u, p))
{
return View(p);
}
else
{
return RedirectToAction("AccessDenied");
}
}
}
My issues:
Some of this code will need to be repeated - imagine there are several operations (Update, Delete, SetStock, Order, CreateOffer) depending on the User-Products relationship. You'd have to copy-paste several times.
It's not very testable - you've got to mock up by my count four objects for every test.
It doesn't really seem like the controller's "job" to be checking whether the user is allowed to perform the action. I'd much rather a more pluggable (e.g. AOP via attributes) solution. However, would that necessarily mean you'd have to SELECT the product twice (once in the AuthorizationFilter, and again in the Controller)?
Would it be better to return a 403 if the user isn't allowed to make this request? If so, how would I go about doing that?
I'll probably keep this updated as I get ideas myself, but I'm very eager to hear yours!
Thanks in advance!
Edit
Just to add a bit of detail here. The issue I'm having is that I want the business rule "Only users with permission may edit products" to be contained in one and only one place. I feel that the same code which determines whether a user can GET or POST to the Edit action should also be responsible for determining whether to render the "Edit" link on the Index or Details views. Maybe that's not possible/not feasible, but I feel like it should be...
Edit 2
Starting a bounty on this one. I've received some good and helpful answers, but nothing that I feel comfortable "accepting". Bear in mind that I'm looking for a nice clean method to keep the business logic that determines whether or not the "Edit" link on the index view will be displayed in the same place that determines whether or not a request to Products/Edit/1 is authorised or not. I'd like to keep the pollution in my action method to an absolute minimum. Ideally, I'm looking for an attribute-based solution, but I accept that may be impossible.
First of all, I think you already half-way figured it, becuase you stated that
as first I'd need a different role for every product, and second I won't know which role to check for until I've retrieved my Product from the Repository
I've seen so many attempts at making role-based security do something it was never intended to do, but you are already past that point, so that's cool :)
The alternative to role-based security is ACL-based security, and I think that is what you need here.
You will still need to retrieve the ACL for a product and then check if the user has the right permission for the product. This is so context-sensitive and interaction-heavy that I think that a purely declarative approach is both too inflexible and too implicit (i.e. you may not realize how many database reads are involved in adding a single attribute to some code).
I think scenarios like this are best modeled by a class that encapsulates the ACL logic, allowing you to either Query for decision or making an Assertion based on the current context - something like this:
var p = this.ProductRepository.GetProductById(id);
var user = this.GetUser();
var permission = new ProductEditPermission(p);
If you just want to know whether the user can edit the product, you can issue a Query:
bool canEdit = permission.IsGrantedTo(user);
If you just want to ensure that the user has rights to continue, you can issue an Assertion:
permission.Demand(user);
This should then throw an exception if the permission is not granted.
This all assumes that the Product class (the variable p) has an associated ACL, like this:
public class Product
{
public IEnumerable<ProductAccessRule> AccessRules { get; }
// other members...
}
You might want to take a look at System.Security.AccessControl.FileSystemSecurity for inspiration about modeling ACLs.
If the current user is the same as Thread.CurrentPrincipal (which is the case in ASP.NET MVC, IIRC), you can simplyfy the above permission methods to:
bool canEdit = permission.IsGranted();
or
permission.Demand();
because the user would be implicit. You can take a look at System.Security.Permissions.PrincipalPermission for inspiration.
From what you are describing it sounds like you need some form of user access control rather than role based permissions. If this is the case then it needs to be implemented throughout your business logic. Your scenario sounds like you can implement it in your service layer.
Basically you have to implement all functions in your ProductRepository from the perspective of the current user and the products are tagged with permissions for that user.
It sounds more difficult than it actually is. First off you need a user token interface that contains the user information of uid and role list (if you want to use roles). You can use IPrincipal or create your own along the lines of
public interface IUserToken {
public int Uid { get; }
public bool IsInRole(string role);
}
Then in your controller you parse the user token into your Repository constructor.
IProductRepository ProductRepository = new ProductRepository(User); //using IPrincipal
If you're using FormsAuthentication and a custom IUserToken then you can create a Wrapper around the IPrincipal so your ProductRepository is created like:
IProductRepository ProductRepository = new ProductRepository(new IUserTokenWrapper(User));
Now all your IProductRepository functions should access the user token to check permissions. For example:
public Product GetProductById(productId) {
Product product = InternalGetProductById(UserToken.uid, productId);
if (product == null) {
throw new NotAuthorizedException();
}
product.CanEdit = (
UserToken.IsInRole("admin") || //user is administrator
UserToken.Uid == product.CreatedByID || //user is creator
HasUserPermissionToEdit(UserToken.Uid, productId) //other custom permissions
);
}
If you wondering about getting a list of all products, in your data access code you can query based on permission. In your case a left join to see if the many-to-many table contains the UserToken.Uid and the productId. If the right side of the join is present you know the user has permission to that product and then you can set your Product.CanEdit boolean.
Using this method you can then use the following, if you like, in your View (where Model is your Product).
<% if(Model.CanEdit) { %>
Edit
<% } %>
or in your controller
public ActionResult Get(int id) {
Product p = ProductRepository.GetProductById(id);
if (p.CanEdit) {
return View("EditProduct");
}
else {
return View("Product");
}
}
The benefit to this method is that the security is built in to your service layer (ProductRepository) so it is not handled by your controllers and cannot be bypassed by your controllers.
The main point is that the security is placed in your business logic and not in your controller.
The copy paste solutions really become tedious after a while, and is really annoying to maintain. I would probably go with a custom attribute doing what you need. You can use the excellent .NET Reflector to see how the AuthorizeAttribute is implemented and perform your own logic to it.
What it does is inheriting FilterAttribute and implementing IAuthorizationFilter. I can't test this at the moment, but something like this should work.
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true, AllowMultiple = true)]
public class ProductAuthorizeAttribute : FilterAttribute, IAuthorizationFilter
{
public void OnAuthorization(AuthorizationContext filterContext)
{
if (filterContext == null)
{
throw new ArgumentNullException("filterContext");
}
object productId;
if (!filterContext.RouteData.Values.TryGetValue("productId", out productId))
{
filterContext.Result = new HttpUnauthorizedResult();
return;
}
// Fetch product and check for accessrights
if (user.IsAuthorizedFor(productId))
{
HttpCachePolicyBase cache = filterContext.HttpContext.Response.Cache;
cache.SetProxyMaxAge(new TimeSpan(0L));
cache.AddValidationCallback(new HttpCacheValidateHandler(this.Validate), null);
}
else
filterContext.Result = new HttpUnauthorizedResult();
}
private void Validate(HttpContext context, object data, ref HttpValidationStatus validationStatus)
{
// The original attribute performs some validation in here as well, not sure it is needed though
validationStatus = HttpValidationStatus.Valid;
}
}
You could probably also store the product/user that you fetch in the filterContext.Controller.TempData so you can fetch it in the controller, or store it in some cache.
Edit: I just noticed the part about the edit link. The best way I can think of is factoring out the authorization part from the attribute and make a HttpHelper for it that you can use in your view.
I tend to think that authorization is part of your business logic (or at least outside of your controller logic anyway). I agree with kevingessner above, in that the authorization check should be part of the call to fetch the item. In his OnException method, you could show the login page (or whatever you have configured in the web.config) by something like this:
if (...)
{
Response.StatusCode = 401;
Response.StatusDescription = "Unauthorized";
HttpContext.Response.End();
}
And instead of making UserRepository.GetUserSomehowFromTheRequest() calls in all the action methods, I would do this once (in an override of the Controller.OnAuthorization method for example), then stick that data somewhere in your controller base class for later use (e.g. a property).
I think that it's unrealistic, and a violation of the separation of concerns, to expect to have controller/model code control what the view renders. The controller/model code can set a flag, in the view model, that the view can use to determine what it should do, but I don't think that you should expect a single method to be used by both controller/model and view to control both access to and rendering of the model.
Having said that you could approach this in either of two ways -- both would involve a view model that carries some annotations used by the view in addition to the actual model. In the first case, you can use an attribute to control access to the action. This would be my preference, but would involve decorating each method independently -- unless all of the actions in a controller have the same access attributes.
I've developed a "role or owner" attribute for just this purpose. It verifies that the user is in a particular role or is the owner of the data being produced by the method. Ownership, in my case, is controlled by the presence of a foreign key relationship between the user and the data in question -- that is, you have a ProductOwner table and there needs to be a row containing the product/owner pair for the product and current user. It differs from the normal AuthorizeAttribute in that when the ownership or role check fails, the user is directed to an error page, not the login page. In this case, each method would need to set a flag in the view model that indicates that the model can be edited.
Alternatively, you could implement similar code in the ActionExecuting/ActionExecuted methods of the controller (or a base controller so that it applies consistently across all controllers). In this case, you would need to write some code to detect what kind of action is being executed so you know whether to abort the action based on the ownership of the product in question. The same method would set the flag to indicate that the model can be edited. In this case, you'd probably need a model hierarchy so you could cast the model as an editable model so that you can set the property regardless of the specific model type.
This option seems more coupled to me than using the attribute and arguably more complicated. In the case of the attribute you can design it so that it takes the various table and property names as attributes to the attribute and uses reflection to get the proper data from your repository based on the attribute's properties.
Answering my own question (eep!), Chapter 1 of Professional ASP.NET MVC 1.0 (the NerdDinner tutorial) recommends a similar solution to mine above:
public ActionResult Edit(int id)
{
Dinner dinner = dinnerRepositor.GetDinner(id);
if(!dinner.IsHostedBy(User.Identity.Name))
return View("InvalidOwner");
return View(new DinnerFormViewModel(dinner));
}
Asides from making me hungry for my dinner, this doesn't really add anything as the tutorial goes on to repeat the code implementing the business rule immediately in the matching POST Action Method, and in the Details view (actually in a child partial of the Details view)
Does that violate SRP? If the business rule changed (so that e.g. anyone who had RSVP'd could edit the dinner), you'd have to change both GET and POST methods, and the View (and the GET and POST methods and View for the Delete operation too, although that's technically a seperate business rule).
Is pulling the logic out into some kind of permissions arbitrator object (as I've done above) as good as it gets?
You're on the right track, but you can encapsulate all of the permission check into a single method like GetProductForUser, which takes a product, user, and the required permission. By throwing an exception that's caught in the controller's OnException handler, the handling is all in one place:
enum Permission
{
Forbidden = 0,
Access = 1,
Admin = 2
}
public class ProductForbiddenException : Exception
{ }
public class ProductsController
{
public Product GetProductForUser(int id, User u, Permission perm)
{
Product p = ProductRepository.GetProductById(id);
if (ProductPermissionService.UserPermission(u, p) < perm)
{
throw new ProductForbiddenException();
}
return p;
}
public ActionResult Edit(int id)
{
User u = UserRepository.GetUserSomehowFromTheRequest();
Product p = GetProductForUser(id, u, Permission.Admin);
return View(p);
}
public ActionResult View(int id)
{
User u = UserRepository.GetUserSomehowFromTheRequest();
Product p = GetProductForUser(id, u, Permission.Access);
return View(p);
}
public override void OnException(ExceptionContext filterContext)
{
if (typeof(filterContext.Exception) == typeof(ProductForbiddenException))
{
// handle me!
}
base.OnException(filterContext);
}
}
You just have to provide ProductPermissionService.UserPermission, to return a user's permission on a given product.By using a Permission enum (I think I've got the right syntax...) and comparing permissions with <, Admin permissions imply Access permissions, which is pretty much always right.
You can use a XACML based implementation. This way you can externalize authorization and also have a repository for your policies outside of your code.

Binding action parameters to request cookies in ASP.NET MVC - what happened?

In several early previews of ASP.NET MVC, arguments to controller methods would be resolved by inspecting the query string, then the form, then the cookies and server variables collections, as documented in this post from Stephen Walther.
For example, this code used to work:
public class MyController : Controller {
// This should bind to Request.Cookies["userId"].Value
public ActionResult Welcome(int userId) {
WebUser wu = WebUser.Load(userId);
ViewData["greeting"] = "Welcome, " + wu.Name;
return(View());
}
}
but now running against the release candidate, it throws an exception because it can't find a value for userId, even though userId definitely appears in the request cookies.
Was this change covered anywhere in the release notes? If this is a change to the framework, is there now a recommended alternative to binding cookies and server variables in this way?
EDIT: Thanks to those of you who have responded so far. I may have picked a bad example to demonstrate this; our code uses cookies for various forms of "convenient" but non-essential persistence (remembering ordering of search results, that kind of thing), so it's by no means purely an authentication issue. The security implications of relying on user cookies are well documented; I'm more interested in current recommendations for flexible, easily testable techniques for retrieving cookie values. (As I'm sure you can appreciate, the above example may have security implications, but is very, very easy to test!)
I believe it was the security implications that persuaded them to take these out:
The comments in Stephen Walther's post ASP.NET MVC Tip 15, leading to Phil Haack's posting User Input in Sheep's Clothing, especially his comment here:
#Troy - Step one is to dissuade devs from that line of thinking in the first place. ;) Step one prime (in parallel) is for us to remove the possibility of this line of thinking in this case.
The larger point still stands, we can make this change (after discussing it, we probably will), but that doesn't mean that it's suddenly safe to trust action method parameters.
Coupled with the complications of how you would call these methods from the various action builder classes.
I can't seem to find any explicit documentation one way or another about the controllers behaving like this other than Stephen's post, so I guess it was "quietly dropped".
I don't believe the cookies are checked anymore, and I'm not sure if it is intentional or not.
In an app against the RC I wrote recently I used the CookieContainer code from this post and a custom authorize attribute on classes like this:
public class LoginRequiredAttribute : AuthorizeAttribute
{
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
IAppCookies a = new AppCookies(new CookieContainer());
return a.UserId != null; /* Better checks here */
}
}
My AppCookies.cs just has a method for UserId like this (auto resolves to int/null for you):
public int? UserId
{
get { return _cookieContainer.GetValue<int?>("UserId"); }
set { _cookieContainer.SetValue("UserId", value, DateTime.Now.AddDays(10)); }
}
Then just make sure your web.config is setup to point to your login page like this:
<authentication mode="Forms">
<forms loginUrl="~/Login"/>
</authentication>
This means in my controller to get a UserId I need to do something like this to retrieve my cookie:
[LoginRequiredAttribute]
public class RandomController : Controller
{
BaseDataContext dbContext = new BaseDataContext();
private readonly IAppCookies _cookies = new AppCookies(new CookieContainer());
public ActionResult Index()
{
return View(new RandomViewData(dbContext, _cookies.UserId));
}
}
Besides the obvious security implications, why would you need to pass the cookie through in the route anyway?
Surely you would be better off having an Authorize attribute on the action, indicating that the user should be authenticated before the action is executed.
At the end of the day, I think (hope) Microsoft has closed this as it's quite a large security issue. If this is the case, you should consider rewriting your application to comply with this.

Resources