コード例 #1
0
 public DirectoryServicesConfigurationStore(
     ILog log,
     IKeyValueStore settings,
     IConfigurationStore configurationStore,
     IAuthenticationConfigurationStore authenticationConfigurationStore)
 {
     this.log                = log;
     this.settings           = settings;
     this.configurationStore = configurationStore;
     this.authenticationConfigurationStore = authenticationConfigurationStore;
 }
        public IntegratedAuthenticationModule(ILog log, IAuthCookieCreator tokenIssuer, IAuthenticationConfigurationStore authenticationConfigurationStore, IUrlEncoder encoder)
        {
            Add("GET", DirectoryServicesConstants.ChallengePath, context =>
            {
                if (context.User == null)
                {
                    context.Response.StatusCode = 401;
                    return(Task.FromResult(0));
                }

                var principal = (IOctopusPrincipal)context.User;

                // Decode the state object sent from the client (if there was one) so we can use those hints to build the most appropriate response
                // If the state can't be interpreted, we will fall back to a safe-by-default behaviour, however:
                //   1. Deep-links will not work because we don't know where the anonymous request originally wanted to go
                //   2. Cookies may not have the Secure flag set properly when SSL Offloading is in play
                LoginState state = null;
                if (context.Request.Query.TryGetValue("state", out var stateString))
                {
                    try
                    {
                        state = JsonConvert.DeserializeObject <LoginState>(stateString);
                    }
                    catch (Exception e)
                    {
                        log.Warn(e, "Invalid login state object passed to the server when setting up the NTLM challenge. Falling back to the default behaviour.");
                    }
                }

                // Build the auth cookies to send back with the response
                var authCookies = tokenIssuer.CreateAuthCookies(principal.IdentificationToken, SessionExpiry.TwentyDays, context.Request.IsHttps, state?.UsingSecureConnection);

                // If the caller has provided a redirect after successful login, we need to check it is a local address - preventing Open Redirection attacks
                if (!string.IsNullOrWhiteSpace(state?.RedirectAfterLoginTo))
                {
                    var whitelist = authenticationConfigurationStore.GetTrustedRedirectUrls();
                    if (Requests.IsLocalUrl(state.RedirectAfterLoginTo, whitelist))
                    {
                        // This is a safe redirect, let's go!
                        context.Response.Redirect(state.RedirectAfterLoginTo);
                        foreach (var cookie in authCookies)
                        {
                            context.Response.WithCookie(cookie);
                        }
                        return(Task.FromResult(0));
                    }

                    // Just log that we detected a non-local redirect URL, and fall through to the root of the local web site
                    log.WarnFormat(
                        "Prevented potential Open Redirection attack on an NTLM challenge, to the non-local url {0}",
                        state.RedirectAfterLoginTo);
                }

                // By default, redirect to the root of the local web site
                context.Response.Redirect(context.Request.PathBase ?? "/");
                foreach (var cookie in authCookies)
                {
                    context.Response.WithCookie(cookie);
                }

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