Delete the expired or invalid openiddict tokens used in azure function - .net-core

I am working on an azure function which is a part of a system. The authentication/ authorization of system is controlled by OpenIdDict library. After using our system for sometime in our production, there are millions of invalid and expired tokens in the OpenIddictTokens table which I believe is causing some of the calls in our system to slowdown.
Now I am working on a time triggered azure function whose purpose is to delete (get rid of) all the useless tokens & authorizations saved in the OpenIddictTokens and OpenIddictAuthorizations tables respectively.
I started looking at the openiddict documentation and api but could not find the exact match for my requirements related to implementation in azure yet.
Can someone please help? Thanks.

After looking into the documentation and experimenting with code, I was able to find the method and how to use this in my azure functions app.
First add the dependency for openiddict in startup:
builder.Services.AddOpenIddict()
// Register the OpenIddict core services.
.AddCore(options =>
{
// Register the Entity Framework stores and models.
options.UseEntityFrameworkCore()
.UseDbContext<ApplicationDbContext>();
});
Then create the respective function with the IOpenIddictAuthorizationManager and IOpenIddictTokenManager as dependencies and call the PruneAsync method for both.
private readonly IOpenIddictAuthorizationManager _openIddictAuthorizationManager;
private readonly IOpenIddictTokenManager _openIddictTokenManager;
public PruneTokenFunction(IOpenIddictAuthorizationManager openIddictAuthorizationManager, IOpenIddictTokenManager openIddictTokenManager)
{
_openIddictAuthorizationManager = openIddictAuthorizationManager;
_openIddictTokenManager = openIddictTokenManager;
}
[FunctionName("prunetoken")]
public async Task Run([TimerTrigger("0 */5 * * * ")] TimerInfo timerInfo)
{
await _openIddictTokenManager.PruneAsync(DateTimeOffset.Now.AddDays(-1));
await _openIddictAuthorizationManager.PruneAsync(DateTimeOffset.Now.AddDays(-1));
}
Also following is the issue related to same query which might be helpful to many. Implement automatic expired token flushing

Related

Audit.NET EntityFramework

I am trying to replace our own Audit system with Audit.NET. I have checked the documentation for Audit.EntityFramework, https://github.com/thepirat000/Audit.NET/tree/master/src/Audit.EntityFramework, and it is not clear to me where the configuration setup should be added. Also, lets say I am building a ASP.NET CORE RestFUL API and need to keep track of users making changes by extracting user information from a JWT, how would I set that up with Audit.EntityFramework?
In the documentation there is the follow code snippet to configure audits for orders and tracking users :
Audit.Core.Configuration.Setup()
.UseEntityFramework(ef => ef
.AuditTypeExplicitMapper(m => m
.Map<Order, Audit_Order>()
.Map<OrderItem, Audit_OrderItem>()
.AuditEntityAction<IAudit>((evt, entry, auditEntity) =>
{
auditEntity.AuditDate = DateTime.UtcNow;
auditEntity.UserName = evt.Environment.UserName;
auditEntity.AuditAction = entry.Action; // Insert, Update, Delete
})
)
);
However, if I would add that in the Startup.cs it would not help track what each user is doing on each call made by different users on the different endpoints. Do you have any example of how I can do this using Audit.EntityFramework?
Thanks
Have you seen the main Audit.NET documentation?
Yes, the setup must be executed before any audit takes place, so on your start-up code should be fine.
If you need to add more information to the audit events you could use custom actions that also should be setup on your start-up code. That doesn't mean you have to set the value at the start-up, but you have to provide a way to get the value on the start-up. For example if you need something from the current HttpContext, you could get it from an HttpContextAccessor. For example:
public void Configure(IApplicationBuilder app, IHttpContextAccessor contextAccessor)
{
// ...
Audit.Core.Configuration.AddCustomAction(ActionType.OnScopeCreated, scope =>
{
var httpContext = contextAccessor.HttpContext;
// Add a new field
scope.Event.CustomFields["CorrelationId"] = httpContext.TraceIdentifier;
// reuse an existing field
scope.Event.Environment.UserName = GetUserFromContext(httpContext);
});
}
Also, Audit.NET provides two libraries Audit.WebApi and Audit.MVC to audit Web API and/or MVC calls.
Also there is a dotnet new template exposed you could use to quickly create a minimal WebAPI/MVC project with audit enabled and using entity framework. For example:
dotnet new -i Audit.WebApi.Template
dotnet new webapiaudit -E

How can I (simply) enable CORS on my Azure webrole API

I have an Azure webrole which is running an API service. I'm trying to enable CORS so that the API can be consumed by browser scripts. There are a quite a few questions that refer to enabling CORS on web-api applications but I haven't found one that gives an answer for webroles.
I've tried adding the magic customheaders block from this answer to my web.config but that doesn't work.
This document from Microsoft implies that the Microsoft.AspNet.Cors nuget package may be used but it's unclear to me how to get hold of the HttpConfiguration from within a webrole OnStart method. It also seems odd that I have to decorate every one of my API methods. Is there not a single 'switch' I can flick to enable CORS for the entire service?
Related questions...
What's the easiest way to verify that CORS is actually enabled? At the moment I'm using a Blazor PostJsonAsync call and relying on that to pass but it's getting pretty tedious repeatedly reconfiguring and uploading the role to Azure to try out changes.
Bigger question...am I fighting against the tide using a webrole? Much of the documentation refers to web-api and web-apps. Maybe these are the future and webroles are deprecated?
I would also recommend moving over to webapps. However, you might also get it to work with web roles and how you apply cors there also works for webapps if you use OWIN.
You might host your API in the web role like this:
https://learn.microsoft.com/en-us/aspnet/web-api/overview/hosting-aspnet-web-api/host-aspnet-web-api-in-an-azure-worker-role
This gives you the HttpConfiguration you need (Startup.cs).
It also seems odd that I have to decorate every one of my API methods. Is there not a single 'switch' I can flick to enable CORS for the entire service?
You can use an ICorsPolicyProvider to enable it everywhere:
// in startup.cs
config.EnableCors(new AllowAllCorsPolicyProvider());
public class AllowAllCorsPolicyProvider : ICorsPolicyProvider
{
readonly CorsPolicy _CorsPolicy;
public AllowAllCorsPolicyProvider()
{
_CorsPolicy = new CorsPolicy {AllowAnyHeader = true, AllowAnyMethod = true, AllowAnyOrigin = true};
}
public Task<CorsPolicy> GetCorsPolicyAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
return Task.FromResult(_CorsPolicy);
}

"System.Net.HttpListener" not available in IAppBuilder properties

I am developing a web app with mix authentication (Owin Token Based and Windows authentication). I have implemented Owin token based authentication and want to implement windows authentication for the users which are marked as active directory users.
In Owin middleware, I want to get requesting user's windows username. I am getting object in OwinContext.Request.User.Identity. However, OwinContext.Request.User.Identity.Name is always blank string.
I found that I should add below lines in startup.cs:
var listener = (HttpListener)app.Properties["System.Net.HttpListener"];
listener.AuthenticationSchemes = AuthenticationSchemes.IntegratedWindowsAuthentication;
However, I am getting key not found exception. "System.Net.HttpListener" is not present in Properties array. I have installed Microsoft.Owin.SelfHost, Microsoft.Owin.Host.HttpListener. However, I am still getting the error.
Any help is greatly appreciated.
Thanks,
GB
For me issue was that project was started as shared lib, not a web app.
Solution was to add a line into .cspro file after <ProjectGuid> line.
<ProjectTypeGuids>{349C5851-65DF-11DA-9384-00065B846F21};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
Then you dont need to add HttpListener explicitly, just reload project and follow this instructions starting from Properties edition part.
Enabling Windows Authentication in Katana
You can access principal the same ways:
Get the user in an OWIN middleware:
public async Task Invoke(IDictionary<string, object> env)
{
OwinContext context = new OwinContext(env);
WindowsPrincipal user = context.Request.User as WindowsPrincipal;
//...
}
Get the user in a Web API Controller:
// In a web api controller function
WindowsPrincipal user = RequestContext.Principal as WindowsPrincipal;
UPD: List of Visual Studio Projects GUIDs

Invalid Token when using ASP.NET MVC 5 and Dependency Injection with Unity

I am building an ASP.NET MVC 5 website and am using Unity for dependency injection. I get an Invalid Token exception when some time has passed (more than an hour, less than a day) between the token generation and the token validation.
I have the following code in my Startup.cs:
internal static IDataProtectionProvider DataProtectionProvider { get; private set; }
public void Configuration(IAppBuilder app)
{
DataProtectionProvider = app.GetDataProtectionProvider();
ConfigureAuth(app);
}
I have the following code in the conctructor of my ApplicationUserManager class (timespan is set to 7 days now just to make sure that is not the issue):
var dataProtectionProvider = Startup.DataProtectionProvider;
if (dataProtectionProvider != null)
{
this.UserTokenProvider = new DataProtectorTokenProvider<ApplicationUser> (dataProtectionProvider.Create("ASP.NET Identity")) {
TokenLifespan = TimeSpan.FromDays(7)
};
}
In Startup.Auth.cs, I have the following line of code in the ConfigureAuth method:
app.CreatePerOwinContext(() => DependencyResolver.Current.GetService<ApplicationUserManager>());
In UnityConfig.cs, I have set up dependency injection:
container.RegisterType<ApplicationDbContext>();
container.RegisterType<ApplicationSignInManager>();
container.RegisterType<ApplicationUserManager>();
container.RegisterType<ApplicationRoleManager>();
container.RegisterType<IAuthenticationManager>(
new InjectionFactory(c => HttpContext.Current.GetOwinContext().Authentication)
);
container.RegisterType<IUserStore<ApplicationUser>, UserStore<ApplicationUser>>(
new InjectionConstructor(typeof(ApplicationDbContext))
);
container.RegisterType<IRoleStore<IdentityRole, string>, RoleStore<IdentityRole>>(
new InjectionConstructor(typeof(ApplicationDbContext))
);
I have to add that one of my scenarios allows for the creation of a Contact with an associated user account. The Contact and associated user account are created in the ContactController, while the ConfirmEmail method is in the AccountController. Both take ApplicationUserManager as a constructor parameter, which means the ApplicationUserManager is injected into the controllers.
That does not appear to be the issue, since everything works fine if I confirm right after receiving the confirmation email. However, if I wait an hour or so, and then try to confirm, I get the Invalid Token exception.
I have already verified that I am not accidentally mixing different token types, both generation and verification are for email confirmation. I have also verified that I am url encoding (and decoding) the token.
I am currently testing on an Azure virtual machine with a static IP that is running its own IIS, the production environment will most likely be on a non-Azure VPS, als running its own IIS. I am not an Azure expert, but to my knowledge, I didn't select any options that are related to load balancing.
I would really appreciate your help, as I have already tried any possible solutions I was able to find here and on other websites.
The Invalid token issue has been solved. Since it only happened after some time had passed, I figured it might have something to do with my application recycling.
I managed to get rid of the problem by setting a fixed MachineKey in my web.config. You can use IIS Manager to generate it, as described here: https://blogs.msdn.microsoft.com/vijaysk/2009/05/13/iis-7-tip-10-you-can-generate-machine-keys-from-the-iis-manager/
Please note: for some reason, IIS adds the IsolateApps when it generates a machine key. However, this results in ASP.NET throwing an exception. After you manually remove the IsolateApps and save, it should work as expected.

Spring Social Facebook

I am developing with Spring Social and Thymeleaf from the quick start example, but I realised that it only supports one Facebook object per controller. This means the sample can't provide support for multiple users and I am guessing it has to do with the #Scope of the variable. Its runs in a Spring boot container and I wonder how I can configure this so that each session has its own Facebook object.
As you suggested, the Facebook object should be configured with request scope. If you're using the configuration support and/or Spring Boot, then it will be request scoped. Therefore, even though the controller is injected once with a Facebook instance, that instance is really a proxy that will delegate to a real FacebookTemplate instance that is created at request time for the authenticated user.
I can only assume that you're referring to the getting started guide example at http://spring.io/guides/gs/accessing-facebook/. In that case, it's using the most simple Spring Boot autoconfiguration possible for Spring Social, which includes a basic (yet not intended for production) implementation of UserIdSource which always returns "anonymous" as the user ID. Therefore, after you create the first Facebook connection, the second browser tries to find a connection for "anonymous", finds it, and gives you an authorized Facebook object.
This may seem peculiar, but it is an example app intended to get you started...and it does that. All you need to do to get a real UserIdSource is to add Spring Security to the project. That will tell Spring Social autoconfiguration to configure a UserIdSource that fetches the current user ID from the security context. This reflects a more real-world use of Spring Social, albeit obviously more involved and beyond the scope of the getting started guide.
But you can look at https://github.com/spring-projects/spring-social-samples/tree/master/spring-social-showcase-boot for a more complete example of Spring Social within Spring Boot.
Spring Boot autoconfigures a lot of things behind the scenes. It does autoconfigure the Facebook, LinkedIn and Twitter properties and sets up the connection factories for social providers.
However, the implementation of UserIdSource always returns “anonymous” as the user ID. Once the first Facebook connection is established the second browser will try to find a connection for “anonymous” which it finds and gives you an authorised Facebook object.
#Configuration
#EnableSocial
#ConditionalOnWebApplication
#ConditionalOnMissingClass("org.springframework.security.core.context.SecurityContextHolder")
protected static class AnonymousUserIdSourceConfig extends SocialConfigurerAdapter {
#Override
public UserIdSource getUserIdSource() {
return new UserIdSource() {
#Override
public String getUserId() {
return "anonymous";
}
};
}
}
Solution
The solution is to override the “anonymous” as the UserId for each new user/session. So for each session, we can simply return a SessionID, however, it may not be unique enough to identify users, especially if it’s being cached or stored somewhere in a connection database.
#Override
public String getUserId() {
RequestAttributes request = RequestContextHolder.currentRequestAttributes();
String uuid = (String) request.getAttribute("_socialUserUUID", RequestAttributes.SCOPE_SESSION);
if (uuid == null) {
uuid = UUID.randomUUID().toString();
request.setAttribute("_socialUserUUID", uuid, RequestAttributes.SCOPE_SESSION);
}
return uuid;
}
The solution for above problem has been talked about in detail over here

Resources