@robotdan Yes it is the same. We can continue the discussion here.
Posts made by ethalacker
-
RE: Blazor WASM auth
-
Blazor WASM auth
Currently trying to get Blazor WASM (Web Assembly) to work with Fusion Auth.
My initial issue was to get to fusion auth at all and I was having a CORS issue. I ended up having to enable all CORS origins for now.
Which brings me to the issues I am experiencing now. I believe these are each related to CORS as well and probably only an issue because I am on localhost.
-
I am not getting a clean redirect to FusionAuth. Though, it does eventually redirect to the provider.
Refused to display 'http://localhost:9011/oauth2/authorize?client_id=ff87ab0d-0a7e-4bcc-af02-8fbf31a92b66&redirect_uri=https%3A%2F%2Flocalhost%3A5001%2Fauthentication%2Flogin-callback&response_type=code&scope=openid profile openid&state=30eaea5137a6491eb2447547c6948c7a&code_challenge=6KbxXv06jvGjTIG_KxvY2K6HRHy9v52z22usno4BnYk&code_challenge_method=S256&prompt=none&response_mode=query' in a frame because it set 'X-Frame-Options' to 'deny'. -
Once I login and get back from Fusion Auth, I get the following error:
Access to XMLHttpRequest at 'http://localhost:9011/oauth2/token' from origin 'https://localhost:5001' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
And
POST http://localhost:9011/oauth2/token net::ERR_FAILED
My Program.cs file looks like the following:
public class Program { public static async Task Main(string[] args) { var builder = WebAssemblyHostBuilder.CreateDefault(args); builder.RootComponents.Add<App>("#app"); builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) }); builder.Services.AddOidcAuthentication(options => { builder.Configuration.Bind("FusionAuth_test", options.ProviderOptions); options.ProviderOptions.ResponseType = "code"; options.ProviderOptions.RedirectUri = "https://localhost:5001/authentication/login-callback"; options.ProviderOptions.PostLogoutRedirectUri = "https://localhost:5001/"; options.ProviderOptions.DefaultScopes.Add("openid"); }); await builder.Build().RunAsync(); } }
Where
FusionAuth_Test
config looks like the following:{ "Local": { "Authority": "https://login.microsoftonline.com/", "ClientId": "33333333-3333-3333-33333333333333333" }, "FusionAuth_test": { "Authority": "http://localhost:9011", "ClientId": "myIDhere" } }
To Replicate
- Use the new .NET 5 sdk.
dotnet new blazorwasm -au Individual -o BlazorAuthSample5
in the CLI/powershell- copy my Program.cs into yours. Only a few lines added/replaced.
- change wwwroot/appsettings.json to include your fusionAuth clientId
dotnet run
on folder and try to login
-
-
RE: MVC Application that routes to different (fusion auth) tenants
But but that doesn't have access to the request.. or at least not that I saw/could figure out.
Instead I did something like this:
Startup.cs
// app is Owin.IAppBuilder app.Use<MyCustomAuthMiddleware>(app, FusionAuthHelper.MakeOptions());
MyCustomAuthMiddleware
public class MyCustomAuthMiddleware : OpenIdConnectAuthenticationMiddleware { public MyCustomAuthMiddleware(OwinMiddleware next, IAppBuilder app, OpenIdConnectAuthenticationOptions options) : base(next, app, options) { } public override Task Invoke(IOwinContext context) { // can do something like this if you want a service of something // var session = DependencyResolver.Current.GetService<ISession>(); if (context.Request.Host.Value.Contains("clientname")) { Options.ClientId = "clientNames_clientId"; Options.RedirectUri = "clientNames_RedirectUri"; Options.ClientSecret = "clientNames_ClientSecret"; Options.TokenValidationParameters.ValidAudience = "clientNames_clientId"; Options.ConfigurationManager = new DynamicConfigurationManager("clientNames_clientId", "clientNames_tenantId"); } else { Options.ClientId = "mySite_clientId"; Options.RedirectUri = "mySite_redirectUri"; Options.ClientSecret = "mySite_clientSecret"; Options.TokenValidationParameters.ValidAudience = "mySite_clientId"; Options.ConfigurationManager = new DynamicConfigurationManager("mySite_clientId", "mySite_tenantId"); } // could continue this pattern for "anotherClient" return base.Invoke(context); } }
FusionAuthHelper
public static class FusionAuthHelper { public static OpenIdConnectAuthenticationOptions MakeOptions() { return new OpenIdConnectAuthenticationOptions { AuthenticationType = OpenIdConnectAuthenticationDefaults.AuthenticationType, SignInAsAuthenticationType = CookieAuthenticationDefaults.AuthenticationType, ResponseType = OpenIdConnectResponseType.Code, CallbackPath = new PathString("/oauth/callback"), Scope = OpenIdConnectScope.OpenId, RequireHttpsMetadata = false, Authority = "http://localhost:9011", SaveTokens = true, RedeemCode = true, Notifications = new OpenIdConnectAuthenticationNotifications { SecurityTokenValidated = OnSecurityTokenValidated } }; } private static Task OnSecurityTokenValidated(SecurityTokenValidatedNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> notification) { var userId = new Guid(notification.AuthenticationTicket.Identity.GetUserId()); var userRepository = DependencyResolver.Current.GetService<IUserRepository>(); var user = userRepository.Query().Where(u => u.IsActive) .Where(u => u.Guid == userId) .Select(u => new { //stuff }) .SingleOrDefault(); if (user == null) { //do soemthing if the user isn't found } else { notification.AuthenticationTicket.Identity.AddClaim(new Claim("MyCoolClaim", user.Soemthing.ToString())); } return Task.CompletedTask; } }
DynamicConfigurationManager
public class DynamicConfigurationManager : IConfigurationManager<OpenIdConnectConfiguration> { private string clientId; private string tenantId; public DynamicConfigurationManager(string clientId, string tenantId) { this.clientId = clientId; this.tenantId = tenantId; } public async Task<OpenIdConnectConfiguration> GetConfigurationAsync(CancellationToken cancel) { var authority = "http://localhost:9011"; var stsDiscoveryEndpoint = string.Format("{0}/.well-known/openid-configuration/{1}", authority, this.tenantId); ConfigurationManager<OpenIdConnectConfiguration> configManager = new ConfigurationManager<OpenIdConnectConfiguration>(stsDiscoveryEndpoint , new OpenIdConnectConfigurationRetriever() , new HttpDocumentRetriever() { RequireHttps = false }); var config = await configManager.GetConfigurationAsync(cancel); config.EndSessionEndpoint = config.EndSessionEndpoint + "?client_id=" + this.clientId; return config; } public void RequestRefresh() { } }
here are my usings in case you wonder what packages I was using
using Microsoft.AspNet.Identity; using Microsoft.Extensions.DependencyInjection; using Microsoft.IdentityModel.Protocols; using Microsoft.IdentityModel.Protocols.OpenIdConnect; using Microsoft.Owin; using Microsoft.Owin.Security.Cookies; using Microsoft.Owin.Security.Notifications; using Microsoft.Owin.Security.OpenIdConnect; using Owin; using System; using System.Linq; using System.Security.Claims; using System.Threading; using System.Threading.Tasks; using System.Web; using System.Web.Mvc;
I'm not sure if this will create 1, or 2 options instances in the middleware.. So that might be an issue. I haven't tested it enough. Might just need to put all the FusionAuthHelper options into the middleware class.
Also, I think this will only work for MVC .Net Framework. Still need to come up with solution for .NET Core
-
MVC Application that routes to different (fusion auth) tenants
I am using a MVC app (.net Core and .net Framework MVC specifically) that needs to route to different tenants depending on the url they go to.
For example:
User A goes to www.mysite.com and I want them to go to Tenant1's login page.
User B goes to www.clientname.mysite.com and I want them to go to Tenant2's login page.
Similary,
User C goes to www.anotherclient.mysite.com and I want them to go to Tenant3's login page.The issue I am running into, is that my OpenIdConnect Options is defined at the build and not per request.
My OpenIdConnect Options look like the following:private const string clientSecret = "mySecretKey"; private const string clientId = "myCleintIdGuid"; public static OpenIdConnectAuthenticationOptions MakeOptions() { return new OpenIdConnectAuthenticationOptions { AuthenticationType = OpenIdConnectAuthenticationDefaults.AuthenticationType, SignInAsAuthenticationType = CookieAuthenticationDefaults.AuthenticationType, ResponseType = OpenIdConnectResponseType.Code, CallbackPath = new PathString("/oauth/callback"), // this part needs to become dynamic RedirectUri = "https://clientname.mysite.com/oauth/callback", Scope = OpenIdConnectScope.OpenId, RequireHttpsMetadata = false, ClientId = clientId, Authority = "http://localhost:9011", ClientSecret = FusionAuthHelper.clientSecret, SaveTokens = true, RedeemCode = true, Notifications = new OpenIdConnectAuthenticationNotifications { RedirectToIdentityProvider = OnRedirectToIdentityProvider(), SecurityTokenValidated = OnSecurityTokenValidated() } }; }
Now, this works great for User B going to www.clientname.mysite.com (from my example above), but doesn't work for User A or User C
My Fusion Auth Looks like the following:
There might be other (FusionAuth)Applications for each tenant. But that can be a separate problem to solve if need be.
How can I do this? Or, at least, what can I look up to figure out how to best solve this issue?