private static void ShowLoginUI(
            IOwinContext context,
            StuntmanOptions options)
        {
            context.Response.ContentType = "text/html";
            context.Response.StatusCode  = 200;

            var css       = Resources.GetCss();
            var usersHtml = GetUsersLoginUI(context, options);

            context.Response.Write($@"
<!DOCTYPE html>
<html>
    <head>
        <meta charset=""UTF-8"">
        <title>Select a user</title>
        <style>
            {css}
        </style>
    </head>
    <body>
        <div class=""stuntman-login-ui-container"">
            <h2><img src=""https://raw.githubusercontent.com/ritterim/stuntman/gh-pages/images/stuntman-logo.png"" alt=""Welcome to Stuntman"" /></h2>
            <h2>Please select a user to continue authentication.</h2>
            <ul>
                {usersHtml}
            </ul>
        </div>
    </body>
</html>");
        }
        /// <summary>
        /// Add Stuntman to this application.
        /// </summary>
        public static void AddStuntman(this IServiceCollection services, StuntmanOptions options)
        {
            services.AddAuthentication(Constants.StuntmanAuthenticationType);

            var authBuilder = new AuthenticationBuilder(services);

            if (options.AllowBearerTokenAuthentication)
            {
                authBuilder.AddJwtBearer(
                    opts =>
                {
                    opts.Events = new JwtBearerEvents
                    {
                        OnMessageReceived = context => StuntmanOnMessageReceived(options, context)
                    };
                });
            }

            if (options.AllowCookieAuthentication)
            {
                authBuilder.AddCookie(
                    Constants.StuntmanAuthenticationType,
                    opts =>
                {
                    opts.LoginPath          = new PathString(options.SignInUri);
                    opts.LogoutPath         = new PathString(options.SignOutUri);
                    opts.ReturnUrlParameter = Constants.StuntmanOptions.ReturnUrlQueryStringKey;
                });
            }
        }
        private static string GetUsersLoginUI(
            IOwinContext context,
            StuntmanOptions options)
        {
            var usersHtml = new StringBuilder();

            foreach (var user in options.Users)
            {
                var href = string.Format("{0}?OverrideUserId={1}&{2}={3}",
                                         options.SignInUri,
                                         user.Id,
                                         StuntmanOptions.ReturnUrlQueryStringKey,
                                         WebUtility.UrlEncode(context.Request.Query[StuntmanOptions.ReturnUrlQueryStringKey]));

                usersHtml.Append(string.Format(@"
<div class=""stuntman-g"">
    <div class=""stuntman-u-1"">
        <a href=""{0}"" class=""stuntman-button stuntman-u-1"">{1}</a>
    </div>
</div>
", href, user.Name));
            }

            return(usersHtml.ToString());
        }
        private static void ShowLoginUI(
            IOwinContext context,
            StuntmanOptions options)
        {
            context.Response.ContentType = "text/html";
            context.Response.StatusCode  = 200;

            var css       = Resources.GetCss();
            var usersHtml = GetUsersLoginUI(context, options);

            context.Response.Write(string.Format(@"
<html>
    <head>
        <style>
            {0}
        </style>
    </head>
    <body>
        <div class=""stuntman-g"">
            <div class=""stuntman-u-1-4"">&nbsp;</div>
            <div class=""stuntman-u-1-2"">
                <h2 class=""stuntman text-center"">Please select a user to continue authentication.</h2>
                <div class=""stuntman-g"">
                    <div class=""stuntman-u-1-6"">&nbsp;</div>
                    <div class=""stuntman-u-2-3"">
                        {1}
                    </div>
                </div>
            </div>
            <div class=""stuntman-u-1-4"">&nbsp;</div>
        </div>
    </body>
</html>
", css, usersHtml));
        }
示例#5
0
        private static async void ShowLoginUI(
            HttpContext context,
            StuntmanOptions options)
        {
            context.Response.ContentType = "text/html";
            context.Response.StatusCode  = 200;

            var css             = Resources.GetCss();
            var logoForInlining = Resources.GetLogoForInlining();
            var usersHtml       = GetUsersLoginUI(context, options);

            await context.Response.WriteAsync($@"
<!DOCTYPE html>
<html>
    <head>
        <meta charset=""UTF-8"">
        <title>Select a user</title>
        <style>
            {css}
        </style>
    </head>
    <body>
        <div class=""stuntman-login-ui-container"">
            <h2><img src=""{logoForInlining}"" alt=""Welcome to Stuntman"" /></h2>
            <h2>Please select a user to continue authentication.</h2>
            <ul>
                {usersHtml}
            </ul>
        </div>
    </body>
</html>");
        }
示例#6
0
        public void Configuration(IAppBuilder app)
        {
            var options = new StuntmanOptions()
                .AddUser(new StuntmanUser("user-1", "User 1")
                    .AddClaim("given_name", "John")
                    .AddClaim("family_name", "Doe"));

            if (System.Web.HttpContext.Current.IsDebuggingEnabled)
            {
                app.UseStuntman(options);
            }
        }
        private static string GetUsersLoginUI(
            IOwinContext context,
            StuntmanOptions options)
        {
            var usersHtml = new StringBuilder();

            foreach (var user in options.Users)
            {
                var href = $"{options.SignInUri}?OverrideUserId={user.Id}&{Constants.StuntmanOptions.ReturnUrlQueryStringKey}={WebUtility.UrlEncode(context.Request.Query[Constants.StuntmanOptions.ReturnUrlQueryStringKey])}";

                usersHtml.Append($@"<li><a href=""{href}"">{user.Name}</a></li>");
            }

            return(usersHtml.ToString());
        }
示例#8
0
        private static string GetUsersLoginUI(
            HttpContext context,
            StuntmanOptions options)
        {
            var usersHtml = new StringBuilder();

            foreach (var user in options.Users)
            {
                var href = $"{options.SignInUri}?OverrideUserId={user.Id}&{Constants.StuntmanOptions.ReturnUrlQueryStringKey}={WebUtility.UrlEncode(context.Request.Query[Constants.StuntmanOptions.ReturnUrlQueryStringKey])}";

                usersHtml.Append($@"<li><a href=""{href}"" title=""{(string.IsNullOrEmpty(user.Description) ? null : WebUtility.HtmlEncode(user.Description) + " ")}Source: {user.Source}"">{user.Name}</a></li>");
            }

            return(usersHtml.ToString());
        }
示例#9
0
        /// <summary>
        /// Enable Stuntman on this application.
        /// </summary>
        public static void UseStuntman(this IAppBuilder app, StuntmanOptions options)
        {
            if (options.AllowBearerTokenAuthentication)
            {
                app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions()
                {
                    AuthenticationType = Constants.StuntmanAuthenticationType,
                    Provider           = new StuntmanOAuthBearerProvider(options),
                    AccessTokenFormat  = new StuntmanOAuthAccessTokenFormat()
                });
            }

            if (options.AllowCookieAuthentication)
            {
                app.UseCookieAuthentication(new CookieAuthenticationOptions
                {
                    AuthenticationType = Constants.StuntmanAuthenticationType,
                    LoginPath          = new PathString(options.SignInUri),
                    LogoutPath         = new PathString(options.SignOutUri),
                    ReturnUrlParameter = Constants.StuntmanOptions.ReturnUrlQueryStringKey,
                });

                app.Map(options.SignInUri, signin =>
                {
                    signin.Use(async(context, next) =>
                    {
                        var claims = new List <Claim>();

                        var overrideUserId = context.Request.Query[Constants.StuntmanOptions.OverrideQueryStringKey];

                        if (string.IsNullOrWhiteSpace(overrideUserId))
                        {
                            await next.Invoke();

                            IAppBuilderShared.ShowLoginUI(context, options);
                        }
                        else
                        {
                            var user = options.Users
                                       .Where(x => x.Id == overrideUserId)
                                       .FirstOrDefault();

                            if (user == null)
                            {
                                context.Response.StatusCode = 404;
                                await context.Response.WriteAsync(
                                    $"options provided does not include the requested '{overrideUserId}' user.");

                                return;
                            }

                            claims.Add(new Claim(user.NameClaimType, user.Name));
                            claims.AddRange(user.Claims);

                            var identity = new ClaimsIdentity(claims, Constants.StuntmanAuthenticationType, user.NameClaimType, user.RoleClaimType);

                            var authManager = context.Authentication;

                            authManager.SignIn(identity);

                            await next.Invoke();
                        }
                    });

                    IAppBuilderShared.RedirectToReturnUrl(signin);
                });

                app.Map(options.SignOutUri, signout =>
                {
                    signout.Use((context, next) =>
                    {
                        var authManager = context.Authentication;
                        authManager.SignOut(Constants.StuntmanAuthenticationType);

                        return(next.Invoke());
                    });

                    IAppBuilderShared.RedirectToReturnUrl(signout);
                });
            }

            if (options.ServerEnabled)
            {
                app.Map(options.ServerUri, server =>
                {
                    server.Use(async(context, next) =>
                    {
                        var response = new StuntmanServerResponse {
                            Users = options.Users
                        };
                        var json = JsonConvert.SerializeObject(response);

                        context.Response.ContentType = "application/json";
                        await context.Response.WriteAsync(json);
                    });
                });
            }
        }
示例#10
0
 public StuntmanOAuthBearerProvider(StuntmanOptions options)
 {
     this.options = options;
 }
示例#11
0
 public UserPicker(StuntmanOptions options)
 {
     _options = options;
 }
        private static async Task StuntmanOnMessageReceived(
            StuntmanOptions options,
            MessageReceivedContext context)
        {
            var authorizationBearerToken = context.HttpContext.Request.Headers["Authorization"];

            if (string.IsNullOrWhiteSpace(authorizationBearerToken))
            {
                // TODO: Skip to next middleware?
                return;
            }
            else
            {
                var authorizationBearerTokenParts = authorizationBearerToken.ToString().Split(' ');

                var accessToken = authorizationBearerTokenParts
                                  .LastOrDefault();

                var          claims = new List <Claim>();
                StuntmanUser user   = null;

                if (authorizationBearerTokenParts.Count() != 2 ||
                    string.IsNullOrWhiteSpace(accessToken))
                {
                    context.HttpContext.Response.StatusCode = 400;
                    await context.HttpContext.Response.WriteAsync(
                        "Authorization header is not in correct format.");

                    context.Fail(
                        "Authorization header is not in correct format.");
                    return;
                }
                else
                {
                    user = options.Users
                           .Where(x => x.AccessToken == accessToken)
                           .FirstOrDefault();

                    if (user == null)
                    {
                        if (!options.AllowBearerTokenPassthrough)
                        {
                            context.Response.StatusCode = 403;
                            await context.HttpContext.Response.WriteAsync(
                                $"options provided does not include the requested '{accessToken}' user.");
                        }

                        context.Fail(
                            $"options provided does not include the requested '{accessToken}' user.");
                        return;
                    }
                    else
                    {
                        claims.Add(new Claim("access_token", accessToken));
                    }
                }

                claims.Add(new Claim(user.NameClaimType, user.Name));
                claims.AddRange(user.Claims);

                context.Principal = new ClaimsPrincipal(new ClaimsIdentity(claims, Constants.StuntmanAuthenticationType, user.NameClaimType, user.RoleClaimType));
                context.Success();

                options.AfterBearerValidateIdentity?.Invoke(context);
            }
        }
示例#13
0
 public UserPicker(StuntmanOptions options)
 {
     _options = options;
 }
        public static void UseStuntman(this IAppBuilder app, StuntmanOptions options)
        {
            app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions()
            {
                AuthenticationType = StuntmanAuthenticationType,
                Provider           = new StuntmanOAuthBearerProvider(options),
                AccessTokenFormat  = new StuntmanOAuthAccessTokenFormat()
            });

            app.UseCookieAuthentication(new CookieAuthenticationOptions
            {
                AuthenticationType = StuntmanAuthenticationType,
                LoginPath          = new PathString(options.SignInUri),
                LogoutPath         = new PathString(options.SignOutUri),
                ReturnUrlParameter = StuntmanOptions.ReturnUrlQueryStringKey,
            });

            app.Map(options.SignInUri, signin =>
            {
                signin.Use(async(context, next) =>
                {
                    var claims = new List <Claim>();

                    var overrideUserId = context.Request.Query[StuntmanOptions.OverrideQueryStringKey];

                    if (string.IsNullOrWhiteSpace(overrideUserId))
                    {
                        await next.Invoke();

                        ShowLoginUI(context, options);
                    }
                    else
                    {
                        var user = options.Users
                                   .Where(x => x.Id == overrideUserId)
                                   .FirstOrDefault();

                        if (user == null)
                        {
                            context.Response.StatusCode = 404;
                            await context.Response.WriteAsync(string.Format(
                                                                  "options provided does not include the requested '{0}' user.",
                                                                  overrideUserId));

                            return;
                        }

                        claims.Add(new Claim(ClaimTypes.Name, user.Name));
                        claims.AddRange(user.Claims);

                        var identity = new ClaimsIdentity(claims, StuntmanAuthenticationType);

                        var authManager = context.Authentication;

                        authManager.SignIn(identity);

                        await next.Invoke();
                    }
                });

                RedirectToReturnUrl(signin);
            });

            app.Map(options.SignOutUri, signout =>
            {
                signout.Use((context, next) =>
                {
                    var authManager = context.Authentication;
                    authManager.SignOut(StuntmanAuthenticationType);

                    return(next.Invoke());
                });

                RedirectToReturnUrl(signout);
            });
        }
示例#15
0
        public void Configuration(IAppBuilder app)
        {
            var options = new StuntmanOptions()
                .AddUser(new StuntmanUser("user-1", "User 1")
                    .SetAccessToken("user-1-token")
                    .AddClaim("given_name", "John")
                    .AddClaim("family_name", "Doe"))
                .AddUser(new StuntmanUser("user-2", "User 2")
                    .AddClaim("given_name", "Jane")
                    .AddClaim("family_name", "Doe"))
                .AddUser(new StuntmanUser("user-3", "User 3")
                    .AddClaim("given_name", "Sam")
                    .AddClaim("family_name", "Smith"));

            if (System.Web.HttpContext.Current.IsDebuggingEnabled)
            {
                app.UseStuntman(options);
            }

            var userPicker = new UserPicker(options);

            app.Map("/secure", secure =>
            {
                AuthenticateAllRequests(secure, new[] { "StuntmanAuthentication" });

                secure.Run(context =>
                {
                    var userName = context.Request.User.Identity.Name;

                    if (string.IsNullOrEmpty(userName))
                        userName = "******";

                    context.Response.ContentType = "text/html";
                    context.Response.WriteAsync(string.Format(
                        "Hello, {0}. This is the /secure endpoint.",
                        userName));

                    if (System.Web.HttpContext.Current.IsDebuggingEnabled)
                    {
                        context.Response.WriteAsync(
                            userPicker.GetHtml(context.Request.User, context.Request.Uri.AbsoluteUri));
                    }

                    return Task.FromResult(true);
                });
            });

            app.Map("/logout", logout =>
            {
                logout.Run(context =>
                {
                    context.Authentication.SignOut();
                    return Task.FromResult(true);
                });
            });

            app.Map("", nonSecure =>
            {
                nonSecure.Run(context =>
                {
                    var userName = context.Request.User.Identity.Name;

                    if (string.IsNullOrEmpty(userName))
                        userName = "******";

                    context.Response.ContentType = "text/html";
                    context.Response.WriteAsync(string.Format(
                        "Hello, {0}.",
                        userName));

                    if (System.Web.HttpContext.Current.IsDebuggingEnabled)
                    {
                        context.Response.WriteAsync(
                            userPicker.GetHtml(context.Request.User, context.Request.Uri.AbsoluteUri));
                    }

                    return Task.FromResult(true);
                });
            });
        }