Пример #1
0
        public Saml2Configuration GetSamlUpConfig(SamlUpParty party, bool includeSigningCertificate = false)
        {
            var samlConfig = new Saml2Configuration();

            samlConfig.AllowedIssuer = party.Issuer;

            samlConfig.Issuer = !party.SpIssuer.IsNullOrEmpty() ? party.SpIssuer : trackIssuerLogic.GetIssuer();
            samlConfig.AllowedAudienceUris.Add(samlConfig.Issuer);

            samlConfig.SingleSignOnDestination = new Uri(party.AuthnUrl);
            if (!party.LogoutUrl.IsNullOrEmpty())
            {
                samlConfig.SingleLogoutDestination = new Uri(party.LogoutUrl);
            }

            foreach (var key in party.Keys)
            {
                samlConfig.SignatureValidationCertificates.Add(key.ToSaml2X509Certificate());
            }

            if (includeSigningCertificate)
            {
                samlConfig.SigningCertificate = trackKeyLogic.GetPrimarySaml2X509Certificate(RouteBinding.Key);
            }
            samlConfig.SignatureAlgorithm = party.SignatureAlgorithm;

            samlConfig.CertificateValidationMode = party.CertificateValidationMode;
            samlConfig.RevocationMode            = party.RevocationMode;

            return(samlConfig);
        }
Пример #2
0
        public async Task <IActionResult> LogoutRequestAsync(IEnumerable <string> partyIds, SingleLogoutSequenceData sequenceData)
        {
            var frontChannelLogoutRequest = new FrontChannelLogoutRequest
            {
                Issuer    = trackIssuerLogic.GetIssuer(),
                SessionId = sequenceData.Claims.FindFirstValue(c => c.Claim == JwtClaimTypes.SessionId)
            };
            var nameValueCollection = frontChannelLogoutRequest.ToDictionary();

            TParty firstParty      = null;
            var    partyLogoutUrls = new List <string>();

            foreach (var partyId in partyIds)
            {
                try
                {
                    var party = await tenantRepository.GetAsync <TParty>(partyId);

                    if (party.Client == null)
                    {
                        throw new NotSupportedException("Party Client not configured.");
                    }
                    if (party.Client.FrontChannelLogoutUri.IsNullOrWhiteSpace())
                    {
                        throw new Exception("Front channel logout URI not configured.");
                    }

                    firstParty = party;
                    if (party.Client.FrontChannelLogoutSessionRequired)
                    {
                        partyLogoutUrls.Add(QueryHelpers.AddQueryString(party.Client.FrontChannelLogoutUri, nameValueCollection));
                    }
                    else
                    {
                        partyLogoutUrls.Add(party.Client.FrontChannelLogoutUri);
                    }
                }
                catch (Exception ex)
                {
                    logger.Warning(ex, $"Unable to get front channel logout for party ID '{partyId}'.");
                }
            }

            if (partyLogoutUrls.Count() <= 0 || firstParty == null)
            {
                throw new InvalidOperationException("Unable to complete front channel logout. Please close the browser to logout.");
            }

            securityHeaderLogic.AddFrameSrc(partyLogoutUrls);
            var redirectUrl = HttpContext.GetDownPartyUrl(firstParty.Name, sequenceData.UpPartyName, Constants.Routes.OAuthController, Constants.Endpoints.FrontChannelLogoutDone, includeSequence: true);

            return(partyLogoutUrls.ToHtmIframePage(redirectUrl, "FoxIDs").ToContentResult());
        }
        public async Task <OidcDiscovery> OpenidConfiguration(string partyId)
        {
            logger.ScopeTrace(() => "Down, OpenID configuration request.");
            logger.SetScopeProperty(Constants.Logs.DownPartyId, partyId);
            var party = RouteBinding.DownParty != null ? await tenantRepository.GetAsync <TParty>(partyId) : null;

            var oidcDiscovery = new OidcDiscovery
            {
                Issuer = trackIssuerLogic.GetIssuer(),
                AuthorizationEndpoint = UrlCombine.Combine(HttpContext.GetHostWithTenantAndTrack(), RouteBinding.PartyNameAndBinding, Constants.Routes.OAuthController, Constants.Endpoints.Authorize),
                TokenEndpoint         = UrlCombine.Combine(HttpContext.GetHostWithTenantAndTrack(), RouteBinding.PartyNameAndBinding, Constants.Routes.OAuthController, Constants.Endpoints.Token),
                UserInfoEndpoint      = UrlCombine.Combine(HttpContext.GetHostWithTenantAndTrack(), RouteBinding.PartyNameAndBinding, Constants.Routes.OAuthController, Constants.Endpoints.UserInfo),
                EndSessionEndpoint    = UrlCombine.Combine(HttpContext.GetHostWithTenantAndTrack(), RouteBinding.PartyNameAndBinding, Constants.Routes.OAuthController, Constants.Endpoints.EndSession),
                JwksUri = UrlCombine.Combine(HttpContext.GetHostWithTenantAndTrack(), RouteBinding.PartyNameAndBinding, IdentityConstants.OidcDiscovery.Path, IdentityConstants.OidcDiscovery.Keys),
                FrontchannelLogoutSupported        = true,
                FrontchannelLogoutSessionSupported = true
            };

            if (party?.Client != null)
            {
                oidcDiscovery.ResponseModesSupported           = new[] { IdentityConstants.ResponseModes.Fragment, IdentityConstants.ResponseModes.Query, IdentityConstants.ResponseModes.FormPost };
                oidcDiscovery.SubjectTypesSupported            = new[] { IdentityConstants.SubjectTypes.Pairwise };
                oidcDiscovery.IdTokenSigningAlgValuesSupported = new[] { IdentityConstants.Algorithms.Asymmetric.RS256 };
                oidcDiscovery.ResponseTypesSupported           = party.Client.ResponseTypes;
                oidcDiscovery.ScopesSupported = oidcDiscovery.ScopesSupported.ConcatOnce(party.Client.Scopes?.Select(s => s.Scope));
                oidcDiscovery.ClaimsSupported = oidcDiscovery.ClaimsSupported.ConcatOnce(Constants.DefaultClaims.IdToken).ConcatOnce(Constants.DefaultClaims.AccessToken)
                                                .ConcatOnce(party.Client.Claims?.Where(c => c.Claim?.Contains('*') != true)?.Select(c => c.Claim).ToList()).ConcatOnce(party.Client.Scopes?.Where(s => s.VoluntaryClaims != null).SelectMany(s => s.VoluntaryClaims?.Select(c => c.Claim)).ToList());

                if (party?.Client.RequirePkce == true)
                {
                    oidcDiscovery.CodeChallengeMethodsSupported = new[] { IdentityConstants.CodeChallengeMethods.Plain, IdentityConstants.CodeChallengeMethods.S256 };
                }
            }
            else
            {
                oidcDiscovery.ResponseModesSupported           = new[] { IdentityConstants.ResponseModes.Fragment, IdentityConstants.ResponseModes.Query, IdentityConstants.ResponseModes.FormPost };
                oidcDiscovery.SubjectTypesSupported            = new[] { IdentityConstants.SubjectTypes.Pairwise };
                oidcDiscovery.IdTokenSigningAlgValuesSupported = new[] { IdentityConstants.Algorithms.Asymmetric.RS256 };
                oidcDiscovery.ResponseTypesSupported           = new[] { IdentityConstants.ResponseTypes.Code };
                oidcDiscovery.ScopesSupported = oidcDiscovery.ScopesSupported;
                oidcDiscovery.ClaimsSupported = oidcDiscovery.ClaimsSupported.ConcatOnce(Constants.DefaultClaims.IdToken).ConcatOnce(Constants.DefaultClaims.AccessToken);
                oidcDiscovery.CodeChallengeMethodsSupported = new[] { IdentityConstants.CodeChallengeMethods.Plain, IdentityConstants.CodeChallengeMethods.S256 };
            }

            return(oidcDiscovery);
        }
Пример #4
0
        public async Task <FoxIDsSaml2Configuration> GetSamlUpConfigAsync(SamlUpParty party, bool includeSigningAndDecryptionCertificate = false, bool includeSignatureValidationCertificates = true)
        {
            var samlConfig = new FoxIDsSaml2Configuration();

            if (party != null)
            {
                samlConfig.AllowedIssuer = party.Issuer;
            }

            samlConfig.Issuer = !string.IsNullOrEmpty(party?.SpIssuer) ? party.SpIssuer : trackIssuerLogic.GetIssuer();
            samlConfig.AllowedAudienceUris.Add(samlConfig.Issuer);

            if (party != null)
            {
                samlConfig.SingleSignOnDestination = new Uri(party.AuthnUrl);
                if (!string.IsNullOrEmpty(party?.LogoutUrl))
                {
                    samlConfig.SingleLogoutDestination = new Uri(party.LogoutUrl);
                }

                if (includeSignatureValidationCertificates)
                {
                    var partyCertificates = party.Keys.ToSaml2X509Certificates();
                    foreach (var partyCertificate in partyCertificates)
                    {
                        if (partyCertificate.IsValidLocalTime())
                        {
                            samlConfig.SignatureValidationCertificates.Add(partyCertificate);
                        }
                        else
                        {
                            samlConfig.InvalidSignatureValidationCertificates.Add(partyCertificate);
                        }
                    }
                }
            }

            if (includeSigningAndDecryptionCertificate)
            {
                samlConfig.SigningCertificate = samlConfig.DecryptionCertificate = await trackKeyLogic.GetPrimarySaml2X509CertificateAsync(RouteBinding.Key);

                samlConfig.SecondaryDecryptionCertificate = trackKeyLogic.GetSecondarySaml2X509Certificate(RouteBinding.Key);
            }
            if (party != null)
            {
                samlConfig.SignatureAlgorithm = party.SignatureAlgorithm;
                samlConfig.SignAuthnRequest   = party.SignAuthnRequest;

                samlConfig.CertificateValidationMode = party.CertificateValidationMode;
                samlConfig.RevocationMode            = party.RevocationMode;
            }

            return(samlConfig);
        }
Пример #5
0
        public async Task <IActionResult> LogoutRequestAsync(IEnumerable <string> partyIds, SingleLogoutSequenceData sequenceData, bool hostedInIframe, bool doSamlLogoutInIframe)
        {
            var frontChannelLogoutRequest = new FrontChannelLogoutRequest
            {
                Issuer    = trackIssuerLogic.GetIssuer(),
                SessionId = sequenceData.Claims.FindFirstValue(c => c.Claim == JwtClaimTypes.SessionId)
            };
            var nameValueCollection = frontChannelLogoutRequest.ToDictionary();

            TParty firstParty      = null;
            var    partyLogoutUrls = new List <string>();

            foreach (var partyId in partyIds)
            {
                try
                {
                    var party = await tenantRepository.GetAsync <TParty>(partyId);

                    if (party.Client == null)
                    {
                        throw new NotSupportedException("Party Client not configured.");
                    }
                    if (party.Client.FrontChannelLogoutUri.IsNullOrWhiteSpace())
                    {
                        throw new Exception("Front channel logout URI not configured.");
                    }

                    firstParty = party;
                    if (party.Client.FrontChannelLogoutSessionRequired)
                    {
                        partyLogoutUrls.Add(QueryHelpers.AddQueryString(party.Client.FrontChannelLogoutUri, nameValueCollection));
                    }
                    else
                    {
                        partyLogoutUrls.Add(party.Client.FrontChannelLogoutUri);
                    }
                }
                catch (Exception ex)
                {
                    logger.Warning(ex, $"Unable to get front channel logout for party ID '{partyId}'.");
                }
            }

            if (partyLogoutUrls.Count() <= 0 || firstParty == null)
            {
                throw new InvalidOperationException("Unable to complete front channel logout. Please close the browser to logout.");
            }

            if (doSamlLogoutInIframe)
            {
                securityHeaderLogic.AddFrameSrcAllowAll();
                // Start SAML logout
                partyLogoutUrls.Add(GetFrontChannelLogoutDoneUrl(sequenceData, firstParty));
            }
            else
            {
                securityHeaderLogic.AddFrameSrcUrls(partyLogoutUrls);
            }
            string redirectUrl = hostedInIframe ? null : GetFrontChannelLogoutDoneUrl(sequenceData, firstParty);

            return(partyLogoutUrls.ToHtmIframePage(redirectUrl, "FoxIDs").ToContentResult());
        }
Пример #6
0
        public async Task <string> CreateIdTokenAsync(TClient client, IEnumerable <Claim> claims, IEnumerable <string> selectedScopes, string nonce, IEnumerable <string> responseTypes, string code, string accessToken, string algorithm)
        {
            if (!(client is OidcDownClient))
            {
                throw new InvalidOperationException("Include ID Token only possible for OIDC Down Client.");
            }

            var onlyIdToken   = !responseTypes.Contains(IdentityConstants.ResponseTypes.Code) && !responseTypes.Contains(IdentityConstants.ResponseTypes.Token);
            var idTokenClaims = new List <Claim>(await claimsDownLogic.FilterJwtClaimsAsync(client, claims, selectedScopes, includeIdTokenClaims: true, includeAccessTokenClaims: onlyIdToken));

            var clientClaims = claimsDownLogic.GetClientJwtClaims(client, onlyIdTokenClaims: true);

            if (clientClaims?.Count() > 0)
            {
                idTokenClaims.AddRange(clientClaims);
            }

            if (!nonce.IsNullOrEmpty())
            {
                idTokenClaims.AddClaim(JwtClaimTypes.Nonce, nonce);
            }

            if (!onlyIdToken)
            {
                if (responseTypes.Contains(IdentityConstants.ResponseTypes.Token))
                {
                    idTokenClaims.AddClaim(JwtClaimTypes.AtHash, await accessToken.LeftMostBase64urlEncodedHashAsync(algorithm));
                }
                if (responseTypes.Contains(IdentityConstants.ResponseTypes.Code))
                {
                    idTokenClaims.AddClaim(JwtClaimTypes.CHash, await code.LeftMostBase64urlEncodedHashAsync(algorithm));
                }
            }

            logger.ScopeTrace(() => $"Down, JWT ID token claims '{idTokenClaims.ToFormattedString()}'", traceType: TraceTypes.Claim);
            var token = JwtHandler.CreateToken(await trackKeyLogic.GetPrimarySecurityKeyAsync(RouteBinding.Key), trackIssuerLogic.GetIssuer(), client.ClientId, idTokenClaims, expiresIn: (client as OidcDownClient).IdTokenLifetime, algorithm: algorithm);

            return(await token.ToJwtString());
        }