aspnet / AspNetKatana

Microsoft's OWIN implementation, the Katana project
Apache License 2.0
967 stars 334 forks source link

Configure OpenIDConnectAuthentication (i.e Client ID & Secret) using Database rather than web.config #359

Closed din-prajapati closed 11 months ago

din-prajapati commented 4 years ago

Hello Folks,

Currently; it looks like Client ID & Authority is mandatory for OpenIDConnectAuthentication and that is only configurable in Startup file. So, we are left with only one option that ClientID & ClientSecret can be fetched from web.config file only.

app.UseOpenIdConnectAuthentication(New OpenIdConnectAuthenticationOptions With {
            .ClientId = appId,
            .ClientSecret = appSecret,
            .Authority = "https://login.microsoftonline.com/common/v2.0",
            .Scope = $"openid email profile offline_access {ewsScopes}",
            .RedirectUri = redirectUri,
            .PostLogoutRedirectUri = redirectUri,            
            .TokenValidationParameters = New TokenValidationParameters With {
                .ValidateIssuer = False
            },
            .Notifications = New OpenIdConnectAuthenticationNotifications With {
                .AuthenticationFailed = AddressOf OnAuthenticationFailedAsync,
                .AuthorizationCodeReceived = AddressOf OnAuthorizationCodeReceivedAsync
            }
        }) 

Can we have any mechanism that allows us to configure the OpenIDConnectAuthentication dynamically in ASP.NET MVC ? i think and there must be some way by which we can configure ClientID and ClientSecret from Database rathar than web.config in Startup.Auth.cs. I think; it will be good feature where based on the OAuth configuration in Database. it will work accordingly.

Tratcher commented 4 years ago

Would that be dynamically per tenant? This component is not designed for multi-tenancy and we have no plans to add it.

For a small number of tenants you can add multiple instances of the middleware so long as the AuthenticationType and CallbackPath are unique.

din-prajapati commented 4 years ago

Thanks for your response.

At this moment; I would like to know how we can configure OpenIDConnectAuthentication (i.e. Stored Client ID & Client Secret fetched from DB in Startup file or some other way) dynamically in ASP.NET MVC ?

Let me give you little heads up about situation => After Application level Login; we are presenting user which mail system (google or exchange) they want to use and accordingly it will perform Open ID OAuth flow. So at a time it would be only one OAuth flow (dynamic). So having said that; we are storing their Client ID and Client Secret in database. Based on the configuration; Application has to perform Open ID OAuth flow.

Yes, Callback will be different for each one and as of now Auth provider are limited to only google or exchange.

Any help will be highly appreciated.

Tratcher commented 4 years ago

Middleware aren't per-user, they're for the whole application.

The client id and secret aren't user specific, right? If there really are only two providers then you should add them both at startup.

din-prajapati commented 4 years ago

Yes, it's for the whole application and I have that use case as well. It's just those settings are required to be stored at database level. So how could we fetch those settings from database at startup.

din-prajapati commented 4 years ago

One more thing; when "AuthorizationCodeReceived" or "AuthenticationFailed" event fired; I found that session got cleared out. I no longer found any session values which are there before OAuth flow? Could you please let me know how can preserve session values during OAuth flow and redirec?

Tratcher commented 4 years ago

Yes, it's for the whole application and I have that use case as well. It's just those settings are required to be stored at database level. So how could we fetch those settings from database at startup.

Properly abstracted, you'd want a database implementation of IConfiguration, but I haven't seen any examples of that.

Since this is all set up during ConfigureServices you'd have trouble using anything that was based on the current DI container. That's improved in 5.0 via https://github.com/dotnet/aspnetcore/pull/19268. There are some workarounds for accessing services as part of your auth config in https://github.com/dotnet/aspnetcore/issues/18772. Note for accessing your database you'd need to create a scope first. https://docs.microsoft.com/en-us/aspnet/core/tutorials/razor-pages/sql?view=aspnetcore-3.1&tabs=visual-studio#add-the-seed-initializer

One more thing; when "AuthorizationCodeReceived" or "AuthenticationFailed" event fired; I found that session got cleared out.

What session? HttpContext.Session? That's not associated with auth. The only reason session might be missing after an auth login is that the cookie wasn't sent for reasons such as SameSite. Check the session cookie properties.

din-prajapati commented 4 years ago

Thanks Tratcher for you reply.

i will take a look on the links you have provided but i afraid those will not be useful as it is related to Asp.net Core. I am using Owin in MVC project so i do not have IServiceCollection object and have not found any sample which allows me to use that in OWIN.

What session? HttpContext.Session? That's not associated with auth. The only reason session might be missing after an auth login is that the cookie wasn't sent for reasons such as SameSite. Check the session cookie properties.

Yes, it is HttpContext.Session. and thanks for pointing out SameSite cookie direction. As per couple of Stack overflow link below; using either URL rewrite or below web.config allows us to maintain session when response is posted back to Callback url but we still need to use Owin's SystemWebCookieManager for that in order to work.

https://stackoverflow.com/questions/59269476/browser-wont-set-asp-net-sessionid-cookie-on-payment-gateways-post-request-to

https://stackoverflow.com/questions/59117357/how-samesite-attribute-added-to-my-asp-net-sessionid-cookie-automatically

<sessionState cookieSameSite="None" />

Considering above scenario; for OpenIDConnect Authentication; setting samesite cookie to none and secure; that should work but i afraid that would raise CSRF (Cross site request Forgery) vulnerability for application. Though our site will run in HTTPS mode. But still i would like to know you view; on SameSite cookie none and secure option. Does it secure ? if not; what are other options for openidconnect same site cookie issue.

Again thanks for your direction; I have been crazy about this issue from quite sometime.

Tratcher commented 4 years ago

i will take a look on the links you have provided but i afraid those will not be useful as it is related to Asp.net Core. I am using Owin in MVC project so i do not have IServiceCollection object and have not found any sample which allows me to use that in OWIN.

Right, I forgot which project I was posting to. For an OWIN project you can try EF6.

OpenIDConnect uses form post redirects which are incompatible with SameSite. Your alternative is to switch to the Code response type which uses HTTP redirects and works with SameSite=Lax.

https://github.com/aspnet/AspNetKatana/blob/635c92f641ad1e014eead31cc7a365004949fda5/src/Microsoft.Owin.Security.OpenIdConnect/OpenIdConnectAuthenticationOptions.cs#L65-L66

din-prajapati commented 4 years ago

Yes Code based flow works well with SameSite = Lax.

Since; our application is legacy one (ADO.NET) and we will not be able to use EF. However; i still think it would be good idea that OWIN allows by any way (ie. executing code in middleware) which allows us change client id, secrete from database etc before initiating oAuth Flow.

Right now; i have removed the OWIN dependency to make it work since i am using code based oAuth Flow.

Thanks for your help.