NancyFX : Why is my IUserMapper singleton instantiated twice? - singleton

I am trying to implement a very simple example of FormsAuthentication. It is not real life but it has thrown up a problem. The AuthenticationService, which is intended to be an Application level singleton, appears to be instantiated twice.
Here is the code:
public class User : IUserIdentity
{
public string UserName { get; set; }
public IEnumerable<string> Claims { get; set; }
}
public interface IAuthenticationService
{
Guid GetIdentifier(string username, string password);
}
public class AuthenticationService : IUserMapper, IAuthenticationService
{
public readonly Guid Identifier = Guid.NewGuid();
private readonly string Username = "admin";
private readonly string Password = "x";
public Guid GetIdentifier(string username, string password)
{
return (username == Username && password == Password) ? Identifier : Guid.Empty;
}
public IUserIdentity GetUserFromIdentifier(Guid identifier, NancyContext context)
{
return (identifier == Identifier) ? new User { UserName = "admin" } : null;
}
}
public class MyBootstrapper : DefaultNancyBootstrapper
{
protected override void ConfigureApplicationContainer(TinyIoCContainer container)
{
base.ConfigureApplicationContainer(container);
container.Register<IAuthenticationService, AuthenticationService>().AsSingleton();
}
}
The code above is being used by my LoginModule as follows. Please note that I am injecting the application-level singleton instance of the AuthenticationService via the module's constructor.
public LoginModule(IAuthenticationService authenticationService)
{
Post["/login"] = _ =>
{
var identifier = authenticationService.GetIdentifier(
(string) Form.Username,
(string) Form.Password);
if (identifier.IsEmpty())
{
return Context.GetRedirect("~/login?error=true");
}
return this.LoginAndRedirect(identifier);
};
}
What should happen is that when the user POSTs their username and password, these are checked by the AuthenticationService via the GetIdentifier(..) method. If the credentials match then the single GUID identifier is returned. This GUID will always be the same because it is created as a readonly field and thus set once when the singleton AuthenticationService is first instantiated at application startup.
However this is not the case. Instead two distinct instances of the AuthenticationService are created, one that is injected into the LoginModule constructor and used to call the GetIdentifier(..) method and another instance which Nancy uses to call the IUserIdentity.GetUserFromIdentifier(..) method.
These two instances have different GUID identifiers and so the GetUserFromIdentifier(..) method always return null.
I have tested a standard singleton service that does not implement IUserMapper and it works as expected, only one instance is created.
So it seems that Nancy is instantiating the IUserMapper singleton twice, once for its own internal use during FormsAuthentication, and once to inject into my LoginModule constructor!
Can you spot my mistake?
Thanks

It's probably because you're using a different interface so you have one singleton for things requesting IUsernameMapper and another for things requesting IAuthenticationService.
You can either:
Register both with an instance of your authentication service
Split out the username mapper and take a dependency on that in your service (so your Application Service has a dependency on the IUsernameMapper - that will be the same one Nancy is using)
Register one of them using a factory that resolves using the other interface (container.Register((c,p) => c.Resolve
My I ask why you're doing any of this though rather than just using the built in forms auth?

Related

.NET 5 Web API: Storing data per request

When getting a request in any action of any controller, I look at the jwt know which user is requesting and lookup the user in the database to get some user-data that I want to use throughout the application. E.g. which departments the user belongs to or the users preferred language.
Now I could create a object which wraps these information and send it down the layers and pass it to every method that likes to use some of this data. But I like the data to be available to every method throughout the application without passing it in every method. Like e.g. dependency injection (Seems to late at that point) or something else I can get access to that data quickly.
Any advice of how to handle it?
Try it with the Items property on the HttpContext. By using it you can store data during a single request. The only downside with this approach is that every service needs to have access to the HttpContext to read the values. Values can be added to the Items Dictionary as shown below
public class IndexModel : PageModel
{
//
public void OnGet()
{
HttpContext.Items.Add("Key", new RequestInfo { Key = "RequestKey" });
}
}
class RequestInfo
{
public string Key { get; set; }
}
You can then access the value by registering the IHttpContextAccessor to the IServiceCollection and then using Constructor injection to use the HttpContext in your service so that you can work with the Items Dictionary.
public class Service
{
private IHttpContextAccessor _htp;
public Service(IHttpContextAccessor http)
{
_htp = http;
}
public void Log()
{
Console.WriteLine(((RequestInfo)_htp.HttpContext.Items["Key"]).Key);
}
}

Validating Against credentials Custom Users DB - IResourceOwnerPasswordValidator

I am using Identity Server 4 and implemented the following two interfaces:
IResourceOwnerPasswordValidator: for the purpose of validating user credentials against my custom DB
public class ResourceOwnerPasswordValidator : IResourceOwnerPasswordValidator
{
private IUserRepository _userRepository;
public ResourceOwnerPasswordValidator(IUserRepository userRepository)
{
this._userRepository = userRepository;
}
public Task ValidateAsync(ResourceOwnerPasswordValidationContext context)
{
var isAuthenticated = _userRepository.ValidatePassword(context.UserName, context.Password);
//code is omitted for simplicity
}
}
IProfileService: for getting necessary claims
public class ProfileService : IdentityServer4.Services.IProfileService
{
public IUserRepository _userRepository;
public ProfileService(IUserRepository userRepository)
{
_userRepository = userRepository;
}
public Task GetProfileDataAsync(ProfileDataRequestContext context)
{
//code is ommitted
}
Then added then necessary Interfaces and dependencies to the services in Startup class. I have also modified the Account Controller by injecting the login service which has the following implementation:
public class LoginService
{
private readonly IUserRepository _userRepository;
public LoginService( IUserRepository userRepository)
{
_userRepository = userRepository;
}
public bool ValidateCredentials(string username, string password)
{
return _userRepository.ValidatePassword(username, password);
}
The AccountController "Login" Action validate for the credentials by calling:
if (_loginService.ValidateCredentials(model.Username, model.Password))
{
var user = _loginService.FindByUsername(model.Username);
await HttpContext.Authentication.SignInAsync(user.Subject, user.Username);
//other code is omitted
When debugging the project the Login Action of AccountContoller is called, then my login service. After validating the user credentials, the consent page is displayed, which trigger the ProfileService GetProfileDataAsync Method.
However, the ResourceOwnerPasswordValidator was never called. Am I Implementing the LoginService in the correct manner or should I replace the IUserRepository injected by IResourceOwnerPasswordValidation then call the "ValidateAsync" method in Login Service ValidateCredentails?
And if that was the case, what is the advantage of passing that to LoginService, since I am already validating users in this way?
I ran into the same problem. The solution was to do just as you have done, but then needed to modify Startup.cs to see it.
// Adds IdentityServer
services.AddIdentityServer()
.AddResourceOwnerValidator<**PasswordAuthentication**>()
NOTE: Make sure you don't add it to the AddIdentity which also has the same .AddResourceOwnerValidator function. It took me awhile. Hope this helps someone.
According to docs:
If you want to use the OAuth 2.0 resource owner password credential
grant (aka password), you need to implement and register the
IResourceOwnerPasswordValidator interface:
Since you don't use password grant, expected behaviour is to not call ResourceOwnerPasswordValidator. For your case you don't need ResourceOwnerPasswordValidator implementation.

Spring & Reslet : is it possible to map a URL path component to a method argument?

I'm new to Restlet, but I've followed the tutorial on Restlet's own website and got a basic application up and running. What I'm doing right now is that I'm setting up a basic ServerResource and expose a #Get method.
What I'd like is to be able to invoke /user/{userId} and get the user representation back. Is it possible, somehow, to hand over the mapping of {userId} to Restlet, which in turn would invoke getUser(String userId) in my ServerResource?
Such feature (binding path variables into annotated method parameters) isn't natively supported in the framework. Such mapping in the annotated method signatures is only supported with input representation.
To get the path variables of a request, you can get them from the request object (method getAttribute), as described below:
public class UserServerResource extends ServerResource {
#Get
public User getUser() {
String userId = getAttribute("userId");
User user = (...)
(...)
return user;
}
}
If you want to share this path variable across several methods, you can define it as a instance variable (notice that a new instance of the server resource is created for each request unlike to Spring REST where each controller is a singleton and such variable must be defined in method signatures). We can leverage the method doInit of the server resource, as described below:
public class UserServerResource extends ServerResource {
private String userId;
private User user;
#Override
protected void doInit() throws ResourceException {
super.doInit();
userId = getAttribute("userId");
// for example
user = loadUser(userId);
// throws a status 404 if user can't be found
setExisting(user != null);
}
#Get
public User getUser() {
return user;
}
#Put
public User saveUser(User user) {
saveUser(user);
return user;
}
#Delete
public void deleteUser() {
deleteUser(user);
}
}
If you really want to use a mapping from request elements (like path variables, ...) to method parameters, you should use JAXRS. Restlet provides a support of this specification. Implementing a similar server resource as above but with JAXRS is described below:
#Path("/users/{userId}")
public class UserResource {
#GET
#Produces("text/xml")
public String getUser(#PathParam("userId") String userId) {
(...)
}
}
For more details, you can have a look at the corresponding documentation: http://restlet.com/technical-resources/restlet-framework/guide/2.2/extensions/jaxrs.
Hop it helps,
Thierry

How to implement custom role based authorization in ASP.Net MVC

I am working on a project where we are using Amazon SimpleDB as a data storage. In this application user can create roles at run time. While creating role, user can give Read/Write/Update permission for specific feature.
The code I have tried;
using System;
using System.Web.Http;
using System.Web.Http.Controllers;
using System.Web.Http.Filters;
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class MyAuthorization : ActionFilterAttribute
{
public string Model { get; set; }
public string Action { get; set; }
public override void OnActionExecuting(HttpActionContext filterContext)
{
//My code will go here
base.OnActionExecuting(filterContext);
}
}
In Web API controller I have written as;
// GET api/values
[MyAuthorization(Action = "Edit", Model = "Rack")]
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
Now in OnActionExecuting, I want to fetch Action and Model attributes which I have specified over action method in APIController.
How to handle it through code, since role names and rights are not known at design time.
I assume that each feature you will be implementing in a certain controller and each action method designates the type of operation you are performing (ex Read, Write etc).
If my assumption is correct, you may have to first extend the AuthorzeAttribute ASP.NET MVC framework like below.
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
public class CustomAuthorizeAttribute : AuthorizeAttribute
{
public string Operation;
public override void OnAuthorization(AuthorizationContext filterContext)
{
base.OnAuthorization(filterContext);
//Get the User Id from the session
// Get Role associated with the user (probably from database)
// get the permission associated with the role (like Read, write etc)
// Let assume the retrieved operations are in the form of list of strings
List<string> retrievedOperations =RetrieveRoleOperations(userId)
if (!retrievedOperations.Contains(Operation)
{
filterContext.Result = new HttpUnauthorizedResult();
}
}
}
After creating this class, you have to specify the extended authorize filter in required action methods like below.
Class MyFeatureController:Controller
{
[MyCustomAuthorize(Operation="Read")]
public ActionResult MyReadMethod()
{
//
}
}
I hope this will solve your problem.

WEBAPI ActionContext Request.Properties.Add for store sensitive information

I would like to pass information from the action filter (database) to the Action function.
Is it secure to use ActionContext Request.Properties.Add to store the data?
is there any chance that the information will be seen by the WEBAPI client or its safe as it safe to store information in the Cache\Session?
Is it a better way to do it?
The client will not see request properties unless you explicitly serialize them. They completely remain on the server side.
To answer your followup question here are two other ways to do it. There is no "Best" way per se. It all depends on how far you want the information to flow, and how generic you want your filter to be. My personal preference is using the controller object, but again it is just a preference.
For the sample here is a simple values controller and a POCO class:
[MyActionfilter]
public class ValuesController : ApiController
{
public string Foo { get; set; }
public User Get(User user)
{
if (Foo != null && user != null)
{
user.FamilyName = Foo;
}
return user;
}
}
public class User
{
public string FirstName { get; set; }
public string FamilyName { get; set; }
}
The action filter below is naively implementing access to the controller object or the method parameters. Note that it's up to you to either apply the filter sparingly or do type checks/dictionary checks.
public class MyActionfilter : ActionFilterAttribute
{
public override void OnActionExecuting(System.Web.Http.Controllers.HttpActionContext actionContext)
{
controller = actionContext.ControllerContext.Controller;
// Not safe unless applied only to controllers deriving
// from ValuesController
((ValuesController)controller).Foo = "From filter";
// Not safe unless you know the user is on the signature
// of the action method.
actionContext.ActionArguments["user"] = new User()
{
FirstName = "From filter"
};
}
}