Using Client Credetials as the part of Usermanager<User> - openiddict

Currently i am using Password Flow with my SPA application.
Now i had to integrate Client Credentials flow with my current implementation.
var descriptor = new OpenIddictApplicationDescriptor
{
ClientId = "console",
ClientSecret = "388D45FA-B36B-4988-BA59-B187D329C207",
DisplayName = "My client application",
Permissions =
{
OpenIddictConstants.Permissions.Endpoints.Token,
OpenIddictConstants.Permissions.GrantTypes.ClientCredentials
}
I have successfully implemented the both integration on my system. When sending the request using the client_id the app is authorized and authenticated as expected.
But as i notice that when using the Password flow i as using ApplicationUser as a part of Asp.net identity from dbo.User table.
But client credentials comes from different namespace that is not linked up with the Application User.
How can i setup the client_id as the part of dbo.User. How to link the the Client Credetials with Usermanager<User>?
Why i want this implementation is because during the crud operation i have the column name CreatedBy. which is refrenced to table dbo.User and i wanted to fill up the Id from dbo.User. But in the client credetials flow do not have the User.
Getting UserId
public interface IUserResolverService
{
HttpContext HttpContext { get; }
Task<Guid> GetUserId();
}
public class UserResolverService : IUserResolverService
{
IHostingEnvironment _hostingEnv;
private readonly IHttpContextAccessor accessor;
private readonly UserManager<User> _user;
public UserResolverService(IHttpContextAccessor accessor, UserManager<User> user, IHostingEnvironment hostingEnv)
{
this._user = user;
this.accessor = accessor;
this._hostingEnv = hostingEnv;
}
public HttpContext HttpContext
{
get { return accessor.HttpContext; }
}
public async Task<Guid> GetUserId()
{
var user = await _user.GetUserAsync(accessor.HttpContext.User);
return user?.Id ?? Guid.Empty;
}
}
Can you suggest me a way for this scenario?

How can i setup the client_id as the part of dbo.User. How to link the the Client Credetials with Usermanager?
It's not possible and it doesn't make any sense, actually. The client credentials is the only OAuth 2.0 core flow that doesn't involve any user as it's been designed for service-to-service scenarios, where the client application doesn't act on behalf of a user, but directly under its own identity.
To work around your issue, you may want to either make CreatedBy nullable or use one of the claim representing the application you use in AuthorizationController, like the client identifier or the client name.

Related

Is there a better way of JWT Web Token combined with Windows Auth. for building auth service in an ASP.NET Core project?

The reason behind my question is that, there is a beginner developer team at a company, starting to create a new business project after finishing some vital courses for web applications.
The aim is to have a Web Application within the company's intranet in the following form:
On Angular SPA frontend with ASP.NET Core WebAPI, using Entity Framework Core with a Microsoft SQL Server database running on Windows Server.
The current authentication method of course is Windows Authentication.
In order to create proper auth services, it was suggested to use JWT Web Token, however it is hard to tell whether there is a better approach for using authentication by combining them on the above mentioned Web Application.
As we are lacking of experience, a review of any familiars' would be highly appreciated in this matter!
The current authentication method of course is Windows Authentication.
In order to create proper auth services, it was suggested to use JWT
Web Token.
As you may know JSON Web Token (JWT) is an open standard (RFC 7519) that defines a compact and self-contained way for securely transmitting information between parties as a JSON object.Therefore, JWT creates a JSON web token and encodes, sterilizes, and adds a signature with a secret key that cannot be tampered with; Thus, it would ensure your application security well.
It is hard to tell whether there is a better approach for using
authentication by combining them on the above mentioned Web
Application.
Depending on your current application eco-system you could use Jwt without any concern as you have SPAs and other application running on intranet. While, implementing jwt it would allow you to ensure your authentication regardless of any platform. For instance, It could be windows app, SPA or any cross platform app. You can authenticate all the platfroms using this infrastructure.
As we are lacking of experience, a review of any familiars' would be
highly appreciated in this matter!
Considering your scenario, here is the implementaion steps, you could follow. You always can customize it based on your requirement. Altough, I am share you the basic steps which might assist you.
Note:
Following implementation, can be used either in any internal(intranet) or public web application(internet app) in any platforms.
Implementaion Guideline:
appsettings.json:
"Jwt": {
"Key": "Set_Your_SecretKey",
"Issuer": "YourApplication_URL"
}
Jwt Token View Model:
public class LoginViewModel
{
[Required]
[EmailAddress]
public string Email { get; set; } = string.Empty;
[Required]
[DataType(DataType.Password)]
public string Password { get; set; } = string.Empty;
}
Jwt Token Interface:
public interface IAuthenticationRepository
{
Task<TokenViewModel> AuthenticateLogin(LoginViewModel loginInfo);
}
Repository Implementation:
public class AuthenticationRepository : IAuthenticationRepository
{
private readonly ApplicationDbContext _dbContext;
private readonly IMapper _mapper;
private readonly IConfiguration _config;
public AuthenticationRepository(ApplicationDbContext dbContext, IMapper mapper, IConfiguration config)
{
_dbContext = dbContext;
_mapper = mapper;
_config = config;
}
public async Task<TokenViewModel> AuthenticateLogin(LoginViewModel loginInfo)
{
try
{
var isAuthenticate = await _dbContext.Users.FirstOrDefaultAsync(u => u.UserEmail == loginInfo.Email && u.Password == loginInfo.Password);
var tokenViewModel = new TokenViewModel();
if (isAuthenticate != null)
{
var getToken = GenerateJSONWebToken(loginInfo);
tokenViewModel = _mapper.Map<TokenViewModel>(isAuthenticate);
tokenViewModel.Token = getToken;
}
return tokenViewModel;
}
catch (Exception ex)
{
throw;
}
}
private string GenerateJSONWebToken(LoginViewModel userInfo)
{
var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["Jwt:Key"]));
var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);
var claims = new[] {
new Claim(JwtRegisteredClaimNames.Sub, userInfo.Email),
new Claim(JwtRegisteredClaimNames.Email, userInfo.Password),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())
};
var token = new JwtSecurityToken(_config["Jwt:Issuer"],
_config["Jwt:Issuer"],
claims,
expires: DateTime.Now.AddMinutes(120),
signingCredentials: credentials);
return new JwtSecurityTokenHandler().WriteToken(token);
}
Response Model I Have Used:
public class ResponseViewModel
{
public string output { get; set; }
public string msg { get; set; }
public object apiResponse { get; set; }
}
Auth Controller:
[Route("api/Authentication")]
[ApiController]
public class AuthenticationController : ControllerBase
{
private readonly IAuthenticationRepository _authenticationService;
public AuthenticationController(IAuthenticationRepository authenticationService)
{
this._authenticationService = authenticationService;
}
[AllowAnonymous]
[Route("login")]
[HttpPost]
public async Task<IActionResult> LoginAsync([FromBody] LoginViewModel loginInfo)
{
IActionResult response = Unauthorized();
var user = await _authenticationService.AuthenticateLogin(loginInfo);
if (user.Token != null)
{
response = Ok(new ResponseViewModel { output = "success", msg = "Login Successfully", apiResponse = user });
}
return response;
}
Authenticate Your Access:
Once you have successfully generate jwt auth token, now you can pass that as Bearer token for any authorization and to restrict access you can use [Authorize] before any resource where you wants to restrict access.
Output:
Note: If you would like to know more details on jwt token you could check our official document here

Where to put user claims in Identity Server 4

I am using Identity Server 4 to manage my logins for all applications in my organization.
So I have IdentityServer 4 deployed and connected to sql server database.
Now I have 5 client applications that each has it's own roles/claims (ie app 1 has manager, accountant, while app 2 has developer, manager, electrician, app 3 has designer, administrator, reviewer...).
My question is:
Do I put those user role/claims in Identityserver4 database or should each application have its own database holding its own user roles/claims?
Thanks
You can solve it by adding one extra table to IdentityServer Database,like RoleClientAuthorizations. You need to hold RoleId,ClientId and AuthorizationLevel in this table.
Then you can return all claims about that client in ProfileService at runtime.
public class ProfileService : IProfileService
{
private readonly IUserClaimsPrincipalFactory<ApplicationUser> _claimsFactory;
private readonly UserManager<ApplicationUser> _userManager;
private readonly IClientService _clientService;
public ProfileService(UserManager<ApplicationUser> userManager, IUserClaimsPrincipalFactory<ApplicationUser> claimsFactory,IClientService clientService)
{
_userManager = userManager;
_claimsFactory = claimsFactory;
_clientService = clientService;
}
public async Task GetProfileDataAsync(ProfileDataRequestContext context)
{
var sub = context.Subject.GetSubjectId();
var user = await _userManager.FindByIdAsync(sub);
var principal = await _claimsFactory.CreateAsync(user);
var clientId = context.Client.ClientId;
var claims = principal.Claims.ToList();
--You will get role client information from RoleClientAuthorization table here
var userAuthorizationLevelClaim = _clientService.GetUserAuthorizationLevel(clientId, sub);
if(userAuthorizationLevelClaim != null)
{
claims.Add(new Claim("authorizationLevelCode", userAuthorizationLevelClaim.AuthorizationLevelId.ToString()));
claims.Add(new Claim("authorizationPrivilegeType", userAuthorizationLevelClaim.PrivilegeType));
}
context.IssuedClaims = claims;
}
public async Task IsActiveAsync(IsActiveContext context)
{
var sub = context.Subject.GetSubjectId();
var user = await _userManager.FindByIdAsync(sub);
context.IsActive = user != null;
}
In startup;
services.AddIdentity()
.AddProfileService<ProfileService>();
It's sounding a little like you're mixing up authentication and authorization. Your identity shouldn't change from App to App - who you are and what you are made up of is a constant (ish) and your identity shouldn't change just because you're now on a different application.
Yes, your roles might change from app to app, and your permissions and authorization decisions, but not your identity.
https://leastprivilege.com/2016/12/16/identity-vs-permissions/
Using IdentityServer for managing identity, and issuing proof-of-identity is great but you should look for a different solution for authorizing the user within your applications ... something that lets those applications decide whether, given the identity provided, the user is allowed to do the thing. This may be role based, or something more involved. This means you should manage the application roles a user has with each application, not with identity server.

How can I get the user from my AuthorizationAttribute from within an ASPNETCORE 2.2 application?

I have created a custom attribute that I would like to decorate my api controller from within my ASPNETCORE angular application. I am able to set up my authentication as required and log into the application from the login. Then I decorate my api method with my custom attribute.
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = false)]
public class ManageAuditAttribute : AuthorizeAttribute, IAuthorizationFilter
{
public List<Claim> Claims { get; set; }
public ManageAuditAttribute(String feature)
{
Feature = feature;
}
public bool IsAuthorized()
{
// TODO check there is a claim for the given feature
}
private String Feature { get; }
public void OnAuthorization(AuthorizationFilterContext context)
{
var accessor = (IHttpContextAccessor)context.HttpContext.RequestServices.GetService(typeof(IHttpContextAccessor));
var name = context.HttpContext.User.FindFirst(ClaimTypes.Email); //NULL
var user = context.HttpContext.User; // NULL
var userName = Thread.CurrentPrincipal.Identity.Name; // NULL
}
}
Before saying that claims are not used this way I would add that I need to fit this into a legacy system that has a list of allowed features. I am adding those features to the user as claims and checking the claim exists for each user. The value for the actual claim is the name of the application that the user needs the claim for.
I could easily add these as a custom list to my custom identity user which might be more fitting however, I still need to access my user.
I can get the user but the name is always null and my claims list is empty as well. It is as if I am not logged in at all. Even after logging in.
For retrieving name, you should pass ClaimTypes.Name instead of ClaimTypes.Email like
var user = context.HttpContext.User.FindFirst(ClaimTypes.Name);
Or, you could retrieve by HttpContext.User.Identity.Name like
var userName = context.HttpContext.User.Identity.Name;
I have solved you problem by adding:
app.UseAuthentication();
in Startup.cs.

Recommended best practice for role claims as permissions

The app I am working on is a SPA and we are using JWT Bearer authentication and OpenIdConnect/OAuth2 when communicating with our backend API which uses .NETCore and ASP.NET Identity. Our API endpoints are secured using Custom Policy based authentication as shown here:
Custom Policy Based Authentication
We decided to use the out of the box AspNetRoleClaims table to store claims for our users as permissions. Each user is assigned 1 primary role although the potential is there to have multiple roles. Each role will have many claims - which are stored in the AspNetRoleClaims table.
Role claims would look like this:
ClaimType: Permission
ClaimValue(s):
MyModule1.Create
MyModule1.Read
MyModule1.Edit
MyModule1.Delete
MyModule1.SomeOtherPermission
MyModule2.Read
MyModule3.Read
MyModule3.Edit
etc.
The more permissions or role claims that a user has, the larger the access_token will be, thereby increasing the HTTP header size. Also the ASP.NET Identity Authorization cookie - as there are more and more role claims it gets chunked out into multiple cookies.
I have experimented with adding in a lot of role claims and eventually the request fails because the header gets too big.
I am looking for some advice on what is considered "best practice" when it comes to bearer authentication with role claims. Microsoft gives you AspNetRoleClaims out of the box that work for my scenario and from what I understand the advantage of storing these role claims in the access_token is that we don't have to hit the database on each API endpoint that is secured with the custom policy.
The way I see it, I can try to make the claim values smaller, and in the case of where a user has multiple roles that may share common role claims that are duplicated, I can try to intercept when these get written into the cookie and remove the duplicates.
However, since the app is still in development, I can foresee more and more roles claims being added and there is always the possibility that the HTTP header will become too large with the cookies and the access_token. Not sure if this is the best approach.
The only alternative I see is to hit the database each time we hit our protected API. I could inject a DbContext in each custom claim policy requirement handler and talk to the AspNetRoleClaims table on each request.
I haven't seen too many examples out there of how people accomplish a more finely grained permissions scheme with ASP.NET Identity and .NET Core API. This must be a fairly common requirement I would think...
Anyways, just looking for some feedback and advice on recommended best practice for a scenario like this.
****UPDATE - See answer below ****
I never did find a recommended "best practice" on how to accomplish this but thanks to some helpful blog posts I was able to architect a nice solution for the project I was working on. I decided to exclude the identity claims from the id token and the Identity cookie and do the work of checking the users permissions (role claims) server side with each request.
I ended up using the architecture are described above, using the built in AspNetRoleClaims table and populating it with permissions for a given role.
For example:
ClaimType: Permission
ClaimValue(s):
MyModule1.Create
MyModule1.Read
MyModule1.Edit
MyModule1.Delete
I use Custom policy based authentication as described in the Microsoft article in the link above.
Then I lock down each of my API endpoints with the Role based policy.
I also have an enum class that has all the permissions stored as enums. This enum just lets me refer to the permission in code without having to use magic strings.
public enum Permission
{
[Description("MyModule1.Create")]
MyModule1Create,
[Description("MyModule1.Read")]
MyModule1Read,
[Description("MyModule1.Update")]
MyModule1Update,
[Description("MyModule1.Delete")]
MyModule1Delete
}
I register the permissions in Startup.cs like so:
services.AddAuthorization(options =>
{
options.AddPolicy("MyModule1Create",
p => p.Requirements.Add(new PermissionRequirement(Permission.MyModule1Create)));
options.AddPolicy("MyModule1Read",
p => p.Requirements.Add(new PermissionRequirement(Permission.MyModule1Read)));
options.AddPolicy("MyModule1Update",
p => p.Requirements.Add(new PermissionRequirement(Permission.MyModule1Update)));
options.AddPolicy("MyModule1Delete",
p => p.Requirements.Add(new PermissionRequirement(Permission.MyModule1Delete)));
}
So there is a matching Permission and a PermissionRequirement like so:
public class PermissionRequirement : IAuthorizationRequirement
{
public PermissionRequirement(Permission permission)
{
Permission = permission;
}
public Permission Permission { get; set; }
}
public class PermissionRequirementHandler : AuthorizationHandler<PermissionRequirement>,
IAuthorizationRequirement
{
private readonly UserManager<User> _userManager;
private readonly IPermissionsBuilder _permissionsBuilder;
public PermissionRequirementHandler(UserManager<User> userManager,
IPermissionsBuilder permissionsBuilder)
{
_userManager = userManager;
_permissionsBuilder = permissionsBuilder;
}
protected override async Task HandleRequirementAsync(
AuthorizationHandlerContext context,
PermissionRequirement requirement)
{
if (context.User == null)
{
return;
}
var user = await _userManager.GetUserAsync(context.User);
if (user == null)
{
return;
}
var roleClaims = await _permissionsBuilder.BuildRoleClaims(user);
if (roleClaims.FirstOrDefault(c => c.Value == requirement.Permission.GetEnumDescription()) != null)
{
context.Succeed(requirement);
}
}
}
The extension method on the permission GetEnumDescription just takes the enum that I have in the code for each permission and translates it to the same string name as it is stored in the database.
public static string GetEnumDescription(this Enum value)
{
FieldInfo fi = value.GetType().GetField(value.ToString());
DescriptionAttribute[] attributes =
(DescriptionAttribute[])fi.GetCustomAttributes(
typeof(DescriptionAttribute),
false);
if (attributes != null &&
attributes.Length > 0)
return attributes[0].Description;
else
return value.ToString();
}
My PermissionHandler has a PermissionsBuilder object. This is a class I wrote that will hit the database and check if the logged in user has a particular role claim.
public class PermissionsBuilder : IPermissionsBuilder
{
private readonly RoleManager<Role> _roleManager;
public PermissionsBuilder(UserManager<User> userManager, RoleManager<Role> roleManager)
{
UserManager = userManager;
_roleManager = roleManager;
}
public UserManager<User> UserManager { get; }
public async Task<List<Claim>> BuildRoleClaims(User user)
{
var roleClaims = new List<Claim>();
if (UserManager.SupportsUserRole)
{
var roles = await UserManager.GetRolesAsync(user);
foreach (var roleName in roles)
{
if (_roleManager.SupportsRoleClaims)
{
var role = await _roleManager.FindByNameAsync(roleName);
if (role != null)
{
var rc = await _roleManager.GetClaimsAsync(role);
roleClaims.AddRange(rc.ToList());
}
}
roleClaims = roleClaims.Distinct(new ClaimsComparer()).ToList();
}
}
return roleClaims;
}
}
I build up a list of distinct role claims for a user - I use a ClaimsComparer class to help do this.
public class ClaimsComparer : IEqualityComparer<Claim>
{
public bool Equals(Claim x, Claim y)
{
return x.Value == y.Value;
}
public int GetHashCode(Claim claim)
{
var claimValue = claim.Value?.GetHashCode() ?? 0;
return claimValue;
}
}
The controllers are locked down with the role based custom policy:
[HttpGet("{id}")]
[Authorize(Policy = "MyModule1Read", AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
public IActionResult Get(int id){
Now here is the important part - you need to override the UserClaimsPrincipalFactory in order to prevent the role claims from being populated into the Identity cookie. This solves the problem of the cookie and the headers being too big. Thanks to Ben Foster for his helpful posts (see links below)
Here is my custom AppClaimsPrincipalFactory:
public class AppClaimsPrincipalFactory : UserClaimsPrincipalFactory<User, Role>
{
public AppClaimsPrincipalFactory(UserManager<User> userManager, RoleManager<Role> roleManager, IOptions<IdentityOptions> optionsAccessor)
: base(userManager, roleManager, optionsAccessor)
{
}
public override async Task<ClaimsPrincipal> CreateAsync(User user)
{
if (user == null)
{
throw new ArgumentNullException(nameof(user));
}
var userId = await UserManager.GetUserIdAsync(user);
var userName = await UserManager.GetUserNameAsync(user);
var id = new ClaimsIdentity("Identity.Application",
Options.ClaimsIdentity.UserNameClaimType,
Options.ClaimsIdentity.RoleClaimType);
id.AddClaim(new Claim(Options.ClaimsIdentity.UserIdClaimType, userId));
id.AddClaim(new Claim(Options.ClaimsIdentity.UserNameClaimType, userName));
if (UserManager.SupportsUserSecurityStamp)
{
id.AddClaim(new Claim(Options.ClaimsIdentity.SecurityStampClaimType,
await UserManager.GetSecurityStampAsync(user)));
}
// code removed that adds the role claims
if (UserManager.SupportsUserClaim)
{
id.AddClaims(await UserManager.GetClaimsAsync(user));
}
return new ClaimsPrincipal(id);
}
}
Register this class in Startup.cs
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
// override UserClaimsPrincipalFactory (to remove role claims from cookie )
services.AddScoped<IUserClaimsPrincipalFactory<ApplicationUser>, AppClaimsPrincipalFactory>();
Here are the links to Ben Foster's helpful blog posts:
AspNet Identity Role Claims
Customizing claims transformation in AspNet Core Identity
This solution has worked well for the project I was working on - hope it helps someone else out.
I haven't seen too many examples out there of how people accomplish a more finely grained permissions scheme with ASP.NET Identity and .NET Core API. This must be a fairly common requirement I would think...
Your current design is RBAC (Role Based Access Control). Since you are experiencing a "role explosion", you need ReBAC (Relationship Based Access Control), which allows for fine-grained permissions. See my other answer here for more details on current offerings.

Adding RequestFilter data to Context (Request Scope), Retrieve in Service

I implemented Basic Auth for my services. Since ServiceStack's AuthFeature is strongly coupled with the session concept, I implemented a custom RequestFilter that performs stateless basic auth (credentials go in, on every request). Our auth strategy internally contemplates roles and permissions.
Besides authentication, we need to enforce authorization (e.g., user is manipulating a product that he owns). We are using FluentValidation, for all service validations.
Authorization validations include cross checking auth data with request parameters. Question is, where should I place the auth data produced in the BasicAuthRequestFilter? Should I key value pair it in cache, associating, for instance, RequestContext (or any other object that uniquely identifies the request scope) with an Authentication object?
I could just plug the AuthData in the Request Dto, which is available directly at the RequestFilter, however this would mess up our service contract design. We define dtos in a separate DLL, where only service input/output details are defined.
Any suggestions?
Thanks in advance.
I too use my own custom authentication mechanism and make custom role information available to my service. I do this by authenticating the request in a custom ServiceRunner which can then pass the information directly to my custom Service base. This ultimately means accessing information about the users permissions is exceptionally easy.
Create a custom ServiceRunner:
public class ServiceRunner<T> : ServiceStack.ServiceHost.ServiceRunner<T>
{
public ServiceRunner(IAppHost appHost, ActionContext actionContext) : base(appHost, actionContext)
{
}
public override object Execute(IRequestContext requestContext, object instance, T request)
{
// Check if the instance is of type AuthenticatedBase
var authenticatedBase = instance as AuthenticatedBase;
// If the request is not using the AuthenticatedBase, then allow it to run, as normal.
if(authenticatedBase == null)
return base.Execute(requestContext, instance, request);
/*
* Authentication required. Do you authorization check here.
* i.e.
* var authorization = requestContext.GetHeader("Authorization");
* bool authorised = ... some condition;
*/
/* You have access to your service base so if you injected the Db connection
* in you app config using IoC, then you can access the Db here.
* i.e.
* authenticatedBase.Db
*/
/*
* Not authorized?
* throw new UnauthorizedException();
*/
/*
* If authorized:
* Then simple set the details about their permissions
*/
authenticatedBase.AuthData = new AuthData { Id = 123, Roles = [], Username = "" };
// Pass back the authenticated base
return base.Execute(requestContext, authenticatedBase, request);
}
}
Configure you application to use it by adding this to your AppHost:
public override IServiceRunner<TRequest> CreateServiceRunner<TRequest>(ActionContext actionContext)
{
return new ServiceRunner<TRequest>(this, actionContext);
}
Create a custom class to hold your auth data i.e. the user session information, such as:
public class AuthData
{
public int Id { get; set; }
public string Username { get; set; }
public int[] Roles { get; set; }
...
}
Then create a custom service base
public class AuthenticatedBase : Service
{
public AuthData AuthData { get; set; }
}
To then use the AuthData in the service is simply a case of extending AuthenticatedBase.
public class CustomerHandler : AuthenticatedBase
{
public object Get(ListCustomers request)
{
// You can access the AuthData now in the handler
var roles = AuthData.Role; // Check they have the role required to list customers
...
}
}
You are probably wondering why go to all the trouble of using the ServiceRunner over a RequestFilter but the main advantage is it gives direct access to the instance of the Service base, which isn't available to a RequestFilter.
The RequestFilters are run before the Service base is instantiated, so you can't populate it from there. See order of operations for more information.
By having access to the ServiceBase we can populate values (in this case AuthData) and we have access to our injected dependancies such as the database connection.
I hope you find this useful. You should be able to copy most of your existing RequestFilter into the service runner. If you need any further help with this just let me know.
Update to support Attributes:
Since you are unable to avoid using the attribute method to handle your authentication needs you can still use this method:
Continue doing your authentication and access filtering the way you were before.
In your existing authentication mechanism use req.Items.Add to set the AuthData i.e. Where req is your request object
req.Items.Add("AuthData", new AuthData { Username = "", Roles = [] ... });
Then access your AuthData item in your service base:
public class AuthenticatedBase : Service
{
public AuthData AuthData
{
get { return base.Request.Items["AuthData"] as AuthData; }
}
}