Пример #1
0
        private async Task <IActionResult> LogoutResponseAsync <T>(Saml2Configuration samlConfig, string inResponseTo, string relayState, string singleLogoutResponseUrl, Saml2Binding <T> binding, Saml2StatusCodes status, string sessionIndex)
        {
            binding.RelayState = relayState;

            var saml2LogoutResponse = new Saml2LogoutResponse(samlConfig)
            {
                InResponseTo = new Saml2Id(inResponseTo),
                Status       = status,
                Destination  = new Uri(singleLogoutResponseUrl),
                SessionIndex = sessionIndex
            };

            binding.Bind(saml2LogoutResponse);
            logger.ScopeTrace(() => $"SAML Single Logout response '{saml2LogoutResponse.XmlDocument.OuterXml}'.", traceType: TraceTypes.Message);
            logger.ScopeTrace(() => $"Single logged out response URL '{singleLogoutResponseUrl}'.");
            logger.ScopeTrace(() => "Down, SAML Single Logout response.", triggerEvent: true);

            await sequenceLogic.RemoveSequenceDataAsync <SamlDownSequenceData>();

            securityHeaderLogic.AddFormActionAllowAll();

            if (binding is Saml2Binding <Saml2RedirectBinding> )
            {
                return(await(binding as Saml2RedirectBinding).ToActionFormResultAsync());
            }
            if (binding is Saml2Binding <Saml2PostBinding> )
            {
                return(await(binding as Saml2PostBinding).ToActionFormResultAsync());
            }
            else
            {
                throw new NotSupportedException();
            }
        }
Пример #2
0
        private async Task <IActionResult> LogoutResponseAsync <T>(Saml2Configuration samlConfig, string inResponseTo, string relayState, string loggedOutUrl, Saml2Binding <T> binding, Saml2StatusCodes status, string sessionIndex = null)
        {
            binding.RelayState = relayState;

            var saml2LogoutResponse = new Saml2LogoutResponse(samlConfig)
            {
                InResponseTo = new Saml2Id(inResponseTo),
                Status       = status,
                Destination  = new Uri(loggedOutUrl),
                SessionIndex = sessionIndex
            };

            binding.Bind(saml2LogoutResponse);
            logger.ScopeTrace($"SAML Logout response '{saml2LogoutResponse.XmlDocument.OuterXml}'.");
            logger.ScopeTrace($"Logged out url '{loggedOutUrl}'.");
            logger.ScopeTrace("Down, SAML Logout response.", triggerEvent: true);

            await sequenceLogic.RemoveSequenceDataAsync <SamlDownSequenceData>();

            await formActionLogic.RemoveFormActionSequenceDataAsync();

            if (binding is Saml2Binding <Saml2RedirectBinding> )
            {
                return(await Task.FromResult((binding as Saml2RedirectBinding).ToActionResult()));
            }
            if (binding is Saml2Binding <Saml2PostBinding> )
            {
                return(await Task.FromResult((binding as Saml2PostBinding).ToActionResult()));
            }
            else
            {
                throw new NotSupportedException();
            }
        }
Пример #3
0
        private async Task <IActionResult> SingleLogoutRequestAsync <T>(SamlDownParty party, Saml2Binding <T> binding, IEnumerable <Claim> claims)
        {
            var samlConfig = saml2ConfigurationLogic.GetSamlDownConfig(party, true);

            claims = await claimTransformationsLogic.Transform(party.ClaimTransforms?.ConvertAll(t => (ClaimTransform)t), claims);

            var saml2LogoutRequest = new Saml2LogoutRequest(samlConfig)
            {
                NameId       = samlClaimsDownLogic.GetNameId(claims),
                Destination  = new Uri(party.SingleLogoutUrl),
                SessionIndex = samlClaimsDownLogic.GetSessionIndex(claims)
            };

            binding.RelayState = SequenceString;
            binding.Bind(saml2LogoutRequest);
            logger.ScopeTrace($"SAML Single Logout request '{saml2LogoutRequest.XmlDocument.OuterXml}'.");
            logger.ScopeTrace($"Single logged out URL '{party.SingleLogoutUrl}'.");
            logger.ScopeTrace("Down, SAML Single Logout request.", triggerEvent: true);

            securityHeaderLogic.AddFormAction(party.SingleLogoutUrl);
            if (binding is Saml2Binding <Saml2RedirectBinding> )
            {
                return(await(binding as Saml2RedirectBinding).ToActionFormResultAsync());
            }
            if (binding is Saml2Binding <Saml2PostBinding> )
            {
                return(await(binding as Saml2PostBinding).ToActionFormResultAsync());
            }
            else
            {
                throw new NotSupportedException();
            }
        }
Пример #4
0
        private async Task <IActionResult> AuthnResponseAsync <T>(Saml2Configuration samlConfig, string inResponseTo, string relayState, string acsUrl, Saml2Binding <T> binding, Saml2StatusCodes status, SamlDownParty party = null, IEnumerable <Claim> claims = null)
        {
            binding.RelayState = relayState;

            var saml2AuthnResponse = new FoxIdsSaml2AuthnResponse(settings, samlConfig)
            {
                InResponseTo = new Saml2Id(inResponseTo),
                Status       = status,
                Destination  = new Uri(acsUrl),
            };

            if (status == Saml2StatusCodes.Success && party != null && claims != null)
            {
                claims = await claimTransformationsLogic.Transform(party.ClaimTransformations?.ConvertAll(t => (ClaimTransformation)t), claims);

                saml2AuthnResponse.SessionIndex = claims.FindFirstValue(c => c.Type == Saml2ClaimTypes.SessionIndex);

                saml2AuthnResponse.NameId = GetNameId(claims);

                var tokenIssueTime  = DateTimeOffset.UtcNow;
                var tokenDescriptor = saml2AuthnResponse.CreateTokenDescriptor(GetSubjectClaims(party, claims), party.Issuer, tokenIssueTime, party.IssuedTokenLifetime);

                var authnContext            = claims.FindFirstValue(c => c.Type == ClaimTypes.AuthenticationMethod);
                var authenticationInstant   = claims.FindFirstValue(c => c.Type == ClaimTypes.AuthenticationInstant);
                var authenticationStatement = saml2AuthnResponse.CreateAuthenticationStatement(authnContext, DateTime.Parse(authenticationInstant));

                var subjectConfirmation = saml2AuthnResponse.CreateSubjectConfirmation(tokenIssueTime, party.SubjectConfirmationLifetime);

                await saml2AuthnResponse.CreateSecurityTokenAsync(tokenDescriptor, authenticationStatement, subjectConfirmation);
            }

            binding.Bind(saml2AuthnResponse);
            logger.ScopeTrace($"SAML Authn response '{saml2AuthnResponse.XmlDocument.OuterXml}'.");
            logger.ScopeTrace($"Acs url '{acsUrl}'.");
            logger.ScopeTrace("Down, SAML Authn response.", triggerEvent: true);

            await sequenceLogic.RemoveSequenceDataAsync <SamlDownSequenceData>();

            await formActionLogic.RemoveFormActionSequenceDataAsync();

            if (binding is Saml2Binding <Saml2RedirectBinding> )
            {
                return(await Task.FromResult((binding as Saml2RedirectBinding).ToActionResult()));
            }
            else if (binding is Saml2Binding <Saml2PostBinding> )
            {
                return(await Task.FromResult((binding as Saml2PostBinding).ToActionResult()));
            }
            else
            {
                throw new NotSupportedException();
            }
        }
Пример #5
0
        private async Task <IActionResult> AuthnRequestAsync <T>(SamlUpParty party, Saml2Binding <T> binding, SamlUpSequenceData samlUpSequenceData)
        {
            var samlConfig = await saml2ConfigurationLogic.GetSamlUpConfigAsync(party, includeSigningAndDecryptionCertificate : true);

            binding.RelayState = await sequenceLogic.CreateExternalSequenceIdAsync();

            var saml2AuthnRequest = new Saml2AuthnRequest(samlConfig);

            switch (samlUpSequenceData.LoginAction)
            {
            case LoginAction.ReadSession:
                saml2AuthnRequest.IsPassive = true;
                break;

            case LoginAction.RequireLogin:
                saml2AuthnRequest.ForceAuthn = true;
                break;

            default:
                break;
            }

            if (party.AuthnContextClassReferences?.Count() > 0)
            {
                saml2AuthnRequest.RequestedAuthnContext = new RequestedAuthnContext
                {
                    Comparison           = party.AuthnContextComparison.HasValue ? (AuthnContextComparisonTypes)Enum.Parse(typeof(AuthnContextComparisonTypes), party.AuthnContextComparison.Value.ToString()) : null,
                    AuthnContextClassRef = party.AuthnContextClassReferences,
                };
            }

            binding.Bind(saml2AuthnRequest);
            logger.ScopeTrace(() => $"SAML Authn request '{saml2AuthnRequest.XmlDocument.OuterXml}'.", traceType: TraceTypes.Message);
            logger.ScopeTrace(() => $"Authn URL '{samlConfig.SingleSignOnDestination?.OriginalString}'.");
            logger.ScopeTrace(() => "Up, Sending SAML Authn request.", triggerEvent: true);

            securityHeaderLogic.AddFormActionAllowAll();

            if (binding is Saml2Binding <Saml2RedirectBinding> )
            {
                return(await(binding as Saml2RedirectBinding).ToActionFormResultAsync());
            }
            else if (binding is Saml2Binding <Saml2PostBinding> )
            {
                return(await(binding as Saml2PostBinding).ToActionFormResultAsync());
            }
            else
            {
                throw new NotSupportedException();
            }
        }
Пример #6
0
        private async Task <IActionResult> LogoutAsync <T>(SamlUpParty party, Saml2Binding <T> binding, LogoutRequest logoutRequest)
        {
            var samlConfig = saml2ConfigurationLogic.GetSamlUpConfig(party, includeSigningCertificate: true);
            await formActionLogic.AddFormActionByUrlAsync(samlConfig.SingleLogoutDestination.OriginalString);

            binding.RelayState = SequenceString;

            var saml2LogoutRequest = new Saml2LogoutRequest(samlConfig);

            saml2LogoutRequest.SessionIndex = logoutRequest.SessionId;

            var nameID       = logoutRequest.Claims?.Where(c => c.Type == Saml2ClaimTypes.NameId).Select(c => c.Value).FirstOrDefault();
            var nameIdFormat = logoutRequest.Claims?.Where(c => c.Type == Saml2ClaimTypes.NameIdFormat).Select(c => c.Value).FirstOrDefault();

            if (!nameID.IsNullOrEmpty())
            {
                if (nameIdFormat.IsNullOrEmpty())
                {
                    saml2LogoutRequest.NameId = new Saml2NameIdentifier(nameID);
                }
                else
                {
                    saml2LogoutRequest.NameId = new Saml2NameIdentifier(nameID, new Uri(nameIdFormat));
                }
            }

            binding.Bind(saml2LogoutRequest);
            logger.ScopeTrace($"SAML Logout request '{saml2LogoutRequest.XmlDocument.OuterXml}'.");
            logger.ScopeTrace($"Logout url '{samlConfig.SingleLogoutDestination?.OriginalString}'.");
            logger.ScopeTrace("Up, SAML Logout request.", triggerEvent: true);

            if (binding is Saml2Binding <Saml2RedirectBinding> )
            {
                return(await Task.FromResult((binding as Saml2RedirectBinding).ToActionResult()));
            }
            if (binding is Saml2Binding <Saml2PostBinding> )
            {
                return(await Task.FromResult((binding as Saml2PostBinding).ToActionResult()));
            }
            else
            {
                throw new NotSupportedException();
            }
        }
Пример #7
0
        private async Task <IActionResult> AuthnRequestAsync <T>(SamlUpParty party, Saml2Binding <T> binding, SamlUpSequenceData samlUpSequenceData)
        {
            var samlConfig = saml2ConfigurationLogic.GetSamlUpConfig(party);

            binding.RelayState = SequenceString;
            var saml2AuthnRequest = new Saml2AuthnRequest(samlConfig);

            switch (samlUpSequenceData.LoginAction)
            {
            case LoginAction.ReadSession:
                saml2AuthnRequest.IsPassive = true;
                break;

            case LoginAction.RequireLogin:
                saml2AuthnRequest.ForceAuthn = true;
                break;

            default:
                break;
            }

            binding.Bind(saml2AuthnRequest);
            logger.ScopeTrace($"SAML Authn request '{saml2AuthnRequest.XmlDocument.OuterXml}'.");
            logger.ScopeTrace($"Authn URL '{samlConfig.SingleSignOnDestination?.OriginalString}'.");
            logger.ScopeTrace("Up, Sending SAML Authn request.", triggerEvent: true);

            securityHeaderLogic.AddFormActionAllowAll();

            if (binding is Saml2Binding <Saml2RedirectBinding> )
            {
                return(await(binding as Saml2RedirectBinding).ToActionFormResultAsync());
            }
            else if (binding is Saml2Binding <Saml2PostBinding> )
            {
                return(await(binding as Saml2PostBinding).ToActionFormResultAsync());
            }
            else
            {
                throw new NotSupportedException();
            }
        }
Пример #8
0
        private async Task <IActionResult> LogoutRequestAsync <T>(SamlUpParty party, Saml2Binding <T> binding, SamlUpSequenceData samlUpSequenceData)
        {
            var samlConfig = await saml2ConfigurationLogic.GetSamlUpConfigAsync(party, includeSigningAndDecryptionCertificate : true);

            binding.RelayState = await sequenceLogic.CreateExternalSequenceIdAsync();

            var saml2LogoutRequest = new Saml2LogoutRequest(samlConfig);

            var session = await sessionUpPartyLogic.GetSessionAsync(party);

            if (session == null)
            {
                return(await LogoutResponseDownAsync(samlUpSequenceData));
            }

            try
            {
                if (!samlUpSequenceData.SessionId.Equals(session.SessionId, StringComparison.Ordinal))
                {
                    throw new Exception("Requested session ID do not match up-party session ID.");
                }
            }
            catch (Exception ex)
            {
                logger.Warning(ex);
            }

            saml2LogoutRequest.SessionIndex = session.ExternalSessionId;

            samlUpSequenceData.SessionDownPartyLinks = session.DownPartyLinks;
            samlUpSequenceData.SessionClaims         = session.Claims;
            await sequenceLogic.SaveSequenceDataAsync(samlUpSequenceData);

            var jwtClaims    = samlUpSequenceData.SessionClaims.ToClaimList();
            var nameID       = jwtClaims?.Where(c => c.Type == JwtClaimTypes.Subject).Select(c => c.Value).FirstOrDefault();
            var nameIdFormat = jwtClaims?.Where(c => c.Type == Constants.JwtClaimTypes.SubFormat).Select(c => c.Value).FirstOrDefault();

            if (!nameID.IsNullOrEmpty())
            {
                var prePartyName = $"{party.Name}|";
                if (nameID.StartsWith(prePartyName, StringComparison.Ordinal))
                {
                    nameID = nameID.Remove(0, prePartyName.Length);
                }
                if (nameIdFormat.IsNullOrEmpty())
                {
                    saml2LogoutRequest.NameId = new Saml2NameIdentifier(nameID);
                }
                else
                {
                    saml2LogoutRequest.NameId = new Saml2NameIdentifier(nameID, new Uri(nameIdFormat));
                }
            }

            binding.Bind(saml2LogoutRequest);
            logger.ScopeTrace(() => $"SAML Logout request '{saml2LogoutRequest.XmlDocument.OuterXml}'.", traceType: TraceTypes.Message);
            logger.ScopeTrace(() => $"Logout URL '{samlConfig.SingleLogoutDestination?.OriginalString}'.");
            logger.ScopeTrace(() => "Up, SAML Logout request.", triggerEvent: true);

            _ = await sessionUpPartyLogic.DeleteSessionAsync(party, session);

            await oauthRefreshTokenGrantLogic.DeleteRefreshTokenGrantsAsync(samlUpSequenceData.SessionId);

            securityHeaderLogic.AddFormActionAllowAll();

            if (binding is Saml2Binding <Saml2RedirectBinding> )
            {
                return(await(binding as Saml2RedirectBinding).ToActionFormResultAsync());
            }
            else if (binding is Saml2Binding <Saml2PostBinding> )
            {
                return(await(binding as Saml2PostBinding).ToActionFormResultAsync());
            }
            else
            {
                throw new NotSupportedException();
            }
        }