Let's say I have an ASP.NET MVC Core application, and I want to validate certain custom conditions when allowing authentication. For example, an user that provides a valid pair of credentials, but is disabled by the application's administrator, or a flag that indicates the user is up-to-date with his payments, or any other arbitrary condition. Is there a place in ASP.NET Core Identity where I can hook this custom validation? I have to make this work for local and external authentication.
For you case, you could create custom user validators.
Writing a custom validator for ASP.NET Core Identity
Custom User Validator That Requires E-Mail Addresses to End in #example.com
This follows a common pattern within Identity, where you can either implement the interface (in this case IValidator<T>) and provide all of the validation code, or override the base implementation of it and add additional logic by overriding methods as I did here.
public class CustomUserValidator : UserValidator<ApplicationUser>
{
public override async Task<IdentityResult> ValidateAsync(UserManager<ApplicationUser> manager,
ApplicationUser user)
{
IdentityResult baseResult = await base.ValidateAsync(manager, user);
List<IdentityError> errors = new List<IdentityError>(baseResult.Errors);
if (!user.Email.EndsWith("#example.com"))
{
IdentityError invalidEmailError = Describer.InvalidEmail(user.Email);
invalidEmailError.Description += " Email address must end with #example.com";
errors.Add(invalidEmailError);
}
return errors.Count > 0 ? IdentityResult.Failed(errors.ToArray()) : IdentityResult.Success;
}
}
Then to plug this in, head over to the Startup.cs file and find the ConfigureServices method. Somewhere before the line starting with services.AddIdentity, add the following line:
services.AddTransient<IUserValidator<ApplicationUser>, CustomUserValidator>();
This will add the implementation of CustomUserValidator to the internal services collection, allowing it to be injected anywhere that an IUserValidator<ApplicationUser> is required.
Related
I'm working on an ASP.NET Core MVC application and I want to be able to better handle what happens when an unauthenticated user runs an action through AJAX.
I found this solution that essentially extends the Authorize attribute's logic and sets an AJAX request's status code to 401 when user is no longer authenticated. The status code is returned to a global AJAX error handler and the appropriate action can be performed.
I'm trying to create the attribute in Core 3.1 but I cannot find a way to first run the base logic of the filter. base.OnAuthorization method is not there. I specifically don't want to rewrite the Authorize attribute's functionality - only to extend it.
How can I extend the Authorize attribute's logic in Core 3.1?
The authorize attribute I'm writing:
public class AuthorizeUserAttribute : AuthorizeAttribute, IAuthorizationFilter
{
public void OnAuthorization(AuthorizationFilterContext context)
{
base.OnAuthorization(context); //method does not exist
OnAjaxAuthorization(context);
}
internal void OnAjaxAuthorization(AuthorizationFilterContext context)
{
if (context.HttpContext.User.Identity.IsAuthenticated == false)
{
if (context.HttpContext.Request.IsAjaxRequest())
{
context.HttpContext.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
}
}
}
}
Just as a side note, I was thinking of writing a ActionFilterAttribute to run the additional code instead, but I can't do that because the Authorize attribute always runs first.
I want to develop dynamic roles authorization using .net core webAPI, my structure is that user have one role and the role have some function or features to access
my question is there is any way yo get the function name where authorization policies applied
as example I have the following code
[Authorize(Roles = "Admin", Policy = "isHasPermission")]
public async Task<IActionResult> GetAllAsync()
{
var users = await _userService.GetAllAsync();
var userDtos = _mapper.Map<IList<UserDto>>(users);
return Ok(DataMessage.Data(new { users = userDtos }));
//return Ok(userDtos);
}
and my policy is something like that
protected override async Task HandleRequirementAsync(
AuthorizationHandlerContext context,
isHasPermissionRequirement requirement)
{
/*
CAN I GET THE FUNCTION NAME "GetAllAsync" HERE!
TO VALIDATE IF IT IS ONE OF USER'S FEATURE
*/
return await Task.CompletedTask;
}
So that I need to get the function name in the policy to validate user's permissions, if it is possible or not?
You are doing it backwards: The way policies work is that you say that a certain action has requirements. It is not a valid requirement to then circle back to where the policy is used. Policies should be completely separate from what you are trying to access. If a certain thing specifies a policy, then just the presense of the policy should be all that’s necessary.
If you want to have your logic actually check what you are trying to access, then you could look into authorization filters instead. When they are called, they pass an AuthorizationFilterContext which also contains information about the route and action the user is trying to access. With that, you can get the action name for example using (context.ActionDescriptor as ControllerActionDescriptor).ActionName.
How to skip the [Authorization](Azure AD authentication) from Web Api controller depends on the value from header request?
[Authorize]
public class ExampleController : ApiController
{
//code
private string _clientid;
var req = Request.Headers;
_clientid = string.IsNullOrEmpty(req.GetValues("clientid").First())
? null :
req.GetValues("clientid").First();
}
The above mentioned _clientid is a header value, I want to skip authentication for some _clientid values.
In my opinion you essentially have an alternative way of authentication.
It would make the most sense to define your own authentication scheme that checks that header and creates a user principal based on that.
Then you can keep on using [Authorize] as usual.
Writing an example would be quite time-consuming, the best I can offer at the moment is the Security repo, which contains all of the built-in authentication schemes, like JWT Bearer here: https://github.com/aspnet/Security/blob/dev/src/Microsoft.AspNetCore.Authentication.JwtBearer/JwtBearerHandler.cs Check those for examples on how to implement an authentication handler.
You can create a custom authentication handler similar to the one here .
Then, where you add authorization in Startup.cs, you can add a custom policy like this:
services.AddAuthorization(
o =>
{
// create a policy called ApiKeyPolicy which requires a Role defined in
// ApiKeyAuthenticationOptions.
// The policy is used by the API controllers.
o.AddPolicy(
"ApiKeyPolicy", builder =>
{
builder.AddAuthenticationSchemes(
ApiKeyAuthenticationOptions.AuthenticationSchemeName);
});
});
and add the scheme to the services.AddAuthentication builder:
builder.AddScheme<ApiKeyAuthenticationOptions, ApiKeyAuthenticationHandler>(
"ApiKey", "ApiKey", o =>
{
o.AllowedApiKeys = config["Api:AllowedApiKeys"];
o.ApiKeyHeaderName = config["Api:ApiKeyHeaderName"];
});
In my example, I have an ApiKeyAuthenticationOptions class that is configured with some API keys and the http header name to check. In your case, you would probably want the valid client IDs.
Finally, you need to tell the [Authorize] attribute which policy is needed:
[Authorize(Policy = "ApiKeyPolicy")]
In your case, you want to be able to handle both the client IDs and regular auth, so you could add the regular auth scheme to the policy builder expression (the first snippet above).
Context
I have a working WebApi2 application, which uses the out of the box bearer token validation, just as was in the original Visual Studio project template.
I would like to add a custom data to the generated token, then check against that custom data when the subsequent api calls happen what are presenting this token.
For the sake of example say I would like to store the IP address of the caller when the token was created, then when validating the token check if the call which is uses the token have the very same IP.
I found the custom class
public class ApplicationOAuthProvider : OAuthAuthorizationServerProvider
in my project and I also see that OAuthOptions is configured to use that custom class in start up.
I suppose where to add my custom token data (the ip):
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
here I can add it to the ticket properties as custom data.
Question
However I can not find out in what method to check against the token has this data, and it matches to the actual call's ip, and if not, then regard the token invalid?
You are absolutely right when you decided to implement OAuthAuthorizationServerProvider . Now you need to add something like this:
private ClaimsIdentity CreateIdentity(User user, string authenticationType)
{
var identity = new ClaimsIdentity(authenticationType);
identity.AddClaim(new Claim(ClaimTypes.Name, user.Login));
identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, user.UserID.ToString())); // or ip instead of user.UserID if you need
return identity;
}
And then use it in your Grant... method (for instance GrantResourceOwnerCredentials) like this:
ClaimsIdentity identity = CreateIdentity(user, context.Options.AuthenticationType);
context.Validated(identity);
Then when request come to your webapi controller you can check your data in your custom Attribute:
Claim userIdClaim = ((ClaimsIdentity)actionContext.ControllerContext.RequestContext.Principal.Identity)
.Claims
.FirstOrDefault(c => c.Type == ClaimTypes.NameIdentifier);
hope it helps.
Member have many jobs. A member can add, delete or update Jobs. Currently there are actions (add, delete or update) defined in a controller which are called through jQuery.ajax(). We are sending job id and member id to perform the operation. Member id is necessary because there is a role admin who can modify the job on behalf of members, so we need to identify the member. But sending member id is dangerous as anyone can send the request by modifying the member id.
I know, we can add constraint do restrict that only admin can modify the jobs or a member can modify only his jobs. My question is, Do I need to add these constraints in the action of the controller or Is there any Grails way to do that. I have google, the same thing is handled in Ruby and Rails by using routes. And in grails I have skim through RESTful URL mapping, which is perhaps used for this purpose.
Can anyone points me to right direction, thanks. I am using Grails 2.1.1.
You can implement some realization of AbstractPersistenceEventListenerService to not allow perform actions with entity that constains id of not logged in user. Example:
class MultiTenantPersistenceEventListenerService extends AbstractPersistenceEventListenerService {
def springSecurityService
#Override
protected AbstractPersistenceEventListener createPersistenceEventListener(Datastore datastore) {
return new MultiTenantPersistenceEventListener(datastore)
}
}
class MultiTenantPersistenceEventListener extends AbstractPersistenceEventListener {
MultiTenantPersistenceEventListener(final Datastore datastore) {
super(datastore)
}
#Override
protected void onPersistenceEvent(AbstractPersistenceEvent event) {
def entity = event.getEntityObject() // could be your Job domain entity
def user = springSecurityService.getCurrentUser() //current logged in user
if(entity.hasProperty('userId')){ // every job belongs to User
if(entity.userId != user.id){
throw new AccessDeniedException("Acces Denied !")
}
}
}
}
I'd recomment to use grails spring-security-plugin. There is a lot of information in web about plugin and it's easy configurable. Plugin allows you to perfrom controller's action in secure way. For example:
#Secured(['ROLE_USER'])
def followAjax = { ... }
#Secured(['IS_AUTHENTICATED_REMEMBERED'])
def personal = { ... }
For more information - plugin and spring-security with grails.
You can use Authorize attribute to authorize the user,
e.g
[CustomAuthorize(Roles=SiteRoles.Admin|SiteRoles.HelpDesk)]
public ActionResult Index()
{
return View();
}
This is a nice approach for making website secure.
go through these link, this will help you.
custom authorization with asp.net mvc
asp.net mvc authorization