API, in same project (Blazor server app) with Windows Authentication, not authorizing roles - asp.net-core-webapi

Blazor server app (.net 6.0) which uses Windows Authentication and works properly with Authorizing Roles is not recognizing Authorize Roles in an API I have in the same project. If I have allow anonymous in iis set and use [AllowAnonymous] in API it works fine. (Making an api call from code in same project). If iis does not allow anonymous then I try to use [Authorize(Roles.... but I always get 401 Unauthorized.
I do pass in headers username and password that do a validation that works fine if api set for allowanonymous but if not set then the api Get method never even gets triggered and returns 401.
Shouldn't the API recognize the Authorization? Do I need to configure something different in the project?
[Route("api/[controller]")]
[ApiController]
[Authorize]
public class SampleController : ControllerBase
{
private readonly IConfiguration _config;
private readonly IDataServices _iService;
public SampleController(IDataServices dataAccess, IConfiguration config)
{
this._iService = dataAccess;
_config = config;
}
// GET: api/<SampleController>
[HttpGet]
[Authorize(Roles = "Administrators")]
public async Task<List<SampleModel>> GetAllItems([FromHeader] string username, [FromHeader] string password)
{
List<SampleModel> list = new List<SampleModel>();
if (username == _config.GetValue<string>("SampleSettings:username") && password == _config.GetValue<string>("SampleSettings:password"))
{
list = await _iService.GetList();
}
return list;
}
}
thanks,

Related

HotChocolate with Authorize attribute, how to get currently logged on user?

I've got a GraphQL mutation using HotChocolate with the [Authorize] attribute from HotChocolate.AspNetCore.Authorization to enforce authorization on my GraphQL endpoints.
This works fine, I can only call the mutation once I'm logged in as an Admin ...
... but now I'd like to retrieve the user which is authorized, but I don't seem to find a way to do it.
[ExtendObjectType(Name = "Mutation")]
[Authorize(Roles = new[] { "Administrators" })]
public class MyMutations
{
public bool SomeMethod()
{
// In a regular Web API controller, you can do User.Identity.Name to fetch the user name of the current user. What is the equivalent in Hot Chocolate?
var userName = "";
return false;
}
}
Any ideas?
HotChocolate uses the asp.net core authentication mechanisms, so you can get the user using the HttpContext.
[ExtendObjectType(Name = "Mutation")]
[Authorize(Roles = new[] { "Administrators" })]
public class MyMutations
{
public bool SomeMethod([Service] IHttpContextAccessor contextAccessor)
{
var user = contextAccessor.HttpContext.User; // <-> There is your user
// In a regular Web API controller, you can do User.Identity.Name to fetch the user name of the current user. What is the equivalent in Hot Chocolate?
var userName = "";
return false;
}
}

.NET Core Identity Server dynamic Client app registration and authentication

I have created an Identity Server using .NET Core and IdentityServer4, I have set of APIs and all calls to these APIs must be authenticated but these APIs might be used by third-party applications so clients can be dynamic
Till now example I am finding is set Clients on startup statically like
public void ConfigureServices(IServiceCollection services)
{
services.AddIdentityServer()
.AddDeveloperSigningCredential()
.AddInMemoryApiResources(Config.GetApiResources())
.AddInMemoryClients(Config.GetClients());
}
public class Config
{
public static IEnumerable<ApiResource> GetApiResources()
{
return new List<ApiResource>
{
new ApiResource("resourceApi1", "API Application1")
new ApiResource("resourceApi2", "API Application2")
};
}
public static IEnumerable<Client> GetClients()
{
return new List<Client>
{
new Client
{
ClientId = "clientApp1",
// no interactive user, use the clientid/secret for authentication
AllowedGrantTypes = GrantTypes.ClientCredentials,
// secret for authentication
ClientSecrets =
{
new Secret("secret".Sha256())
},
AllowedScopes = { "resourceApi1" }
}
};
}
}
Is there a way in IdentityServer implementation to register Client Apps and set dynamically
For Example, If I have APIs
1. resourceApi1
2. resourceApi2
Each third-party APIs should be able to register and we should be able to generate ClientID and Client secret for each with what resources they can access and Identity Server authenticates that ClientID and Client Secret?
There is an option to use a client store. By default identity server uses in memory store for finding clients:
services.AddIdentityServer()
.AddInMemoryClients(Clients)
You can change this and register your own client store
services.AddIdentityServer()
.AddClientStore<MyClientStore>()
and implement the service
class MyClientStore : IClientStore
{
public Task<Client> FindClientByIdAsync(string clientId)
{
}
}
This would solve dynamic lookup of clients. For registration of clients and their management, you would need to implement your own infrastructure.
First of all configure your IdentityServer using EntityFramework, Then you need to some Apis to add Client and ApiResources.
IdentityServer has its own implementation of Stores using EntityFramework.
You can add new Api for this purpose.
[Route("api/[controller]")]
[ApiController]
[AllowAnonymous]
public class DynamicController : ControllerBase
{
private readonly ConfigurationDbContext context;
public DynamicController(ConfigurationDbContext context)
{
this.context = context;
}
[HttpPost]
public async Task<ActionResult> AddApiResource(ApiResource apiResource)
{
context.ApiResources.Add(apiResource);
await context.SaveChangesAsync();
return Ok();
}
[HttpPost]
public async Task<ActionResult> AddClient(Client client)
{
context.Clients.Add(client);
await context.SaveChangesAsync();
return Ok();
}
}

Why asp.net core project is crashing, when EFCore try to return data to controller from repository?

I am trying to fetch data from database by using EFCore in my asp.net core mvc application, but application crashes, when repository try to return data to controller.
Tools I am using Vs2017, MSSQL2017, Asp.net Core 2.2, EFCore2.2. I have made a repository which authenticate user from database. When I try to authenticate user through repository by sending username and password through controller, so application crashes.
Even though I can see while debugging that user is authenticated and repository fetching that user from database. But when repository try to return user to controller, so application crashes. It does not generate any kind Exception, but crashes as soon as repository try to return user.
But I can see some information in the output windows of Vs2017, which is as follows
"iisexpress.exe' has exited with code -1073741819 (0xc0000005) 'Access violation"
Controller Code
public class LoginController : AppController
{
private readonly IUserRepository _userRepository;
public LoginController(IUserRepository userRepository)
{
_userRepository = userRepository;
}
[HttpGet]
public IActionResult Login()
{
return View(new LoginViewModel());
}
[HttpPost]
public IActionResult Login(LoginViewModel loginViewModel)
{
loginViewModel.Password = EncryptionLibrary.EncryptText(loginViewModel.Password);
var user = _userRepository.FindUser(loginViewModel.Username, loginViewModel.Password);
if ( user!= null)
{
this.CurrentSaleState.Login.Id = user.Id;
return RedirectToAction("Create", "RegisterCompany");
}
return null;
}
}
Repository Code
public UserModel FindUser(string userName, string password)
{
using (IRepositoryContext context = _repositoryFactory.CreateContext())
{
var user = context.Set<User>().FirstOrDefault(u => u.Username == userName && u.Password == password);
var userModel = _modelMapper.Map<User, UserModel>(user);
return userModel;
}
}
I expect that after authenticating user should move to another page.
I'm probably too late to the party but just for whoever wanders here.
I see you're using a mapper.
In my case this exact situation was caused by a StackOverflowException due to erroneous mapping.

Spring Cloud Zuul Doesn't Relay Access Token

I am trying to use Spring Cloud Zuul as an api/authentication gateway. I have successfully implemented bearer token authorization for my service behind zuul and I successfully have Zuul forwarding to my form login and routing back to my application, but I cannot get Zuul to pass the bearer token to the service.
My Zuul configuration is as follows:
#EnableEurekaClient
#EnableZuulProxy
#SpringBootApplication
#RestController
public class Application { ... }
My service configuration is as follows:
#Profile("oauth")
#Configuration
#EnableResourceServer
#EnableWebSecurity
public static class InternalApiGatewayConfig extends ResourceServerConfigurerAdapter {
When my Angular app tries to access my service through zuul, I get
{"error":"unauthorized","error_description":"Full authentication is required to access this resource"}
I have managed to work around this issue by putting the following code in a ZuulFilter, but it doesn't seem right:
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
OAuth2AuthenticationDetails details = (OAuth2AuthenticationDetails)authentication.getDetails();
String tokenValue = details.getTokenValue();
ctx.addZuulRequestHeader("Authorization", "bearer " + tokenValue);
My understanding is that Zuul should automatically send the bearer token value. What am I missing?
So I've figured out the answer to my own question, and it was painfully simple. My project imported spring-security-oauth2. I simply needed to add a dependency on spring-cloud-security as well. With that, I did not have to implement a ZuulFilter at all.
Btw this is the solution that works without spring-cloud-security
#Component
public class TokenRelayFilter extends ZuulFilter {
#Override
public Object run() {
RequestContext ctx = RequestContext.getCurrentContext();
#SuppressWarnings("unchecked")
Set<String> headers = (Set<String>) ctx.get("ignoredHeaders");
// JWT tokens should be relayed to the resource servers
headers.remove("authorization");
return null;
}
#Override
public boolean shouldFilter() {
return true;
}
#Override
public String filterType() {
return "pre";
}
#Override
public int filterOrder() {
return 10000;
}
}

How to add logging for unauthorized access for [Authorize] filter in webapi

I created an ASP.NET Web API 2 end point, with controllers protected with the [Authorized] attribute.
Unauthenticated access will get 401 UnAuthorized http status.
Now, I want to log those unauthorized access to a log file. However, I don't know where to handle the unauthorized access.
The solution would just be to create a custom Authorize filter inheriting from default Authorize attribute this way:
public class LogAuthorizeAttribute : AuthorizeAttribute
{
protected override bool IsAuthorized(System.Web.Http.Controllers.HttpActionContext actionContext)
{
var authorized = base.IsAuthorized(actionContext);
if (!authorized)
{
// log the denied access attempt.
}
return authorized;
}
}
This way, you keep the same authorize validation from parent, but you can do additional thing such as logging in your case for unauthorized access.
You can then simply use it on your Web API methods:
public class ValuesController : ApiController
{
[LogAuthorize]
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
}

Resources