public async Task <IActionResult> EndSessionResponseAsync(string partyId)
        {
            logger.ScopeTrace($"Up, OIDC End session response.");
            logger.SetScopeProperty("upPartyId", partyId);

            var party = await tenantRepository.GetAsync <OidcUpParty>(partyId);

            logger.SetScopeProperty("upPartyClientId", party.Client.ClientId);

            var queryDictionary           = HttpContext.Request.Query.ToDictionary();
            var rpInitiatedLogoutResponse = queryDictionary.ToObject <RpInitiatedLogoutResponse>();

            logger.ScopeTrace($"Up, End session response '{rpInitiatedLogoutResponse.ToJsonIndented()}'.");
            rpInitiatedLogoutResponse.Validate();
            if (rpInitiatedLogoutResponse.State.IsNullOrEmpty())
            {
                throw new ArgumentNullException(nameof(rpInitiatedLogoutResponse.State), rpInitiatedLogoutResponse.GetTypeName());
            }

            await sequenceLogic.ValidateSequenceAsync(rpInitiatedLogoutResponse.State);

            var sequenceData = await sequenceLogic.GetSequenceDataAsync <OidcUpSequenceData>(remove : party.DisableSingleLogout);

            logger.ScopeTrace("Up, Successful OIDC End session response.", triggerEvent: true);

            if (party.DisableSingleLogout)
            {
                return(await LogoutResponseDownAsync(sequenceData));
            }
            else
            {
                (var doSingleLogout, var singleLogoutSequenceData) = await singleLogoutDownLogic.InitializeSingleLogoutAsync(new UpPartyLink { Name = party.Name, Type = party.Type }, sequenceData.DownPartyLink, sequenceData.SessionDownPartyLinks, sequenceData.SessionClaims);

                if (doSingleLogout)
                {
                    return(await singleLogoutDownLogic.StartSingleLogoutAsync(singleLogoutSequenceData));
                }
                else
                {
                    await sequenceLogic.RemoveSequenceDataAsync <OidcUpSequenceData>();

                    return(await LogoutResponseDownAsync(sequenceData));
                }
            }
        }
        private async Task <IActionResult> EndSessionResponseAsync(OidcUpParty party)
        {
            var queryDictionary           = HttpContext.Request.Query.ToDictionary();
            var rpInitiatedLogoutResponse = queryDictionary.ToObject <RpInitiatedLogoutResponse>();

            logger.ScopeTrace(() => $"Up, End session response '{rpInitiatedLogoutResponse.ToJsonIndented()}'.", traceType: TraceTypes.Message);
            rpInitiatedLogoutResponse.Validate();
            if (rpInitiatedLogoutResponse.State.IsNullOrEmpty())
            {
                throw new ArgumentNullException(nameof(rpInitiatedLogoutResponse.State), rpInitiatedLogoutResponse.GetTypeName());
            }

            await sequenceLogic.ValidateExternalSequenceIdAsync(rpInitiatedLogoutResponse.State);

            var sequenceData = await sequenceLogic.GetSequenceDataAsync <OidcUpSequenceData>(remove : party.DisableSingleLogout);

            logger.ScopeTrace(() => "Up, Successful OIDC End session response.", triggerEvent: true);

            if (party.DisableSingleLogout)
            {
                return(await LogoutResponseDownAsync(sequenceData));
            }
            else
            {
                (var doSingleLogout, var singleLogoutSequenceData) = await singleLogoutDownLogic.InitializeSingleLogoutAsync(new UpPartyLink { Name = party.Name, Type = party.Type }, sequenceData.DownPartyLink, sequenceData.SessionDownPartyLinks, sequenceData.SessionClaims);

                if (doSingleLogout)
                {
                    return(await singleLogoutDownLogic.StartSingleLogoutAsync(singleLogoutSequenceData));
                }
                else
                {
                    await sequenceLogic.RemoveSequenceDataAsync <OidcUpSequenceData>();

                    return(await LogoutResponseDownAsync(sequenceData));
                }
            }
        }
Example #3
0
        private async Task <IActionResult> LogoutResponseAsync <T>(SamlUpParty party, Saml2Binding <T> binding)
        {
            var samlConfig = await saml2ConfigurationLogic.GetSamlUpConfigAsync(party);

            var saml2LogoutResponse = new Saml2LogoutResponse(samlConfig);

            binding.ReadSamlResponse(HttpContext.Request.ToGenericHttpRequest(), saml2LogoutResponse);

            await sequenceLogic.ValidateExternalSequenceIdAsync(binding.RelayState);

            var sequenceData = await sequenceLogic.GetSequenceDataAsync <SamlUpSequenceData>(remove : party.DisableSingleLogout);

            try
            {
                logger.ScopeTrace(() => $"SAML Logout response '{saml2LogoutResponse.XmlDocument.OuterXml}'.", traceType: TraceTypes.Message);
                logger.SetScopeProperty(Constants.Logs.Status, saml2LogoutResponse.Status.ToString());
                logger.ScopeTrace(() => "Up, SAML Logout response.", triggerEvent: true);

                if (saml2LogoutResponse.Status != Saml2StatusCodes.Success)
                {
                    throw new SamlRequestException("Unsuccessful Logout response.")
                          {
                              RouteBinding = RouteBinding, Status = saml2LogoutResponse.Status
                          };
                }

                try
                {
                    binding.Unbind(HttpContext.Request.ToGenericHttpRequest(), saml2LogoutResponse);
                    logger.ScopeTrace(() => "Up, Successful SAML Logout response.", triggerEvent: true);
                }
                catch (Exception ex)
                {
                    var isex = saml2ConfigurationLogic.GetInvalidSignatureValidationCertificateException(samlConfig, ex);
                    if (isex != null)
                    {
                        throw isex;
                    }
                    throw;
                }

                if (party.DisableSingleLogout)
                {
                    return(await LogoutResponseDownAsync(sequenceData));
                }
                else
                {
                    (var doSingleLogout, var singleLogoutSequenceData) = await singleLogoutDownLogic.InitializeSingleLogoutAsync(new UpPartyLink { Name = party.Name, Type = party.Type }, sequenceData.DownPartyLink, sequenceData.SessionDownPartyLinks, sequenceData.SessionClaims);

                    if (doSingleLogout)
                    {
                        return(await singleLogoutDownLogic.StartSingleLogoutAsync(singleLogoutSequenceData));
                    }
                    else
                    {
                        await sequenceLogic.RemoveSequenceDataAsync <SamlUpSequenceData>();

                        return(await LogoutResponseDownAsync(sequenceData));
                    }
                }
            }
            catch (StopSequenceException)
            {
                throw;
            }
            catch (SamlRequestException ex)
            {
                logger.Error(ex);
                return(await LogoutResponseDownAsync(sequenceData, status : ex.Status));
            }
            catch (Exception ex)
            {
                logger.Error(ex);
                return(await LogoutResponseDownAsync(sequenceData, status : Saml2StatusCodes.Responder));
            }
        }
        public async Task <IActionResult> FrontChannelLogoutAsync(string partyId)
        {
            logger.ScopeTrace(() => "Up, OIDC Front channel logout.");
            logger.SetScopeProperty(Constants.Logs.UpPartyId, partyId);

            var party = await tenantRepository.GetAsync <OidcUpParty>(partyId);

            logger.SetScopeProperty(Constants.Logs.UpPartyClientId, party.Client.ClientId);

            if (party.Client.DisableFrontChannelLogout)
            {
                return(new BadRequestResult());
            }

            var queryDictionary           = HttpContext.Request.Query.ToDictionary();
            var frontChannelLogoutRequest = queryDictionary.ToObject <FrontChannelLogoutRequest>();

            logger.ScopeTrace(() => $"Up, Front channel logout request '{frontChannelLogoutRequest.ToJsonIndented()}'.", traceType: TraceTypes.Message);
            frontChannelLogoutRequest.Validate();
            if (party.Client.FrontChannelLogoutSessionRequired)
            {
                if (frontChannelLogoutRequest.SessionId.IsNullOrEmpty())
                {
                    throw new ArgumentNullException(nameof(frontChannelLogoutRequest.SessionId), frontChannelLogoutRequest.GetTypeName());
                }
            }

            var session = await sessionUpPartyLogic.GetSessionAsync(party);

            logger.ScopeTrace(() => "Up, Successful OIDC Front channel logout request.", triggerEvent: true);
            if (session != null)
            {
                if (party.Client.FrontChannelLogoutSessionRequired)
                {
                    if (!party.Issuers.Where(i => i == frontChannelLogoutRequest.Issuer).Any())
                    {
                        throw new Exception("Incorrect issuer.");
                    }
                    if (session.ExternalSessionId != frontChannelLogoutRequest.SessionId)
                    {
                        throw new Exception("Incorrect session id.");
                    }
                }

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

                await oauthRefreshTokenGrantLogic.DeleteRefreshTokenGrantsAsync(session.SessionId);

                if (!party.DisableSingleLogout)
                {
                    var allowIframeOnDomains = new List <string>().ConcatOnce(party.Client.AuthorizeUrl?.UrlToDomain()).ConcatOnce(party.Client.EndSessionUrl?.UrlToDomain()).ConcatOnce(party.Client.TokenUrl?.UrlToDomain());
                    (var doSingleLogout, var singleLogoutSequenceData) = await singleLogoutDownLogic.InitializeSingleLogoutAsync(new UpPartyLink { Name = party.Name, Type = party.Type }, null, session.DownPartyLinks, session.Claims, allowIframeOnDomains, hostedInIframe : true);

                    if (doSingleLogout)
                    {
                        return(await singleLogoutDownLogic.StartSingleLogoutAsync(singleLogoutSequenceData));
                    }
                }
            }

            return(new OkResult());
        }
Example #5
0
        public async Task <IActionResult> FrontChannelLogoutAsync(string partyId)
        {
            logger.ScopeTrace("Up, OIDC Front channel logout.");
            logger.SetScopeProperty("upPartyId", partyId);

            var party = await tenantRepository.GetAsync <OidcUpParty>(partyId);

            logger.SetScopeProperty("upPartyClientId", party.Client.ClientId);

            if (party.Client.DisableFrontChannelLogout)
            {
                return(new BadRequestResult());
            }

            var queryDictionary           = HttpContext.Request.Query.ToDictionary();
            var frontChannelLogoutRequest = queryDictionary.ToObject <FrontChannelLogoutRequest>();

            logger.ScopeTrace($"Up, Front channel logout request '{frontChannelLogoutRequest.ToJsonIndented()}'.");
            frontChannelLogoutRequest.Validate();
            if (party.Client.FrontChannelLogoutSessionRequired)
            {
                if (frontChannelLogoutRequest.SessionId.IsNullOrEmpty())
                {
                    throw new ArgumentNullException(nameof(frontChannelLogoutRequest.SessionId), frontChannelLogoutRequest.GetTypeName());
                }
            }

            var session = await sessionUpPartyLogic.GetSessionAsync(party);

            logger.ScopeTrace("Up, Successful OIDC Front channel logout request.", triggerEvent: true);
            if (session != null)
            {
                if (party.Client.FrontChannelLogoutSessionRequired)
                {
                    if (!session.Claims.Where(c => c.Claim == JwtClaimTypes.Issuer && c.Values.Where(v => v == frontChannelLogoutRequest.Issuer).Any()).Any())
                    {
                        throw new Exception("Incorrect issuer.");
                    }
                    if (session.ExternalSessionId != frontChannelLogoutRequest.SessionId)
                    {
                        throw new Exception("Incorrect session id.");
                    }
                }

                var _ = await sessionUpPartyLogic.DeleteSessionAsync(session);

                await oauthRefreshTokenGrantLogic.DeleteRefreshTokenGrantsAsync(session.SessionId);

                if (!party.DisableSingleLogout)
                {
                    (var doSingleLogout, var singleLogoutSequenceData) = await singleLogoutDownLogic.InitializeSingleLogoutAsync(new UpPartyLink { Name = party.Name, Type = party.Type }, null, session.DownPartyLinks, session.Claims, redirectAfterLogout : false);

                    if (doSingleLogout)
                    {
                        securityHeaderLogic.AddAllowIframeOnUrls(new [] { party.Client.AuthorizeUrl, party.Client.EndSessionUrl });
                        return(await singleLogoutDownLogic.StartSingleLogoutAsync(singleLogoutSequenceData));
                    }
                }
            }

            return(new OkResult());
        }