FusionAuth
    • Home
    • Categories
    • Recent
    • Popular
    • Pricing
    • Contact us
    • Docs
    • Login
    1. Home
    2. ethalacker
    E
    • Profile
    • Following 0
    • Followers 0
    • Topics 2
    • Posts 4
    • Best 1
    • Controversial 0
    • Groups 0

    ethalacker

    @ethalacker

    1
    Reputation
    2
    Profile views
    4
    Posts
    0
    Followers
    0
    Following
    Joined Last Online

    ethalacker Unfollow Follow

    Best posts made by ethalacker

    • 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

      posted in Q&A
      E
      ethalacker

    Latest posts made by ethalacker

    • RE: Blazor WASM auth

      @robotdan Yes it is the same. We can continue the discussion here.

      posted in Q&A
      E
      ethalacker
    • 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.
      2f638e5e-2333-48a3-aa58-608817fab52c-image.png

      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.

      1. I am not getting a clean redirect to FusionAuth. Though, it does eventually redirect to the provider.
        9e06192e-854a-4903-a2b2-52aeb56411df-image.png
        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'.

      2. Once I login and get back from Fusion Auth, I get the following error:
        4f2eef4d-ef4e-4293-a893-8b8410d00a80-image.png
        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

      1. Use the new .NET 5 sdk.
      2. dotnet new blazorwasm -au Individual -o BlazorAuthSample5 in the CLI/powershell
      3. copy my Program.cs into yours. Only a few lines added/replaced.
      4. change wwwroot/appsettings.json to include your fusionAuth clientId
      5. dotnet run on folder and try to login
      posted in Q&A
      E
      ethalacker
    • 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

      posted in Q&A
      E
      ethalacker
    • 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:
      cbe0dc83-c8d1-49c0-a201-4b84cf19cb5e-image.png
      f109e5d6-5185-434b-9812-d6c5699a643d-image.png

      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?

      posted in Q&A
      E
      ethalacker