How to remove authorize functionality in case of login endpoint in c#? - c#

I have created two endpoints one for login and other for logout and used JWT token to authorize the endpoint.
So when I authorize the whole class using [Authorize] it authorizes both the login and logout endpoint. Not I want to remove authorize functionality from Login endpoint only.
So how it can be done?
I tried the same using [AllowAnonymous] but it is not working in my case.
Note: I cannot remove authorize from the whole controller and apply it only to the logout endpoint because I have some other cases too and it can not be done.
This is what I tried to do:
[Authorize(JwtBearerDefaults.AuthenticationScheme)]
public class UserController : Controller {
[AllowAnonymous]
public async Task<IActionResult> Login(string userDetails) {
// This action can be accessed by unauthorized users
}
public async Task<IActionResult> Logout(int Id) {
// This action can NOT be accessed by unauthorized users
}
}

Related

Accessing and using UserClaims in ASP.NET Core Web API

I am working on ASP.NET Core Web API for the first time and am pretty new to it.
I have added claims and now I want to sort of "read" and access them.
Can someone help me with that?
It`s actually pretty simple. When you create JWT token you add claims to it. It can be userId, his role etc.
So when you setup authorization with Bearer scheme, every request that require autorization will be validated. For example this method only will be allowed to reach using jwt token with claim-type role of admin :
[Authorize(AuthenticationSchemes = "Bearer")]
public class YourController : ControllerBase
{
...
[HttpGet]
[Authorize(Roles = "admin")]
public async Task<IActionResult> Method(string id)
{
}
...
}
If token doesn't have required claim you will get 403 Forbidden response

Authorize and AllowAnonymous meta data give different behaviour when they are applied on the controller

When i apply this code
with Authorize on controller method and AllowAnonymous
on one of the action methods inside then all of the action method will be authorized except the one that have AllowAnonymous meta data on it.
obviously the action method meta data is overriding the meta data from the controller method
[Authorize]
public class HomeController : Controller
{
public ActionResult About()
{
ViewBag.Message = "Your application description page.";
return View();
}
[AllowAnonymous]
public string Method1()
{
return "The secure method";
}
}
But when i try the opposite with [AllowAnonymous] on the controller method
and with [Authorize] meta data on the action method
then the action method with the [Authorize] will not be AUTHORIZED
Why the behaviour is different?
[AllowAnonymous]
public class HomeController : Controller
{
public ActionResult About()
{
ViewBag.Message = "Your application description page.";
return View();
}
[Authorize]
public string Method1()
{
return "The secure method";
}
}
The [AllowAnonymous] attribute is specifically meant to whitelist a controller or action on a controller. It is intended to be used when you want to literally bypass authorization to allow anonymous access to a resource when your resource is restricted by the [Authorize] attribute applied to either a controller or globally for the entire web application.
this is described here in the Micosoft docs for the AllowAnonymousAttribute:
Specifies that actions and controllers are skipped by AuthorizeAttribute during authorization.
This functionality is also noted on the docs for the AuthorizeAttribute under the Remarks section:
You can declare multiple AuthorizeAttribute per action. You can also use AllowAnonymousAttribute to disable authorization for a specific action.
So in both of your coding examples in your question your action Method1 has the action attribute applied and the controller inherited attribute applied, so both of your examples are exactly the same as doing this:
[AllowAnonymous]
[Authorize]
public string Method1()
{
return "The secure method";
}
Just as stated in the Microsoft docs, just having [AllowAnonymous] on that action specifies that this action is skipped by the AuthorizeAttribute, even though the Authorize attribute is declared on the action as well. This is due to what I was stating earlier that the intent for the [AllowAnonymous] attribute is for whitelisting a resource and bypassing authorization, so in both of your coding examples the [AllowAnonymous] attribute is working exactly as intended by allowing anonymous access to your action even if it was declared to be authorized as well.

How to call connect/authorize without Authorize attribute

I have two Asp.Net Core MVC apps and login system on IdentityServer4.
First app is fully protected, means all controllers are behind [Authorize] attribute and that one works fine.
Second app is public app and has no any [Authorize] attributes.
Issue is on second app on line
#if (User.Identity.IsAuthenticated)
{
#User.Identity.Name
}
because User.Identity.IsAuthenticated is always false.
This piece of code is on razor page which is called from simple action
public IActionResult Index()
{
return View();
}
What I figured out is when I add [Authorize] attribute on this action then there is call to IDS4 'connect/authorize' endpath and User.Identity.IsAuthenticated is authenticated and all works fine.
Trouble is that action should be without [Authorize] attribute and I just want to show user name and/or user email if user is logged in.
Is there any other way to verify cookie and get user info in User.Identity?
You must have the Authorize attribute applied to have User populated. Period. If you don't want to actually restrict access, you can add also the AllowAnonymous attribute. Generally, the best approach is to decorate all controllers that involve users with [Authorize], and then selectively allow access for specific actions using [AllowAnonymous].
Adding authorization and then turning it off with the AllowAnonymous attribute will not trigger authentication. The user has to be challenged at least once. Because only then a cookie will be created, and once created it is send along on each request, even when it is accessable anonymous.
In my case I have a public app where the login button does nothing more than challenge authentication, and return the user to the page it was on afterwards.
public class HomeController : Controller
{
// available for any user
public IActionResult Index()
{
// false for anonymous, true for authenticated users
// also without the Authorize attribute.
var isAuthenticated = User.Identity.IsAuthenticated;
return View();
}
[Authorize]
public IActionResult Login(string returnUrl)
{
return LocalRedirect(returnUrl);
}
}
Like on the other site, add a login link to your menu that calls the login method. But in this case this is the only method that requires the user to login, assuming you don't have an Authorization filter or other Authorization attributes. If the user did login on IdentityServer then the cookie will be created automatically, unless prompt=login.
In Startup configure cookies, something like this:
services
.AddAuthentication(options =>
{
options.DefaultScheme = "Cookies";
options.DefaultChallengeScheme = "oidc";
})
.AddCookie("Cookies", options =>
{
options.Cookie.Name = ".MySite.Cookie";
})
.AddOpenIdConnect("oidc", "Open Id connect", options =>
{
options.SignInScheme = "Cookies";
// etc
The user remains anonymous until the login link is clicked. If you send the user to this site then you can send it to the login link. Otherwise it's up to the user to login on your public mvc website.

Is it possible to use 2 different authorization schemes inside the same MVC Controller class?

I am currently working with a legacy .NET Framework application that has a webclient (MVC) and a mobile client. I have successfully configured my project to use bearer tokens for my webapi controllers and session cookies for my mvc controller using the following in my WebApiConfig.cs:
////Tells APIs to ignore the Default Cookie Type Authentication
config.SuppressDefaultHostAuthentication();
config.Filters.Add(newHostAuthenticationFilter(OAuthDefaults.AuthenticationType);
However, within my MVC contrtollers I have some methods that return an IActionResult() and some that return a JSonResult. Is it possible to define an attribute/authshcema on a per basis controller method that would allow my JsonResult controller methods to use bearer tokens instead of cookies sessions, despite not being inside a webapi controller?? This would allow me to call these controller methods from my mobile client and save me a lot of time having to refactor these methods into separate controllers.
Example:
//MVC Controller (Not Web API)
public class HomeController : Controller
{
//Should use cookie session
public ActionResult Index()
{
return View();
}
//Should use bearer tokens
[HttpGet]
public JsonResult GetPrograms()
{
var menu = _menuService.GetMenu();
return new JsonResult
{
Data = menu,
JsonRequestBehavior = JsonRequestBehavior.AllowGet
};
}
}

AllowAnonymous vs OverrideAuthorizeAttribute

What is the difference in the use of AllowAnonymous and OverrideAuthorizeAttribute.
Is it same?
http://www.asp.net/web-api/overview/security/authentication-and-authorization-in-aspnet-web-api
The two are different, but can have the same effect in certain circumstances.
Authentication is the process of verifying the user. Overrides disable the filter of the override type at the next highest level of scope. Authorization is the process of determining if the user should have access to a specific resource.
The [AllowAnonymous] attribute disables authentication such that web api will skip authentication adn authorization during an access request to a controller decorated with this attribute or to a specific action method decorated with this attribute. Consider the following Controller Class from the article listed in the link
[Authorize]
public class ValuesController : ApiController
{
[AllowAnonymous]
public HttpResponseMessage Get() { ... }
public HttpResponseMessage Post() { ... }
}
In the above example authorized users (any identified user) have access to the post action method but no authorization is required for the Get action method.
Authorization restricts access to resource to those users that belong to those users or user roles that have been granted access. The [OverrideAuthorization] attribute disables the [Authorization] step such that any authenticated user would have access to the action method. This can be seen in the following example taken from the article.
Consider the following Controller Class:
[Authorize(Roles="Admins")]
public class SomeController : ApiController {
[OverrideAuthorization]
[Authorize(Roles="Users")]
public IEnumerable<SomeModel> Get() {...}
public SomeModel Post() {...}
}
In the above example, a user must be authenticated and have a principle to access any of the action methods defined by the controller. However, while only principles with a role of "Admins" can access the Post action method, any authenticated user in the Users role can access the Get action method.
OverrideAuthorizeAttribute describes an attribute which overrides the current functionality of AuthorizeAttribute according to its implementation by any developer (It is not provided in any version of .NET Framework).
AllowAnonymousAttribute is provided by .NET to override the AuthorizeAttribute functionality in a way defined by .NET team. (It is provided in .NET Framework).

Categories

Resources