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

            if (!party.IdSIssuer.IsNullOrEmpty())
            {
                samlConfig.Issuer = party.IdSIssuer;
            }
            else
            {
                samlConfig.Issuer = UrlCombine.Combine(HttpContext.GetHost(), RouteBinding.TenantName, RouteBinding.TrackName);
            }

            if (party.Keys?.Count > 0)
            {
                foreach (var key in party.Keys)
                {
                    samlConfig.SignatureValidationCertificates.Add(key.ToSaml2X509Certificate());
                }
            }

            if (includeSigningCertificate)
            {
                samlConfig.SigningCertificate = trackKeyLogic.GetSaml2X509Certificate(RouteBinding.PrimaryKey);
            }
            samlConfig.SignatureAlgorithm = party.SignatureAlgorithm;

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

            return(samlConfig);
        }
Пример #2
0
        public async Task <OidcDiscovery> OpenidConfiguration(string partyId)
        {
            logger.SetScopeProperty("downPartyId", partyId);
            var party = await tenantRepository.GetAsync <TParty>(partyId);

            var oidcDiscovery = new OidcDiscovery
            {
                Issuer = UrlCombine.Combine(HttpContext.GetHost(), RouteBinding.TenantName, RouteBinding.TrackName),
                AuthorizationEndpoint = UrlCombine.Combine(HttpContext.GetHost(), RouteBinding.TenantName, RouteBinding.TrackName, RouteBinding.PartyNameAndBinding, Constants.Routes.OAuthController, Constants.Endpoints.Authorize),
                TokenEndpoint         = UrlCombine.Combine(HttpContext.GetHost(), RouteBinding.TenantName, RouteBinding.TrackName, RouteBinding.PartyNameAndBinding, Constants.Routes.OAuthController, Constants.Endpoints.Token),
                UserInfoEndpoint      = UrlCombine.Combine(HttpContext.GetHost(), RouteBinding.TenantName, RouteBinding.TrackName, RouteBinding.PartyNameAndBinding, Constants.Routes.OAuthController, Constants.Endpoints.UserInfo),
                EndSessionEndpoint    = UrlCombine.Combine(HttpContext.GetHost(), RouteBinding.TenantName, RouteBinding.TrackName, RouteBinding.PartyNameAndBinding, Constants.Routes.OAuthController, Constants.Endpoints.EndSession),
                JwksUri = UrlCombine.Combine(HttpContext.GetHost(), RouteBinding.TenantName, RouteBinding.TrackName, RouteBinding.PartyNameAndBinding, IdentityConstants.OidcDiscovery.Path, IdentityConstants.OidcDiscovery.Keys),
            };

            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?.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.EnablePkce == true)
                {
                    oidcDiscovery.CodeChallengeMethodsSupported = new[] { IdentityConstants.CodeChallengeMethods.Plain, IdentityConstants.CodeChallengeMethods.S256 };
                }
            }

            return(oidcDiscovery);
        }
Пример #3
0
        protected override async Task <AuthenticateResult> HandleAuthenticateAsync()
        {
            try
            {
                var accessToken = GetAccessTokenFromHeader();

                var routeBinding = Context.GetRouteBinding();
                var authority    = UrlCombine.Combine(GetFoxIDsEndpoint(), routeBinding.TenantName, Constants.Routes.DefaultMasterTrackName, Options.DownParty);

                var oidcDiscoveryUri     = UrlCombine.Combine(authority, IdentityConstants.OidcDiscovery.Path);
                var oidcDiscoveryHandler = Context.RequestServices.GetService <OidcDiscoveryHandler>();
                var oidcDiscovery        = await oidcDiscoveryHandler.GetOidcDiscoveryAsync(oidcDiscoveryUri);

                var oidcDiscoveryKeySet = await oidcDiscoveryHandler.GetOidcDiscoveryKeysAsync(oidcDiscoveryUri);

                (var principal, var securityToken) = JwtHandler.ValidateToken(accessToken, oidcDiscovery.Issuer, oidcDiscoveryKeySet.Keys, Options.DownParty);
                var ticket = new AuthenticationTicket(principal, Scheme.Name);
                return(AuthenticateResult.Success(ticket));
            }
            catch (Exception ex)
            {
                Logger.LogError(ex, ex.Message);
                return(AuthenticateResult.Fail(ex.Message));
            }
        }
Пример #4
0
        private async Task CreateAspNetCoreSamlIdPSampleUpPartyAsync()
        {
            Func <string, Task> getAction = async(name) =>
            {
                _ = await foxIDsApiClient.GetSamlUpPartyAsync(name);
            };

            Func <string, Task> postAction = async(name) =>
            {
                var baseUrl = "https://localhost:44342";

                var samlUpParty = new SamlUpParty
                {
                    Name   = name,
                    Issuer = "urn:itfoxtec:idservice:samples:aspnetcoresamlidpsample",
                    Keys   = new[] { GetSamlCertificateKey("AspNetCoreSamlIdPSample-test-sign-cert.crt") },
                    //SignatureAlgorithm = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256",
                    //CertificateValidationMode = X509CertificateValidationMode.None,
                    //RevocationMode = X509RevocationMode.NoCheck,
                    AuthnRequestBinding   = SamlBindingTypes.Redirect,
                    AuthnResponseBinding  = SamlBindingTypes.Post,
                    AuthnUrl              = UrlCombine.Combine(baseUrl, "saml/login"),
                    LogoutRequestBinding  = SamlBindingTypes.Post,
                    LogoutResponseBinding = SamlBindingTypes.Post,
                    LogoutUrl             = UrlCombine.Combine(baseUrl, "saml/logout"),
                    Claims = new string[] { ClaimTypes.Email, ClaimTypes.Name, ClaimTypes.GivenName, ClaimTypes.Surname, ClaimTypes.Role }
                };

                await foxIDsApiClient.PostSamlUpPartyAsync(samlUpParty);
            };

            await CreateIfNotExistsAsync(aspNetCoreSamlIdPSampleUpPartyName, getAction, postAction);
        }
Пример #5
0
        private async Task <(OidcDiscovery, JsonWebKeySet)> GetOidcDiscoveryAndValidateAsync(string authority)
        {
            var oidcDiscoveryUrl = UrlCombine.Combine(authority, IdentityConstants.OidcDiscovery.Path);

            try
            {
                var oidcDiscovery = await GetOidcDiscoveryAsync(oidcDiscoveryUrl);

                if (oidcDiscovery.Issuer.IsNullOrEmpty())
                {
                    throw new Exception($"{nameof(oidcDiscovery.Issuer)} is required.");
                }
                if (oidcDiscovery.AuthorizationEndpoint.IsNullOrEmpty())
                {
                    throw new Exception($"{nameof(oidcDiscovery.AuthorizationEndpoint)} is required.");
                }
                if (oidcDiscovery.JwksUri.IsNullOrEmpty())
                {
                    throw new Exception($"{nameof(oidcDiscovery.JwksUri)} is required.");
                }

                var jsonWebKeySet = await GetOidcDiscoveryKeysAsync(oidcDiscovery.JwksUri);

                if (jsonWebKeySet.Keys?.Count <= 0)
                {
                    throw new Exception($"At least one key in {nameof(jsonWebKeySet.Keys)} is required.");
                }

                return(oidcDiscovery, jsonWebKeySet);
            }
            catch (Exception ex)
            {
                throw new Exception($"OIDC discovery error for OIDC discovery URL '{oidcDiscoveryUrl}'.", ex);
            }
        }
        /// <summary>
        /// Combines the Uri with base path and the array of relative urls into one, consolidating the '/' between them
        /// </summary>
        /// <param name="baseUri">Base Uri that will be combined</param>
        /// <param name="relativePaths">The array of relative paths to combine</param>
        /// <returns>The merged Uri</returns>
        public static Uri Combine(this Uri baseUri, params string[] relativePaths)
        {
            if (baseUri == null)
            {
                throw new ArgumentNullException(nameof(baseUri));
            }

            return(new Uri(UrlCombine.Combine(baseUri.AbsoluteUri, relativePaths)));
        }
Пример #7
0
        public void Base_Path_Null_Should_Throw_Exception()
        {
            string basePath = null;
            Uri    baseUri  = null;

            Assert.Throws <ArgumentNullException>(() => UrlCombine.Combine(basePath, "relative/path"));
            Assert.Throws <ArgumentNullException>(() => basePath.CombineUrl("relative/path"));
            Assert.Throws <ArgumentNullException>(() => baseUri.Combine("relative/path"));
        }
        private Uri GetAosRequestUri(string requestRelativePath)
               
        {
            var aosUrl = UrlCombine.Combine(_settings.AosUri, requestRelativePath);
            var aosUri = new Uri(aosUrl);

                                return(aosUri);

                   
        }
Пример #9
0
        public void Base_Path_Null_Should_Throw_Exception_At_Combine_With_Params()
        {
            var    relativePaths = new string[] { "john", "hathorne" };
            string basePath      = null;
            Uri    baseUri       = null;

            Assert.Throws <ArgumentNullException>(() => UrlCombine.Combine(basePath, relativePaths));
            Assert.Throws <ArgumentNullException>(() => basePath.CombineUrl(relativePaths));
            Assert.Throws <ArgumentNullException>(() => baseUri.Combine(relativePaths));
        }
Пример #10
0
        public void One_Base_Path_Should_Be_Combined_With_Relative_Path(string url1, string url2, string expected)
        {
            var actualStatic          = UrlCombine.Combine(url1, url2);
            var actualUriExtension    = new Uri(url1).Combine(url2).ToString();
            var actualStringExtension = url1.CombineUrl(url2);

            Assert.Equal(expected, actualStatic);
            Assert.Equal(expected, actualUriExtension);
            Assert.Equal(expected, actualStringExtension);
        }
Пример #11
0
        public static Uri ConstructUri(string path)
        {
            var url        = UrlCombine.Combine(Constants.UrlResourceBase, path);
            var tokenParam = new Dictionary <string, string>
            {
                { Constants.UrlParamToken, Constants.Token }
            };
            var finalUrl = new Uri(QueryHelpers.AddQueryString(url, tokenParam));

            return(finalUrl);
        }
Пример #12
0
        public void Combine_With_Params_Should_Merge_Urls_Correctly(string baseUrl, string relativePathsRaw, string expected)
        {
            var relativePaths = relativePathsRaw.Split('#');

            var urlStatic         = UrlCombine.Combine(baseUrl, relativePaths);
            var urlUriExtension   = new Uri(baseUrl).Combine(relativePaths).ToString();
            var urlStringExtesion = baseUrl.CombineUrl(relativePaths);

            Assert.Equal(urlStatic, expected);
            Assert.Equal(urlUriExtension, expected);
            Assert.Equal(urlStringExtesion, expected);
        }
Пример #13
0
        public void Combine_Should_Ignore_Empty_Spaces_And_Empty_Slashes(string baseUrl, string relativePathsRaw, string expected)
        {
            var relativePaths = relativePathsRaw.Split('#');

            var urlStatic         = UrlCombine.Combine(baseUrl, relativePaths);
            var urlUriExtension   = new Uri(baseUrl).Combine(relativePaths).ToString();
            var urlStringExtesion = baseUrl.CombineUrl(relativePaths);

            Assert.Equal(urlStatic, expected);
            Assert.Equal(urlUriExtension, expected);
            Assert.Equal(urlStringExtesion, expected);
        }
Пример #14
0
        public async Task <IActionResult> IdPMetadataAsync(string partyId)
        {
            logger.ScopeTrace(() => "Down, IdP Metadata request.");
            logger.SetScopeProperty(Constants.Logs.DownPartyId, partyId);
            var party = RouteBinding.DownParty != null ? await tenantRepository.GetAsync <SamlDownParty>(partyId) : null;

            var signMetadata = party != null ? party.SignMetadata : false;

            var samlConfig = await saml2ConfigurationLogic.GetSamlDownConfigAsync(party, includeSigningCertificate : signMetadata, includeSignatureValidationCertificates : false);

            var authnDestination  = new Uri(UrlCombine.Combine(HttpContext.GetHostWithTenantAndTrack(), RouteBinding.PartyNameAndBinding, Constants.Routes.SamlController, Constants.Endpoints.SamlAuthn));
            var logoutDestination = new Uri(UrlCombine.Combine(HttpContext.GetHostWithTenantAndTrack(), RouteBinding.PartyNameAndBinding, Constants.Routes.SamlController, Constants.Endpoints.SamlLogout));

            var entityDescriptor = new EntityDescriptor(samlConfig, signMetadata);

            if (party != null)
            {
                entityDescriptor.ValidUntil = new TimeSpan(0, 0, settings.SamlMetadataLifetime).Days;
            }

            var trackCertificates = GetTrackCertificates();

            entityDescriptor.IdPSsoDescriptor = new IdPSsoDescriptor
            {
                SigningCertificates = trackCertificates,
                //EncryptionCertificates = trackCertificates,
                SingleSignOnServices = new SingleSignOnService[]
                {
                    new SingleSignOnService {
                        Binding = ToSamleBindingUri(party?.AuthnBinding?.RequestBinding), Location = authnDestination
                    },
                },
            };
            entityDescriptor.IdPSsoDescriptor.SingleLogoutServices = new SingleLogoutService[]
            {
                new SingleLogoutService {
                    Binding = ToSamleBindingUri(party?.LogoutBinding?.RequestBinding), Location = logoutDestination
                },
            };

            if (party?.MetadataNameIdFormats?.Count > 0)
            {
                entityDescriptor.IdPSsoDescriptor.NameIDFormats = party.MetadataNameIdFormats.Select(nf => new Uri(nf));
            }

            if (party?.MetadataContactPersons?.Count() > 0)
            {
                entityDescriptor.ContactPersons = GetContactPersons(party.MetadataContactPersons);
            }

            return(new Saml2Metadata(entityDescriptor).CreateMetadata().ToActionResult());
        }
Пример #15
0
        public static string GetHostWithTenantAndTrack(this HttpContext context)
        {
            var routeBinding = context.GetRouteBinding();

            if (!routeBinding.HasCustomDomain)
            {
                return(UrlCombine.Combine(context.GetHost(), routeBinding.TenantName, routeBinding.TrackName));
            }
            else
            {
                return(UrlCombine.Combine(context.GetHost(), routeBinding.TrackName));
            }
        }
Пример #16
0
        public void Base_Path_With_No_Relative_Should_Return_Base_Path()
        {
            string nullString = null;
            var    expected   = "http://www.google.com.br/";

            var actualStatic          = UrlCombine.Combine(expected, nullString);
            var actualUriExtension    = new Uri(expected).Combine(nullString).ToString();
            var actualStringExtension = expected.CombineUrl(nullString);

            Assert.Equal(expected, actualStatic);
            Assert.Equal(expected, actualUriExtension);
            Assert.Equal(expected, actualStringExtension);
        }
Пример #17
0
        protected override string MapPath(string path)
        {
            if (path.EndsWith(IdentityConstants.OidcDiscovery.Path, StringComparison.InvariantCultureIgnoreCase))
            {
                return(path.Replace(IdentityConstants.OidcDiscovery.Path, UrlCombine.Combine(Constants.Routes.OidcDiscoveryController, Constants.Routes.OidcDiscoveryAction), StringComparison.InvariantCultureIgnoreCase));
            }
            else if (path.EndsWith(IdentityConstants.OidcDiscovery.Keys, StringComparison.InvariantCultureIgnoreCase))
            {
                return(path.Replace(UrlCombine.Combine(IdentityConstants.OidcDiscovery.Path, IdentityConstants.OidcDiscovery.Keys), UrlCombine.Combine(Constants.Routes.OidcDiscoveryController, Constants.Routes.OidcDiscoveryKeyAction), StringComparison.InvariantCultureIgnoreCase));
            }

            return(path);
        }
Пример #18
0
        private async Task CreateAspNetCoreSamlSampleDownPartyAsync()
        {
            Func <string, Task> getAction = async(name) =>
            {
                _ = await foxIDsApiClient.GetSamlDownPartyAsync(name);
            };

            Func <string, Task> postAction = async(name) =>
            {
                var baseUrl = "https://localhost:44343";

                var samlUpParty = new SamlDownParty
                {
                    Name              = name,
                    Issuer            = "urn:itfoxtec:idservice:samples:aspnetcoresamlsample",
                    AllowUpPartyNames = new[] { loginName, aspNetCoreSamlIdPSampleUpPartyName, identityserverOidcOpUpPartyName /*, "foxids_oidcpkce", "adfs_saml_idp"*/ },
                    Keys              = new[]
                    {
                        new JsonWebKey
                        {
                            Kty = "RSA",
                            Kid = "3863A8A752E5D6B812AA8A78A656E2DE6C637D12",
                            X5c = new[] { "MIICzzCCAbegAwIBAgIJAOd44ujQLBp/MA0GCSqGSIb3DQEBCwUAMBkxFzAVBgNVBAMTDnRlc3Qtc2lnbi1jZXJ0MB4XDTE4MTAwOTA4NTMxOFoXDTE5MTAxMDA4NTMxOFowGTEXMBUGA1UEAxMOdGVzdC1zaWduLWNlcnQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDCbttrAY2VkISBs/dQW9B38dvO1++Pcqqlj0darBfq8+1f+nRsn0OcQOYAhMvPhuS7qy5NLaTFm8RbH3veybYm7cJFU6xGu8SiLv6rPa5CBrSTgL/sJ+NwIDG3ZaZbayKTqgf31D1Gv8mIOWtEVHOn9ZPvfO6r0I9tLMZtJASHDTxe7niskT2PEfGe1KBTXVgJqY67KttzlydvH4zN+lwXFguBKLQqicw9iJ9BngxDAMLkOz6SIeF5WFGRPfiLD/MOZQ/skb+1H9Bl+5mbL/F0TiVs1HaQNEt3N9SO18dRyA2ZGtGfTzJbx3gQ7RwRjmNMnK8In9M0jxZZ1Rvji2XFAgMBAAGjGjAYMAkGA1UdEwQCMAAwCwYDVR0PBAQDAgXgMA0GCSqGSIb3DQEBCwUAA4IBAQC5RtTJV7mONXWKFkmF8EnCfPbFemCZs7Usw4cicjWlPTPfneFTsSJ4NuFmpWYrf1Lr75cf9BjHZDVHDGrRTsou/wAuqSehRPlZyj35ysjrC1hNmFYKQU+WkulxE4BZIcD+3fKj+6WAPVGG0NMnKWrmie2XK0aM5nFrWST4xqk6V5+4DOT7lltmPs9eUDJ8wkIL1oP/mhsE7tKpqMk9qNCb5nZMwXhqoTnlqTw/DFDCPJV/CS20/PamGTVUUhW1I0r73QDv054ycFY0ijU3tUK2V4D3daFTBHVGlLsCUxSBJSWkTGieN+iyU5aNbCErBc0+cim79lXT6sZ8VPVJ+kdW" },
                            X5t = "OGOop1Ll1rgSqop4plbi3mxjfRI",
                            N   = "wm7bawGNlZCEgbP3UFvQd_Hbztfvj3KqpY9HWqwX6vPtX_p0bJ9DnEDmAITLz4bku6suTS2kxZvEWx973sm2Ju3CRVOsRrvEoi7-qz2uQga0k4C_7CfjcCAxt2WmW2sik6oH99Q9Rr_JiDlrRFRzp_WT73zuq9CPbSzGbSQEhw08Xu54rJE9jxHxntSgU11YCamOuyrbc5cnbx-MzfpcFxYLgSi0KonMPYifQZ4MQwDC5Ds-kiHheVhRkT34iw_zDmUP7JG_tR_QZfuZmy_xdE4lbNR2kDRLdzfUjtfHUcgNmRrRn08yW8d4EO0cEY5jTJyvCJ_TNI8WWdUb44tlxQ",
                            E   = "AQAB"
                        }
                    },
                    SignatureAlgorithm        = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256",
                    CertificateValidationMode = X509CertificateValidationMode.None,
                    RevocationMode            = X509RevocationMode.NoCheck,
                    AuthnBinding = new SamlBinding {
                        RequestBinding = SamlBindingTypes.Redirect, ResponseBinding = SamlBindingTypes.Post
                    },
                    AcsUrls       = new[] { UrlCombine.Combine(baseUrl, "saml/assertionconsumerservice") },
                    LogoutBinding = new SamlBinding {
                        RequestBinding = SamlBindingTypes.Post, ResponseBinding = SamlBindingTypes.Post
                    },
                    SingleLogoutUrl             = UrlCombine.Combine(baseUrl, "saml/singlelogout"),
                    LoggedOutUrl                = UrlCombine.Combine(baseUrl, "saml/loggedout"),
                    Claims                      = new string[] { ClaimTypes.Email, ClaimTypes.Name, ClaimTypes.GivenName, ClaimTypes.Surname, ClaimTypes.Role },
                    MetadataLifetime            = 1728000, // 20 days
                    SubjectConfirmationLifetime = 300,     // 5 minutes
                    IssuedTokenLifetime         = 36000    // 10 hours
                };

                await foxIDsApiClient.PostSamlDownPartyAsync(samlUpParty);
            };

            await CreateIfNotExistsAsync(aspNetCoreSamlSampleDownPartyName, getAction, postAction);
        }
        /// <summary>
        /// Gets file download acknowledgement request Uri
        /// </summary>
        /// <returns>
        /// File download acknowledgement request Uri
        /// </returns>
        public Uri GetAckUri()
        {
            var downloadSettings = _settings as DownloadJobSettings;
            var ackUri           = new UriBuilder(GetAosRequestUri(UrlCombine.Combine(ConnectorApiActions.AckPath, downloadSettings.ActivityId.ToString()))).Uri;

            if (_settings.LogVerbose || Log.IsDebugEnabled)
            {
                Log.Debug($@"Job: {_settings.JobKey}. HttpClientHelper.GetAckUri is being called.
Output:

Generated Uri: {ackUri.AbsoluteUri}");
            }
            return(ackUri);
        }
Пример #20
0
        internal static Dependency CreateDependency(FileInfo file, ApplicationType application, bool isLauncherExecutable = false)
        {
            var dependency = new Dependency();

            dependency.Name = file.Name;
            var destination = isLauncherExecutable ? LauncherConstants.ExecutablePathVariable : LauncherConstants.ApplicationBaseVariable;

            dependency.Destination = $"%{destination}%";
            dependency.Version     = FileVersionInfo.GetVersionInfo(file.FullName).FileVersion;
            dependency.Sha2        = FileHashHelper.GetFileHash(file.FullName, FileHashHelper.HashType.Sha256);
            dependency.Size        = file.Length;
            dependency.Origin      = UrlCombine.Combine(Program.LaunchOptions.OriginPathRoot, application.ToString(), file.Name);
            Logger.Debug($"Dependency created: {dependency}");
            return(dependency);
        }
Пример #21
0
        private static void AddInfrastructure(ServiceCollection services)
        {
            services.AddHttpClient();

            services.AddTransient <IHttpContextAccessor, HttpContextAccessorSeedHelper>();

            services.AddTransient <TokenHelper>();
            services.AddSingleton(serviceProvider =>
            {
                var settings          = serviceProvider.GetService <SeedSettings>();
                var httpClientFactory = serviceProvider.GetService <IHttpClientFactory>();

                return(new OidcDiscoveryHandler(httpClientFactory, UrlCombine.Combine(settings.Authority, IdentityConstants.OidcDiscovery.Path)));
            });
        }
Пример #22
0
        public static string GetUpPartyUrl(this HttpContext httpContext, string upPartyName, string controller, string action = null, bool includeSequence = false, PartyBindingPatterns partyBindingPattern = PartyBindingPatterns.Brackets)
        {
            var elements = new List <string> {
                upPartyName.ToUpPartyBinding(partyBindingPattern), controller
            };

            if (!action.IsNullOrEmpty())
            {
                elements.Add(action);
            }
            if (includeSequence)
            {
                elements.Add($"_{httpContext.GetSequenceString()}");
            }
            return(UrlCombine.Combine(httpContext.GetHostWithTenantAndTrack(), elements.ToArray()));
        }
Пример #23
0
        public async Task <IActionResult> SpMetadataAsync(string partyId)
        {
            logger.ScopeTrace("Up, SP Metadata request.");
            logger.SetScopeProperty("upPartyId", partyId);
            var party = await tenantRepository.GetAsync <SamlUpParty>(partyId);

            var samlConfig = saml2ConfigurationLogic.GetSamlUpConfig(party, true);

            var acsDestination                  = new Uri(UrlCombine.Combine(HttpContext.GetHost(), RouteBinding.TenantName, RouteBinding.TrackName, RouteBinding.PartyNameAndBinding, Constants.Routes.SamlController, Constants.Endpoints.SamlAcs));
            var singleLogoutDestination         = new Uri(UrlCombine.Combine(HttpContext.GetHost(), RouteBinding.TenantName, RouteBinding.TrackName, RouteBinding.PartyNameAndBinding, Constants.Routes.SamlController, Constants.Endpoints.SamlSingleLogout));
            var singleLogoutResponseDestination = new Uri(UrlCombine.Combine(HttpContext.GetHost(), RouteBinding.TenantName, RouteBinding.TrackName, RouteBinding.PartyNameAndBinding, Constants.Routes.SamlController, Constants.Endpoints.SamlLoggedOut));

            var entityDescriptor = new EntityDescriptor(samlConfig);

            entityDescriptor.ValidUntil      = new TimeSpan(0, 0, party.MetadataLifetime).Days;
            entityDescriptor.SPSsoDescriptor = new SPSsoDescriptor
            {
                //AuthnRequestsSigned = true,
                //WantAssertionsSigned = true,
                SigningCertificates = new X509Certificate2[]
                {
                    samlConfig.SigningCertificate
                },
                //EncryptionCertificates = new X509Certificate2[]
                //{
                //    config.DecryptionCertificate
                //},
                AssertionConsumerServices = new AssertionConsumerService[]
                {
                    new AssertionConsumerService {
                        Binding = ToSamleBindingUri(party.AuthnBinding.ResponseBinding), Location = acsDestination,
                    },
                },
            };
            if (party.LogoutBinding != null)
            {
                entityDescriptor.SPSsoDescriptor.SingleLogoutServices = new SingleLogoutService[]
                {
                    new SingleLogoutService {
                        Binding = ToSamleBindingUri(party.LogoutBinding.ResponseBinding), Location = singleLogoutDestination, ResponseLocation = singleLogoutResponseDestination
                    },
                };
            }

            return(new Saml2Metadata(entityDescriptor).CreateMetadata().ToActionResult());
        }
        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);
        }
Пример #25
0
        private async Task CreateAspNetCoreSamlIdPSampleUpPartyAsync()
        {
            Func <string, Task> getAction = async(name) =>
            {
                _ = await foxIDsApiClient.GetSamlUpPartyAsync(name);
            };

            Func <string, Task> postAction = async(name) =>
            {
                var baseUrl = "https://localhost:44342";

                var samlUpParty = new SamlUpParty
                {
                    Name   = name,
                    Issuer = "urn:itfoxtec:idservice:samples:aspnetcoresamlidpsample",
                    Keys   = new[]
                    {
                        new JsonWebKey
                        {
                            Kty = "RSA",
                            Kid = "27EB823D00B02FA7A02AA754146B6CFC60B8C301",
                            X5c = new[] { "MIICzzCCAbegAwIBAgIJANht5lyL71T0MA0GCSqGSIb3DQEBCwUAMBkxFzAVBgNVBAMTDnRlc3Qtc2lnbi1jZXJ0MB4XDTE4MTAxMTE1MDEyMVoXDTE5MTAxMjE1MDEyMVowGTEXMBUGA1UEAxMOdGVzdC1zaWduLWNlcnQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDUf6b4mtamR7DvTdtz6fdtEe+aXHpzXqvTrjf3SbN5Hol+kAvrIGVXcnJJSfO6N9yC/s8fPE4crVJKwceGkeykzt/j0UHRafmX7e7zzCPO8nd8pVSwZtflogNVdYbrIPTIHLP/eOrPt4Im2PHU0Q561frZjIDgqaoGmtpTLof/0z3GoD52hesZyeE3mW9Q0/+TngLne52rmDe9gmebtmckM7wJw9DXbaJhI24KZPn25PRYnPJMuyBh2EFjJ6qjIAQodpaMstdH6eGJyTan9J/yI6yPhYZ3jl4UngwZ7OpSiGB7m335SYIpPRGxZSdN/tGGdVPV1TIyBU6QFD5mn259AgMBAAGjGjAYMAkGA1UdEwQCMAAwCwYDVR0PBAQDAgXgMA0GCSqGSIb3DQEBCwUAA4IBAQCCYJoiq4sVqTyJ5md4VJIvT3Ezoo6MUDxPmC+bcdT+4j0rYPJr69Fv7celEcS7NEnDK3JQXU2bJ1HAAExBz53bqZphlFnuDFQcJU2lYGaOamDUN/v2aEM/g/Zrlbs4/V4WsCETUkcq7FwmtVia58AZSOtBEqpS7OpdEq4WUmWPRqpjDn+Ne1n921qIKMDtczqOCGc/BREbFUjy49gY/+a57WUxXPhL0gWrGHBwSLIJHp/m9sG7wFA6a2wnvgycrAMYFZ50iGe6IcSzktRdQXd5lTeVtl4JgftwIplIqWyuTYoHwTX+xo2qMSMCF38w31j6BASAmXJniKWeK8aeQ9o7" },
                            X5t = "J-uCPQCwL6egKqdUFGts_GC4wwE",
                            N   = "1H-m-JrWpkew703bc-n3bRHvmlx6c16r064390mzeR6JfpAL6yBlV3JySUnzujfcgv7PHzxOHK1SSsHHhpHspM7f49FB0Wn5l-3u88wjzvJ3fKVUsGbX5aIDVXWG6yD0yByz_3jqz7eCJtjx1NEOetX62YyA4KmqBpraUy6H_9M9xqA-doXrGcnhN5lvUNP_k54C53udq5g3vYJnm7ZnJDO8CcPQ122iYSNuCmT59uT0WJzyTLsgYdhBYyeqoyAEKHaWjLLXR-nhick2p_Sf8iOsj4WGd45eFJ4MGezqUohge5t9-UmCKT0RsWUnTf7RhnVT1dUyMgVOkBQ-Zp9ufQ",
                            E   = "AQAB"
                        }
                    },
                    //SignatureAlgorithm = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256",
                    //CertificateValidationMode = X509CertificateValidationMode.None,
                    //RevocationMode = X509RevocationMode.NoCheck,
                    AuthnBinding = new SamlBinding {
                        RequestBinding = SamlBindingTypes.Redirect, ResponseBinding = SamlBindingTypes.Post
                    },
                    AuthnUrl      = UrlCombine.Combine(baseUrl, "saml/login"),
                    LogoutBinding = new SamlBinding {
                        RequestBinding = SamlBindingTypes.Post, ResponseBinding = SamlBindingTypes.Post
                    },
                    LogoutUrl = UrlCombine.Combine(baseUrl, "saml/logout"),
                    Claims    = new string[] { ClaimTypes.Email, ClaimTypes.Name, ClaimTypes.GivenName, ClaimTypes.Surname, ClaimTypes.Role }
                };

                await foxIDsApiClient.PostSamlUpPartyAsync(samlUpParty);
            };

            await CreateIfNotExistsAsync(aspNetCoreSamlIdPSampleUpPartyName, getAction, postAction);
        }
Пример #26
0
        /// <summary>
        /// Sets authorization header.
        /// </summary>
        /// <returns>Authorization header</returns>
        private async Task <string> AuthorizationHeader()
        {
            if (!string.IsNullOrEmpty(_authorizationHeader) && (DateTime.UtcNow.AddSeconds(60) < AuthenticationResult.ExpiresOn))
            {
                return(_authorizationHeader);
            }
            IConfidentialClientApplication appConfidential;
            IPublicClientApplication       appPublic;
            var    aosUriAuthUri = new Uri(_settings.AosUri);
            string authority     = UrlCombine.Combine(_settings.AzureAuthEndpoint, _settings.AadTenant);

            string[] scopes = new string[] { UrlCombine.Combine(aosUriAuthUri.AbsoluteUri, ".default") };

            if (_settings.UseServiceAuthentication)
            {
                appConfidential = ConfidentialClientApplicationBuilder.Create(_settings.AadClientId.ToString())
                                  .WithClientSecret(_settings.AadClientSecret)
                                  .WithAuthority(authority)
                                  .Build();
                AuthenticationResult = await appConfidential.AcquireTokenForClient(scopes).ExecuteAsync();
            }
            else
            {
                appPublic = PublicClientApplicationBuilder.Create(_settings.AadClientId.ToString())
                            .WithAuthority(authority)
                            .Build();
                var accounts = await appPublic.GetAccountsAsync();

                if (accounts.Any())
                {
                    AuthenticationResult = await appPublic.AcquireTokenSilent(scopes, accounts.FirstOrDefault()).ExecuteAsync();
                }
                else
                {
                    using var securePassword = new SecureString();
                    foreach (char c in _settings.UserPassword)
                    {
                        securePassword.AppendChar(c);
                    }
                    AuthenticationResult = await appPublic.AcquireTokenByUsernamePassword(scopes, _settings.UserName, securePassword).ExecuteAsync();
                }
            }
            return(_authorizationHeader = AuthenticationResult.CreateAuthorizationHeader());
        }
Пример #27
0
        public async Task SendConfirmationEmailAsync(User user)
        {
            logger.ScopeTrace($"Send confirmation email to '{user.Email}' for user id '{user.UserId}'.");
            if (user == null || user.DisableAccount)
            {
                throw new ConfirmationException($"User with email '{user.Email}' do not exists or is disabled.");
            }
            if (user.EmailVerified)
            {
                logger.ScopeTrace($"User is confirmed, email '{user.Email}' and id '{user.UserId}'.");
                return;
            }

            var db  = redisConnectionMultiplexer.GetDatabase();
            var key = ConfirmationEmailWaitPeriodRadisKey(user.Email);

            if (await db.KeyExistsAsync(key))
            {
                logger.ScopeTrace($"User confirmation wait period, email '{user.Email}' and id '{user.UserId}'.");
                return;
            }
            else
            {
                await db.StringSetAsync(key, true, TimeSpan.FromSeconds(settings.ConfirmationEmailWaitPeriod));
            }

            (var separateSequenceString, var separateSequence) = await sequenceLogic.StartSeparateSequenceAsync(accountAction : true, currentSequence : Sequence, requireeUiUpPartyId : true);

            await sequenceLogic.SaveSequenceDataAsync(new ConfirmationSequenceData
            {
                Email = user.Email
            }, separateSequence);

            var confirmationUrl = UrlCombine.Combine(HttpContext.GetHost(), $"{RouteBinding.TenantName}/{RouteBinding.TrackName}/({RouteBinding.UpParty.Name})/action/confirmation/_{separateSequenceString}");
            await sendEmailLogic.SendEmailAsync(new MailAddress(user.Email, GetDisplayName(user)),
                                                localizer["Please confirm your email address"],
                                                localizer["<h2 style='margin-bottom:30px;font-weight:300;line-height:1.5;font-size:24px'>Please confirm your email address</h2><p style='margin-bottom:30px'>By clicking on this <a href='{0}'>link</a>, you are confirming your email address.</p>", confirmationUrl]);

            logger.ScopeTrace($"Confirmation send to '{user.Email}' for user id '{user.UserId}'.", triggerEvent: true);
        }
Пример #28
0
        public IActionResult Metadata()
        {
            var defaultSite = $"{Request.Scheme}://{Request.Host.ToUriComponent()}/";

            var entityDescriptor = new EntityDescriptor(saml2Config);

            entityDescriptor.ValidUntil       = 365;
            entityDescriptor.IdPSsoDescriptor = new IdPSsoDescriptor
            {
                SigningCertificates = new X509Certificate2[]
                {
                    saml2Config.SigningCertificate
                },
                //EncryptionCertificates = new X509Certificate2[]
                //{
                //    saml2Config.DecryptionCertificate
                //},
                SingleSignOnServices = new SingleSignOnService[]
                {
                    new SingleSignOnService {
                        Binding = ProtocolBindings.HttpRedirect, Location = new Uri(UrlCombine.Combine(defaultSite, "/Saml/Login"))
                    }
                },
                SingleLogoutServices = new SingleLogoutService[]
                {
                    new SingleLogoutService {
                        Binding = ProtocolBindings.HttpPost, Location = new Uri(UrlCombine.Combine(defaultSite, "/Saml/Logout"))
                    }
                },
                NameIDFormats = new Uri[] { NameIdentifierFormats.X509SubjectName },
            };
            entityDescriptor.ContactPersons = new [] {
                new ContactPerson(ContactTypes.Administrative)
                {
                    Company = "Some sample IdP",
                }
            };
            return(new Saml2Metadata(entityDescriptor).CreateMetadata().ToActionResult());
        }
        /// <summary>
        /// Gets data job status request URI
        /// </summary>
        /// <param name="jobId">The job identifier.</param>
        /// <returns>
        /// Data job status URI
        /// </returns>
        public Uri GetJobStatusUri(string jobId)
        {
            var processingJobSettings = _settings as ProcessingJobSettings;
            var jobStatusUri          = new UriBuilder(GetAosRequestUri(UrlCombine.Combine(ConnectorApiActions.JobStatusPath, processingJobSettings.ActivityId.ToString())))
            {
                Query = "jobId=" + jobId.Replace(@"""", "")
            };

            if (_settings.LogVerbose || Log.IsDebugEnabled)
            {
                Log.Debug($@"Job: {_settings.JobKey}. HttpClientHelper.GetJobStatusUri is being called.
Parameters:

jobId: {jobId}

Output:

Generated uri: {jobStatusUri.Uri.AbsoluteUri}
Generated query: {jobStatusUri.Query}");
            }
            return(jobStatusUri.Uri);
        }
        /// <summary>
        /// Gets data job enqueue request Uri
        /// </summary>
        /// <returns>
        /// Data job enqueue request Uri
        /// </returns>
        public Uri GetEnqueueUri(string legalEntity = null)
        {
            var uploadSettings = _settings as UploadJobSettings;
            var enqueueUri     = new UriBuilder(GetAosRequestUri(UrlCombine.Combine(ConnectorApiActions.EnqueuePath, uploadSettings.ActivityId.ToString())));
            var query          = HttpUtility.ParseQueryString(enqueueUri.Query);

            if (!string.IsNullOrEmpty(legalEntity))
            {
                query["company"] = legalEntity;
            }
            else
            {
                if (!string.IsNullOrEmpty(uploadSettings.Company))
                {
                    query["company"] = uploadSettings.Company;
                }
            }

            if (!uploadSettings.IsDataPackage)// Individual file
            {
                // entity name is required
                query["entity"] = uploadSettings.EntityName;
            }
            if (_settings.LogVerbose || Log.IsDebugEnabled)
            {
                Log.Debug($@"Job: {_settings.JobKey}. HttpClientHelper.GetEnqueueUri is being called.
Parameters:

legalEntity: {legalEntity}

Output:

Generated Uri: {enqueueUri.Uri.AbsoluteUri}
Generated query: {enqueueUri.Query}");
            }
            enqueueUri.Query = query.ToString();
            return(enqueueUri.Uri);
        }