Beispiel #1
0
        public static CommandResult InitiateLogout(HttpRequestData request, Uri returnUrl, IOptions options, bool terminateLocalSession)
        {
            if (request == null)
            {
                throw new ArgumentNullException(nameof(request));
            }

            if (options == null)
            {
                throw new ArgumentNullException(nameof(options));
            }

            string idpEntityId       = null;
            Claim  sessionIndexClaim = null;

            if (request.User != null)
            {
                idpEntityId       = request.User.FindFirst(Saml2ClaimTypes.LogoutNameIdentifier)?.Issuer;
                sessionIndexClaim = request.User.FindFirst(Saml2ClaimTypes.SessionIndex);
            }

            IdentityProvider idp;
            var knownIdp = options.IdentityProviders.TryGetValue(new EntityId(idpEntityId), out idp);

            options.SPOptions.Logger.WriteVerbose("Initiating logout, checking requirements for federated logout"
                                                  + "\n  Issuer of LogoutNameIdentifier claim (should be Idp entity id): " + idpEntityId
                                                  + "\n  Issuer is a known Idp: " + knownIdp
                                                  + "\n  Session index claim (should have a value): " + sessionIndexClaim
                                                  + "\n  Idp has SingleLogoutServiceUrl: " + idp?.SingleLogoutServiceUrl?.OriginalString
                                                  + "\n  There is a signingCertificate in SPOptions: " + (options.SPOptions.SigningServiceCertificate != null)
                                                  + "\n  Idp configured to DisableOutboundLogoutRequests (should be false): " + idp?.DisableOutboundLogoutRequests);

            CommandResult commandResult;

            if (idpEntityId != null &&
                knownIdp &&
                sessionIndexClaim != null &&
                idp.SingleLogoutServiceUrl != null &&
                options.SPOptions.SigningServiceCertificate != null &&
                !idp.DisableOutboundLogoutRequests)
            {
                var logoutRequest = idp.CreateLogoutRequest(request.User);

                commandResult = Saml2Binding.Get(idp.SingleLogoutServiceBinding)
                                .Bind(logoutRequest);

                commandResult.RelayState   = logoutRequest.RelayState;
                commandResult.RequestState = new StoredRequestState(
                    idp.EntityId,
                    returnUrl,
                    logoutRequest.Id,
                    null);

                if (!options.SPOptions.Compatibility.DisableLogoutStateCookie)
                {
                    commandResult.SetCookieName = StoredRequestState.CookieNameBase + logoutRequest.RelayState;
                }

                commandResult.TerminateLocalSession = terminateLocalSession;

                options.SPOptions.Logger.WriteInformation("Sending logout request to " + idp.EntityId.Id);
            }
            else
            {
                commandResult = new CommandResult
                {
                    HttpStatusCode        = HttpStatusCode.SeeOther,
                    Location              = returnUrl,
                    TerminateLocalSession = terminateLocalSession
                };

                options.SPOptions.Logger.WriteInformation(
                    "Federated logout not possible, redirecting to post-logout"
                    + (terminateLocalSession ? " and clearing local session" : ""));
            }

            return(commandResult);
        }
        /// <summary>
        /// Run the command, initiating or handling the assertion consumer sequence.
        /// </summary>
        /// <param name="request">Request data.</param>
        /// <param name="options">Options</param>
        /// <returns>CommandResult</returns>
        public CommandResult Run(HttpRequestData request, IOptions options)
        {
            if (request == null)
            {
                throw new ArgumentNullException(nameof(request));
            }

            if (options == null)
            {
                throw new ArgumentNullException(nameof(options));
            }

            var binding = options.Notifications.GetBinding(request);

            if (binding != null)
            {
                UnbindResult unbindResult = null;
                try
                {
                    unbindResult = binding.Unbind(request, options);

                    options.Notifications.MessageUnbound(unbindResult);

                    var samlResponse = new Saml2Response(unbindResult.Data, request.StoredRequestState?.MessageId, options);

                    var idpContext = GetIdpContext(unbindResult.Data, request, options);

                    var result = ProcessResponse(options, samlResponse, request.StoredRequestState, idpContext, unbindResult.RelayState);

                    if (request.StoredRequestState != null)
                    {
                        result.ClearCookieName = StoredRequestState.CookieNameBase + unbindResult.RelayState;
                    }

                    options.Notifications.AcsCommandResultCreated(result, samlResponse);

                    return(result);
                }
                catch (FormatException ex)
                {
                    throw new BadFormatSamlResponseException(
                              "The SAML Response did not contain valid BASE64 encoded data.", ex);
                }
                catch (XmlException ex)
                {
                    var newEx = new BadFormatSamlResponseException(
                        "The SAML response contains incorrect XML", ex);

                    // Add the payload to the exception
                    if (unbindResult != null)
                    {
                        newEx.Data["Saml2Response"] = unbindResult.Data.OuterXml;
                    }
                    throw newEx;
                }
                catch (Exception ex)
                {
                    if (unbindResult != null)
                    {
                        // Add the payload to the existing exception
                        ex.Data["Saml2Response"] = unbindResult.Data.OuterXml;
                    }
                    throw;
                }
            }

            throw new NoSamlResponseFoundException();
        }
Beispiel #3
0
        private static CommandResult InitiateLoginToIdp(IOptions options, IDictionary <string, string> relayData, Saml2Urls urls, IdentityProvider idp, Uri returnUrl, HttpRequestData request)
        {
            var authnRequest = idp.CreateAuthenticateRequest(urls);

            var forceAuthnString = request.QueryString["ForceAuthn"].SingleOrDefault();

            if (!string.IsNullOrWhiteSpace(forceAuthnString))
            {
                authnRequest.ForceAuthentication = bool.Parse(forceAuthnString);
            }

            var isPassiveString = request.QueryString["IsPassive"].SingleOrDefault();

            if (!string.IsNullOrWhiteSpace(isPassiveString))
            {
                authnRequest.IsPassive = bool.Parse(isPassiveString);
            }

            options.Notifications.AuthenticationRequestCreated(authnRequest, idp, relayData);

            var commandResult = idp.Bind(authnRequest);

            commandResult.RequestState = new StoredRequestState(
                idp.EntityId, returnUrl, authnRequest.Id, relayData);

            commandResult.SetCookieSecureFlag = urls.AssertionConsumerServiceUrl.IsHttps();
            commandResult.SetCookieName       = StoredRequestState.CookieNameBase + authnRequest.RelayState;

            options.Notifications.SignInCommandResultCreated(commandResult, relayData);

            return(commandResult);
        }
Beispiel #4
0
 /// <summary>
 /// Get a cached binding instance that can handle the current request.
 /// </summary>
 /// <param name="request">Current HttpRequest</param>
 /// <returns>A derived class instance that supports the requested binding,
 /// or null if no binding supports the current request.</returns>
 public static Saml2Binding Get(HttpRequestData request)
 {
     return(bindings.FirstOrDefault(b => b.Value.CanUnbind(request)).Value);
 }
Beispiel #5
0
 /// <summary>
 /// Checks if the binding can extract a message out of the current
 /// http request.
 /// </summary>
 /// <param name="request">HttpRequest to check for message.</param>
 /// <returns>True if the binding supports the current request.</returns>
 protected internal abstract bool CanUnbind(HttpRequestData request);
Beispiel #6
0
 /// <summary>
 /// Extracts a message out of the current HttpRequest.
 /// </summary>
 /// <param name="request">Current HttpRequest.</param>
 /// <param name="options">Options, used to look up certificate information
 /// in bindings that validate signatures. If set to null, the returned
 /// result will have TrustLevel.None.</param>
 /// <returns>Extracted message.</returns>
 public virtual UnbindResult Unbind(HttpRequestData request, IOptions options)
 {
     throw new NotImplementedException();
 }