Ejemplo n.º 1
0
        private async Task <IActionResult> LogoutRequestAsync <T>(SamlDownParty party, Saml2Binding <T> binding)
        {
            var samlConfig = saml2ConfigurationLogic.GetSamlDownConfig(party);

            var saml2LogoutRequest = new Saml2LogoutRequest(samlConfig);

            binding.ReadSamlRequest(HttpContext.Request.ToGenericHttpRequest(), saml2LogoutRequest);
            logger.ScopeTrace($"SAML Logout request '{saml2LogoutRequest.XmlDocument.OuterXml}'.");

            try
            {
                ValidateLogoutRequest(party, saml2LogoutRequest);
                binding.Unbind(HttpContext.Request.ToGenericHttpRequest(), saml2LogoutRequest);
                logger.ScopeTrace("Down, SAML Logout request accepted.", triggerEvent: true);

                await sequenceLogic.SaveSequenceDataAsync(new SamlDownSequenceData
                {
                    Id          = saml2LogoutRequest.Id.Value,
                    RelayState  = binding.RelayState,
                    ResponseUrl = party.LoggedOutUrl,
                });

                await formActionLogic.CreateFormActionByUrlAsync(party.LoggedOutUrl);

                var type = RouteBinding.ToUpParties.First().Type;
                logger.ScopeTrace($"Request, Up type '{type}'.");
                switch (type)
                {
                case PartyTypes.Login:
                    return(await serviceProvider.GetService <LogoutUpLogic>().LogoutRedirect(RouteBinding.ToUpParties.First(), new LogoutRequest
                    {
                        DownParty = party,
                        SessionId = saml2LogoutRequest.SessionIndex,
                        RequireLogoutConsent = false,
                        PostLogoutRedirect = true,
                    }));

                case PartyTypes.OAuth2:
                    throw new NotImplementedException();

                case PartyTypes.Oidc:
                    throw new NotImplementedException();

                case PartyTypes.Saml2:
                    return(await serviceProvider.GetService <SamlLogoutUpLogic>().LogoutAsync(RouteBinding.ToUpParties.First(), GetSamlUpLogoutRequest(saml2LogoutRequest, party)));

                default:
                    throw new NotSupportedException($"Party type '{type}' not supported.");
                }
            }
            catch (SamlRequestException ex)
            {
                logger.Error(ex);
                return(await LogoutResponseAsync(party.Id, samlConfig, saml2LogoutRequest.Id.Value, binding.RelayState, saml2LogoutRequest.Destination?.OriginalString, party.AuthnBinding.ResponseBinding, ex.Status));
            }
        }
Ejemplo n.º 2
0
        private async Task <IActionResult> AuthnRequestAsync <T>(SamlDownParty party, Saml2Binding <T> binding)
        {
            var samlConfig = saml2ConfigurationLogic.GetSamlDownConfig(party);
            var request    = HttpContext.Request;

            var saml2AuthnRequest = new Saml2AuthnRequest(samlConfig);

            binding.ReadSamlRequest(request.ToGenericHttpRequest(), saml2AuthnRequest);
            logger.ScopeTrace($"SAML Authn request '{saml2AuthnRequest.XmlDocument.OuterXml}'.");

            try
            {
                ValidateAuthnRequest(party, saml2AuthnRequest);
                binding.Unbind(request.ToGenericHttpRequest(), saml2AuthnRequest);
                logger.ScopeTrace("Down, SAML Auth request accepted.", triggerEvent: true);

                var responseUrl = GetAcsUrl(party, saml2AuthnRequest);
                await sequenceLogic.SaveSequenceDataAsync(new SamlDownSequenceData
                {
                    Id          = saml2AuthnRequest.Id.Value,
                    RelayState  = binding.RelayState,
                    ResponseUrl = responseUrl,
                });

                await formActionLogic.CreateFormActionByUrlAsync(responseUrl);

                var type = RouteBinding.ToUpParties.First().Type;
                logger.ScopeTrace($"Request, Up type '{type}'.");
                switch (type)
                {
                case PartyTypes.Login:
                    return(await serviceProvider.GetService <LoginUpLogic>().LoginRedirectAsync(RouteBinding.ToUpParties.First(), GetLoginRequestAsync(party, saml2AuthnRequest)));

                case PartyTypes.OAuth2:
                    throw new NotImplementedException();

                case PartyTypes.Oidc:
                    return(await serviceProvider.GetService <OidcAuthUpLogic <OidcDownParty, OidcDownClient, OidcDownScope, OidcDownClaim> >().AuthenticationRequestAsync(RouteBinding.ToUpParties.First()));

                case PartyTypes.Saml2:
                    return(await serviceProvider.GetService <SamlAuthnUpLogic>().AuthnRequestAsync(RouteBinding.ToUpParties.First(), GetLoginRequestAsync(party, saml2AuthnRequest)));

                default:
                    throw new NotSupportedException($"Party type '{type}' not supported.");
                }
            }
            catch (SamlRequestException ex)
            {
                logger.Error(ex);
                return(await AuthnResponseAsync(party.Id, samlConfig, saml2AuthnRequest.Id.Value, binding.RelayState, GetAcsUrl(party, saml2AuthnRequest), party.AuthnBinding.ResponseBinding, ex.Status));
            }
        }
Ejemplo n.º 3
0
        public async Task <IActionResult> AuthenticationRequestAsync(string partyId)
        {
            logger.ScopeTrace("Down, OIDC Authentication request.");
            logger.SetScopeProperty("downPartyId", partyId);
            var party = await tenantRepository.GetAsync <TParty>(partyId);

            if (party.Client == null)
            {
                throw new NotSupportedException($"Party Client not configured.");
            }

            var queryDictionary       = HttpContext.Request.Query.ToDictionary();
            var authenticationRequest = queryDictionary.ToObject <AuthenticationRequest>();

            logger.ScopeTrace($"Authentication request '{authenticationRequest.ToJsonIndented()}'.");
            logger.SetScopeProperty("clientId", authenticationRequest.ClientId);

            var codeChallengeSecret = party.Client.EnablePkce.Value ? queryDictionary.ToObject <CodeChallengeSecret>() : null;

            if (codeChallengeSecret != null)
            {
                codeChallengeSecret.Validate();
                logger.ScopeTrace($"CodeChallengeSecret '{codeChallengeSecret.ToJsonIndented()}'.");
            }

            try
            {
                var requireCodeFlow = party.Client.EnablePkce.Value && codeChallengeSecret != null;
                ValidateAuthenticationRequest(party.Client, authenticationRequest, requireCodeFlow);
                logger.ScopeTrace("Down, OIDC Authentication request accepted.", triggerEvent: true);

                if (!authenticationRequest.UiLocales.IsNullOrWhiteSpace())
                {
                    await sequenceLogic.SetCultureAsync(authenticationRequest.UiLocales.ToSpaceList());
                }

                await sequenceLogic.SaveSequenceDataAsync(new OidcDownSequenceData
                {
                    ResponseType        = authenticationRequest.ResponseType,
                    RedirectUri         = authenticationRequest.RedirectUri,
                    Scope               = authenticationRequest.Scope,
                    State               = authenticationRequest.State,
                    ResponseMode        = authenticationRequest.ResponseMode,
                    Nonce               = authenticationRequest.Nonce,
                    CodeChallenge       = codeChallengeSecret?.CodeChallenge,
                    CodeChallengeMethod = codeChallengeSecret?.CodeChallengeMethod,
                });

                await formActionLogic.CreateFormActionByUrlAsync(authenticationRequest.RedirectUri);

                var type = RouteBinding.ToUpParties.First().Type;
                logger.ScopeTrace($"Request, Up type '{type}'.");
                switch (type)
                {
                case PartyTypes.Login:
                    return(await serviceProvider.GetService <LoginUpLogic>().LoginRedirectAsync(RouteBinding.ToUpParties.First(), await GetLoginRequestAsync(party, authenticationRequest)));

                case PartyTypes.OAuth2:
                    throw new NotImplementedException();

                case PartyTypes.Oidc:
                    return(await serviceProvider.GetService <OidcAuthUpLogic <OidcDownParty, OidcDownClient, OidcDownScope, OidcDownClaim> >().AuthenticationRequestAsync(RouteBinding.ToUpParties.First()));

                case PartyTypes.Saml2:
                    return(await serviceProvider.GetService <SamlAuthnUpLogic>().AuthnRequestAsync(RouteBinding.ToUpParties.First(), await GetLoginRequestAsync(party, authenticationRequest)));

                default:
                    throw new NotSupportedException($"Party type '{type}' not supported.");
                }
            }
            catch (OAuthRequestException ex)
            {
                logger.Error(ex);
                return(await AuthenticationResponseErrorAsync(partyId, authenticationRequest, ex));
            }
        }
Ejemplo n.º 4
0
        public async Task <IActionResult> EndSessionRequestAsync(string partyId)
        {
            logger.ScopeTrace("Down, End session request.");
            logger.SetScopeProperty("downPartyId", partyId);
            var party = await tenantRepository.GetAsync <TParty>(partyId);

            if (party.Client == null)
            {
                throw new NotSupportedException($"Party Client not configured.");
            }

            var endSessionRequest = HttpContext.Request.Query.ToObject <EndSessionRequest>();

            logger.ScopeTrace($"end session request '{endSessionRequest.ToJsonIndented()}'.");
            logger.SetScopeProperty("clientId", party.Client.ClientId);

            ValidateEndSessionRequest(party.Client, endSessionRequest);
            logger.ScopeTrace("Down, OIDC End session request accepted.", triggerEvent: true);

            (var validIdToken, var sessionId, var idTokenClaims) = await ValidateIdTokenHintAsync(party.Client, endSessionRequest.IdTokenHint);

            if (!validIdToken)
            {
                if (!endSessionRequest.IdTokenHint.IsNullOrEmpty())
                {
                    throw new OAuthRequestException($"Invalid ID Token hint.")
                          {
                              RouteBinding = RouteBinding
                          };
                }
                else if (party.Client.RequireLogoutIdTokenHint)
                {
                    throw new OAuthRequestException($"ID Token hint is required.")
                          {
                              RouteBinding = RouteBinding
                          };
                }
            }
            else
            {
                logger.ScopeTrace("Valid ID token hint.");
            }

            await oauthRefreshTokenGrantLogic.DeleteRefreshTokenGrantAsync(party.Client, sessionId);

            await sequenceLogic.SaveSequenceDataAsync(new OidcDownSequenceData
            {
                RedirectUri = endSessionRequest.PostLogoutRedirectUri,
                State       = endSessionRequest.State,
            });

            await formActionLogic.CreateFormActionByUrlAsync(endSessionRequest.PostLogoutRedirectUri);

            var type = RouteBinding.ToUpParties.First().Type;

            logger.ScopeTrace($"Request, Up type '{type}'.");
            switch (type)
            {
            case PartyTypes.Login:
                var logoutRequest = new LogoutRequest
                {
                    DownParty            = party,
                    SessionId            = sessionId,
                    RequireLogoutConsent = !validIdToken,
                    PostLogoutRedirect   = !endSessionRequest.PostLogoutRedirectUri.IsNullOrWhiteSpace(),
                };
                return(await serviceProvider.GetService <LogoutUpLogic>().LogoutRedirect(RouteBinding.ToUpParties.First(), logoutRequest));

            case PartyTypes.OAuth2:
                throw new NotImplementedException();

            case PartyTypes.Oidc:
                throw new NotImplementedException();

            case PartyTypes.Saml2:
                if (!validIdToken)
                {
                    throw new OAuthRequestException($"ID Token hint is required for SAML 2.0 Up Party.")
                          {
                              RouteBinding = RouteBinding
                          };
                }
                return(await serviceProvider.GetService <SamlLogoutUpLogic>().LogoutAsync(RouteBinding.ToUpParties.First(), GetSamlUpLogoutRequest(party, sessionId, idTokenClaims)));

            default:
                throw new NotSupportedException($"Party type '{type}' not supported.");
            }
        }