Closed n4ppy closed 6 years ago
This is a matter of ordering the authentication. Stuntman also has a pass through mode. I think @billbogaiv can help you :)
In something like Startup.cs
, just make sure the UseStuntman
middleware is after the primary identity middleware:
// Use primary authentication system first...
app.UseIdentityServer(...);
// Then, Stuntman...
app.UseStuntman(...);
If you are using ASP.NET, in your controller-action, the direction you take is up to your individual needs:
// Get Stuntman identity...
var stuntmanIdentity = (User as ClaimsPrincipal).Identities.Where(x => x.AuthenticationType == RimDev.Stuntman.Core.Constants.StuntmanAuthenticationType);
Assuming your entire app. requires authentication, this flow should work fine. If you have a landing-page that allows anonymous users, then it will take a bit more work (since you don't want to show the Stuntman user-picker prior to using the primary authentication service):
@if (User.IsAuthenticated)
{
@Html.Raw(YourApplicationNamespace.Startup.StuntmanOptions.UserPicker(User));
}
Basically monkey see monkey do for me :)
If i put Stuntman at the top, stuntman does not work, if i put stuntman last i go to stuntman/sign-in not /Account/Login where i would like to go first. Probably a noob setting somewhere :)
Thanks Franc
{
// Configure the db context, user manager and signin manager to use a single instance per request
app.CreatePerOwinContext(ApplicationDbContext.Create);
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);
// Enable the application to use a cookie to store information for the signed in user
// and to use a cookie to temporarily store information about a user logging in with a third party login provider
// Configure the sign in cookie
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/Account/Login"),
Provider = new CookieAuthenticationProvider
{
// Enables the application to validate the security stamp when the user logs in.
// This is a security feature which is used when you change a password or add an external login to your account.
OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
validateInterval: TimeSpan.FromMinutes(30),
regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
},
CookieDomain = Settings.Default.CookieDomain,
});
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
// Enables the application to temporarily store user information when they are verifying the second factor in the two-factor authentication process.
app.UseTwoFactorSignInCookie(DefaultAuthenticationTypes.TwoFactorCookie, TimeSpan.FromMinutes(5));
// Enables the application to remember the second login verification factor such as phone or email.
// Once you check this option, your second step of verification during the login process will be remembered on the device where you logged in from.
// This is similar to the RememberMe option when you log in.
app.UseTwoFactorRememberBrowserCookie(DefaultAuthenticationTypes.TwoFactorRememberBrowserCookie);
// https://github.com/ritterim/stuntman
if (!string.IsNullOrWhiteSpace(Settings.Default.StuntManEnabledFor))
{
StuntmanOptions.SetUserPickerAlignment(StuntmanAlignment.Right);
StuntmanOptions.AddUsers(StuntmanHelper.StuntManUsers(Settings.Default.StuntManEnabledFor));
StuntmanOptions.AllowBearerTokenPassthrough = true;
if (System.Web.HttpContext.Current.IsDebuggingEnabled)
{
app.UseStuntman(StuntmanOptions);
}
}
Alternatively, you could also try in ASP.NET Core:
app.UseWhen(context =>
context.Request.User.Identity.IsAuthenticated, appBuilder =>
{
appBuiler.UseStuntman(...);
});
If using classic ASP.NET, you'll need this extension:
using Microsoft.Owin.Builder;
using Owin;
using System;
using Predicate = System.Func<Microsoft.Owin.IOwinContext, bool>;
namespace Extensions
{
public static class IAppBuilderExtensions
{
/// <summary>
/// Conditionally creates a branch in the request pipeline that is rejoined to the main pipeline.
/// Modified from https://github.com/aspnet/HttpAbstractions/blob/01f247db4854fd066fb8567a599a4bb591cb392b/src/Microsoft.AspNetCore.Http.Abstractions/Extensions/UseWhenExtensions.cs.
/// </summary>
/// <param name="predicate">Invoked with the request environment to determine if the branch should be taken</param>
/// <param name="configuration">Configures a branch to take</param>
/// <returns></returns>
public static IAppBuilder UseWhen(this IAppBuilder app, Predicate predicate, Action<IAppBuilder> configuration)
{
app = app ?? throw new ArgumentNullException(nameof(app));
predicate = predicate ?? throw new ArgumentNullException(nameof(predicate));
configuration = configuration ?? throw new ArgumentNullException(nameof(configuration));
return app.Use((context, next) =>
{
// Not sure why this next section has to be within the `Use` block. Original was outside. Otherwise, MiniProfiler usage throws Exception.
var builder = app.New();
configuration(builder);
builder.Run(_ => next());
var branch = builder.Build();
if (predicate(context))
{
return branch(context.Environment);
}
else
{
return next();
}
});
}
}
}
What this should do is only execute Stuntman middleware if the User
is already authenticated with your primary authentication middleware. I have never tried this exact setup before, but seems like it would work.
Some small tweaks
if (app == null) { throw new ArgumentNullException(nameof(app)); }
if (predicate == null) { throw new ArgumentNullException(nameof(predicate)); }
if (configuration == null) { throw new ArgumentNullException(nameof(configuration)); }
and
app.UseWhen(context => context.Request.User.Identity.IsAuthenticated, appBuilder => { appBuilder.UseStuntman(StuntmanOptions); });
Seems to work but need to do some more testing (will be early next week as it's end of day for me)
Thanks so far!
if (!string.IsNullOrWhiteSpace(Settings.Default.StuntManEnabledFor))
{
StuntmanOptions.SetUserPickerAlignment(StuntmanAlignment.Right);
StuntmanOptions.AddUsers(StuntmanHelper.StuntManUsers(Settings.Default.StuntManEnabledFor));
if (System.Web.HttpContext.Current.IsDebuggingEnabled)
{
app.UseWhen(context => context.Request.User.Identity.IsAuthenticated, appBuilder => { appBuilder.UseStuntman(StuntmanOptions); });
}
}
have tested it in the demo environment and this does the trick when authenticated the stuntman option is available otherwise it's not.
(StuntmanHelper.StuntManUsers is a method to return a specific list of users)
So thanks, works great and made life easier for testing and doing a demo with some screens having 3 different roles looking at it and getting different buttons depending on role
Hi,
I have stuntman installed and works great for dev but i would also like to use it in our demo/test environment on the web (open for basically anyone).
Issue now is that anyone can just pick a user and get in but i would like the original owin authentication to pop up first and after that be able to use stuntman to quickly demo/test.
Thanks
Franc