示例#1
0
        public void End2End_OpenIdConnect()
        {
            SigningCredentials rsaSigningCredentials =
                new SigningCredentials(
                    KeyingMaterial.RsaSecurityKey_Private2048,
                    SecurityAlgorithms.RsaSha1Signature,
                    SecurityAlgorithms.Sha256Digest,
                    new SecurityKeyIdentifier(new NamedKeySecurityKeyIdentifierClause("kid", "NGTFvdK-fythEuLwjpwAJOM9n-A"))
                    );

            //"<RSAKeyValue><Modulus>rCz8Sn3GGXmikH2MdTeGY1D711EORX/lVXpr+ecGgqfUWF8MPB07XkYuJ54DAuYT318+2XrzMjOtqkT94VkXmxv6dFGhG8YZ8vNMPd4tdj9c0lpvWQdqXtL1TlFRpD/P6UMEigfN0c9oWDg9U7Ilymgei0UXtf1gtcQbc5sSQU0S4vr9YJp2gLFIGK11Iqg4XSGdcI0QWLLkkC6cBukhVnd6BCYbLjTYy3fNs4DzNdemJlxGl8sLexFytBF6YApvSdus3nFXaMCtBGx16HzkK9ne3lobAwL2o79bP4imEGqg+ibvyNmbrwFGnQrBc1jTF9LyQX9q+louxVfHs6ZiVw==</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>"
            RSA rsa = KeyingMaterial.RsaSecurityKey_2048.GetAsymmetricAlgorithm(SecurityAlgorithms.RsaSha1Signature, false) as RSA;
            OpenIdConnectConfiguration configuration = OpenIdConnectConfigurationRetriever.GetAsync(OpenIdConfigData.OpenIdConnectMetadataFile, CancellationToken.None).Result;
            JwtSecurityTokenHandler    tokenHandler  = new JwtSecurityTokenHandler();
            JwtSecurityToken           jwt           = tokenHandler.CreateToken(
                configuration.Issuer,
                IdentityUtilities.DefaultAudience,
                IdentityUtilities.DefaultClaimsIdentity,
                DateTime.UtcNow,
                DateTime.UtcNow + TimeSpan.FromHours(1),
                rsaSigningCredentials);

            TokenValidationParameters validationParameters =
                new TokenValidationParameters
            {
                IssuerSigningTokens = configuration.SigningTokens,
                ValidAudience       = IdentityUtilities.DefaultAudience,
                ValidIssuer         = configuration.Issuer,
            };

            SecurityToken securityToken = null;

            tokenHandler.ValidateToken(jwt.RawData, validationParameters, out securityToken);
        }
示例#2
0
        async static Task <JwtSecurityToken> Validate(string token)
        {
            string stsDiscoveryEndpoint = "https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration";

            ConfigurationManager <OpenIdConnectConfiguration> configManager = new ConfigurationManager <OpenIdConnectConfiguration>(stsDiscoveryEndpoint, new OpenIdConnectConfigurationRetriever());
            OpenIdConnectConfiguration config = configManager.GetConfigurationAsync().Result;
            var openidConfiguration           = await OpenIdConnectConfigurationRetriever.GetAsync(stsDiscoveryEndpoint, CancellationToken.None);

            TokenValidationParameters validationParameters = new TokenValidationParameters
            {
                ValidateAudience  = false,
                ValidateIssuer    = false,
                IssuerSigningKeys = openidConfiguration.SigningKeys,
                ValidateLifetime  = true,
                LifetimeValidator = CustomLifetimeValidator,
            };

            JwtSecurityTokenHandler tokendHandler = new JwtSecurityTokenHandler();

            SecurityToken jwt;

            var result = tokendHandler.ValidateToken(token, validationParameters, out jwt);

            return(jwt as JwtSecurityToken);
        }
示例#3
0
        public static async Task InitAsync(string metaDataUrl, string issuer, string audience)
        {
            var openIdConfigurationRetriever = new OpenIdConnectConfigurationRetriever();

            _configurationManager = new ConfigurationManager <OpenIdConnectConfiguration>(metaDataUrl, openIdConfigurationRetriever)
            {
                AutomaticRefreshInterval = new TimeSpan(0, 15, 0),
                RefreshInterval          = new TimeSpan(0, 15, 0),
            };

            var openIdConnectConfiguration = await _configurationManager.GetConfigurationAsync();

            TokenValidationParameters = new TokenValidationParameters()
            {
                ValidIssuer              = issuer,
                ValidAudience            = audience,
                IssuerSigningKeys        = openIdConnectConfiguration.SigningKeys,
                ValidateIssuer           = true,
                ValidateAudience         = true,
                ValidateIssuerSigningKey = true,
                ValidateLifetime         = true,
                ValidateTokenReplay      = true,
                ValidateActor            = true,
            };
        }
        public void OpenIdConnect()
        {
            SigningCredentials rsaSigningCredentials =
                new SigningCredentials(
                    KeyingMaterial.RsaSecurityKey_2048,
                    SecurityAlgorithms.RsaSha256Signature
                    );

            //"<RSAKeyValue><Modulus>rCz8Sn3GGXmikH2MdTeGY1D711EORX/lVXpr+ecGgqfUWF8MPB07XkYuJ54DAuYT318+2XrzMjOtqkT94VkXmxv6dFGhG8YZ8vNMPd4tdj9c0lpvWQdqXtL1TlFRpD/P6UMEigfN0c9oWDg9U7Ilymgei0UXtf1gtcQbc5sSQU0S4vr9YJp2gLFIGK11Iqg4XSGdcI0QWLLkkC6cBukhVnd6BCYbLjTYy3fNs4DzNdemJlxGl8sLexFytBF6YApvSdus3nFXaMCtBGx16HzkK9ne3lobAwL2o79bP4imEGqg+ibvyNmbrwFGnQrBc1jTF9LyQX9q+louxVfHs6ZiVw==</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>"
            OpenIdConnectConfiguration configuration = OpenIdConnectConfigurationRetriever.GetAsync(OpenIdConfigData.OpenIdConnectMetadataFileEnd2End, new FileDocumentRetriever(), CancellationToken.None).Result;
            JwtSecurityTokenHandler    tokenHandler  = new JwtSecurityTokenHandler();
            JwtSecurityToken           jwtToken      =
                tokenHandler.CreateJwtSecurityToken(
                    configuration.Issuer,
                    Default.Audience,
                    ClaimSets.DefaultClaimsIdentity,
                    DateTime.UtcNow,
                    DateTime.UtcNow + TimeSpan.FromHours(1),
                    DateTime.UtcNow + TimeSpan.FromHours(1),
                    rsaSigningCredentials);

            tokenHandler.WriteToken(jwtToken);

            TokenValidationParameters validationParameters =
                new TokenValidationParameters
            {
                IssuerSigningKeys = configuration.SigningKeys,
                ValidAudience     = Default.Audience,
                ValidIssuer       = configuration.Issuer,
            };

            SecurityToken securityToken = null;

            tokenHandler.ValidateToken(jwtToken.RawData, validationParameters, out securityToken);
        }
示例#5
0
        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllers();

            IdentityModelEventSource.ShowPII = true;

            //var openidconfig = OpenIdConnectConfigurationRetriever.GetAsync("https://login.microsoftonline.com/90f5a437-d7ed-4905-ad39-adc1f0d6b579/v2.0/.well-known/openid-configuration", CancellationToken.None).Result;
            var openidconfig = OpenIdConnectConfigurationRetriever.GetAsync("https://login.microsoftonline.com/8c9b06d0-cb4a-4a03-b449-1f5a2548a910/v2.0/.well-known/openid-configuration", CancellationToken.None).Result;

            services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
            .AddJwtBearer(options =>
            {
                options.Authority = "https://login.microsoftonline.com/8c9b06d0-cb4a-4a03-b449-1f5a2548a910/";
                options.TokenValidationParameters = new TokenValidationParameters
                {
                    ValidIssuer              = openidconfig.Issuer,
                    ValidAudience            = "https://sapnomsdevaatapiaeapp.nonprod-oms-ae-appsvcenv.appserviceenvironment.net",
                    ValidateIssuerSigningKey = true,
                    IssuerSigningKeys        = openidconfig.SigningKeys
                };
            });

            services.AddSingleton <QueueService>();
            services.AddDbContext <AATDbContext>(options =>
                                                 options.UseSqlServer(Configuration["SqlServer"]));
            services.AddApplicationInsightsTelemetry(Configuration["APPINSIGHTS_INSTRUMENTATIONKEY"]);
        }
        public async Task <OpenIdConnectConfiguration> GetConfigurationByPolicyAsync(CancellationToken cancel, string policyId)
        {
            DateTimeOffset now = DateTimeOffset.UtcNow;

            DateTimeOffset sync;

            if (!_syncAfter.TryGetValue(policyId, out sync))
            {
                sync = DateTimeOffset.MinValue;
            }

            // config is actually the same object as _currentConfiguration[policyId]
            OpenIdConnectConfiguration config;

            if (!_currentConfiguration.TryGetValue(policyId, out config))
            {
                config = null;
            }

            if (config != null && sync > now)
            {
                return(config);
            }

            await _refreshLock.WaitAsync(cancel);

            try
            {
                Exception retrieveEx = null;
                if (sync <= now)
                {
                    try
                    {
                        // We're assuming the metadata address provided in the constructor does not contain qp's
                        config = await OpenIdConnectConfigurationRetriever.GetAsync(String.Format(_metadataAddress + "?{0}={1}", policyParameter, policyId), _docRetriever, cancel);

                        _currentConfiguration[policyId] = config;
                        Contract.Assert(_currentConfiguration[policyId] != null);
                        _lastRefresh[policyId] = now;
                        _syncAfter[policyId]   = now.UtcDateTime.Add(_automaticRefreshInterval);
                    }
                    catch (Exception ex)
                    {
                        retrieveEx           = ex;
                        _syncAfter[policyId] = now.UtcDateTime.Add(_automaticRefreshInterval < _refreshInterval ? _automaticRefreshInterval : _refreshInterval);
                    }
                }

                if (config == null)
                {
                    throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, ErrorMessages.IDX10803, _metadataAddress ?? "null"), retrieveEx);
                }

                return(config);
            }
            finally
            {
                _refreshLock.Release();
            }
        }
示例#7
0
        public PolicyConfigurationManager(string metadataAddress, string[] policies, IDocumentRetriever docRetriever)
        {
            if (string.IsNullOrWhiteSpace(metadataAddress))
            {
                throw new ArgumentNullException("metadataAddress");
            }

            if (docRetriever == null)
            {
                throw new ArgumentNullException("retriever");
            }

            _metadataAddress      = metadataAddress;
            _docRetriever         = docRetriever;
            _configRetriever      = new OpenIdConnectConfigurationRetriever();
            _refreshLock          = new SemaphoreSlim(1);
            _syncAfter            = new Dictionary <string, DateTimeOffset>();
            _lastRefresh          = new Dictionary <string, DateTimeOffset>();
            _currentConfiguration = new Dictionary <string, OpenIdConnectConfiguration>();

            foreach (string policy in policies)
            {
                _currentConfiguration.Add(policy, null);
            }
        }
        /// <summary>
        /// Retrieves configuration.
        /// </summary>
        /// <param name="address"></param>
        /// <param name="retriever"></param>
        /// <param name="cancel"></param>
        /// <returns></returns>
        async Task <OpenIdConnectConfiguration> IConfigurationRetriever <OpenIdConnectConfiguration> .GetConfigurationAsync(string address, IDocumentRetriever retriever, CancellationToken cancel)
        {
            ((HttpDocumentRetriever)retriever).RequireHttps = false;
            OpenIdConnectConfiguration result = await OpenIdConnectConfigurationRetriever.GetAsync(address, retriever, cancel);

            result.AuthorizationEndpoint = _config.IdentityServer + _config.AuthorizationEndpoint;

            return(result);
        }
示例#9
0
        public OpenIdConnectCachingSecurityTokenProvider(string metadataEndpoint)
        {
            _metadataEndpoint = metadataEndpoint;

            IConfigurationRetriever<OpenIdConnectConfiguration> pConfigRetriever = new OpenIdConnectConfigurationRetriever();

            _configManager = new ConfigurationManager<OpenIdConnectConfiguration>(metadataEndpoint, pConfigRetriever);

            RetrieveMetadata();
        }
示例#10
0
 /// <inheritdoc/>
 public void RequestRefresh()
 {
     _configurations.Keys.ForEach(url =>
     {
         OpenIdConnectConfigurationRetriever.GetAsync(url, CancellationToken.None).ContinueWith(result =>
         {
             _configurations[url] = result.Result;
         });
     });
 }
示例#11
0
        /// <inheritdoc/>
        public async Task <Microsoft.IdentityModel.Protocols.OpenIdConnect.OpenIdConnectConfiguration> GetConfigurationAsync(CancellationToken cancel)
        {
            if (_configurations.ContainsKey(url))
            {
                return(_configurations[url]);
            }
            var configuration = await OpenIdConnectConfigurationRetriever.GetAsync(url, cancel);

            _configurations[url] = configuration;
            return(configuration);
        }
示例#12
0
        public PolicyConfigurationManager(IDocumentRetriever docRetriever)
        {
            if (docRetriever == null)
            {
                throw new ArgumentNullException("retriever");
            }

            _docRetriever         = docRetriever;
            _configRetriever      = new OpenIdConnectConfigurationRetriever();
            _refreshLock          = new SemaphoreSlim(1);
            _policyConfigurations = new Dictionary <string, PolicyConfiguration>();
        }
        public WsConfigurationManager(string metadataAddress, IDocumentRetriever docRetriever) : base(metadataAddress, docRetriever)
        {
            if (string.IsNullOrWhiteSpace(metadataAddress))
            {
                throw new ArgumentNullException("metadataAddress");
            }

            _metadataAddress      = metadataAddress;
            _docRetriever         = docRetriever ?? throw new ArgumentNullException("retriever");
            _configRetriever      = new OpenIdConnectConfigurationRetriever();
            _refreshLock          = new SemaphoreSlim(1);
            _syncAfter            = new Dictionary <string, DateTimeOffset>();
            _lastRefresh          = new Dictionary <string, DateTimeOffset>();
            _currentConfiguration = new Dictionary <string, OpenIdConnectConfiguration>();
        }
        private static JsonWebKey FetchAndValidateJsonWebKeyWithCommonProperties(string keysResponse)
        {
            Microsoft.IdentityModel.Protocols.OpenIdConnectConfiguration config;
            System.Threading.CancellationTokenSource src = new System.Threading.CancellationTokenSource();
            TestDocumentRetriever retriver = new TestDocumentRetriever("{\"jwks_uri\": \"secondary\"}", keysResponse);

            config = OpenIdConnectConfigurationRetriever.GetAsync("primary", retriver as IDocumentRetriever, src.Token).Result;

            Assert.IsNotNull(config.JsonWebKeySet);
            Assert.IsNotNull(config.JsonWebKeySet.Keys);
            Assert.AreEqual(1, config.JsonWebKeySet.Keys.Count);
            JsonWebKey jsonWebKey = config.JsonWebKeySet.Keys.ToList()[0];

            ValidateCommonJWKProperties(jsonWebKey);
            return(jsonWebKey);
        }
示例#15
0
        private async Task <OpenIdConnectConfiguration> GetConfigurationByPolicyAsync(PolicyConfiguration policyConfiguration, CancellationToken cancel)
        {
            DateTimeOffset now = DateTimeOffset.UtcNow;

            DateTimeOffset             sync   = policyConfiguration.SyncAfter;
            OpenIdConnectConfiguration config = policyConfiguration.Configuration;

            if (config != null && sync > now)
            {
                return(config);
            }

            await _refreshLock.WaitAsync(cancel);

            try
            {
                Exception retrieveEx = null;
                if (sync <= now)
                {
                    try
                    {
                        config = await OpenIdConnectConfigurationRetriever.GetAsync(policyConfiguration.MetadataAddress, cancel);

                        policyConfiguration.Configuration = config;
                        Contract.Assert(policyConfiguration.Configuration != null);
                        policyConfiguration.LastRefresh = now;
                        policyConfiguration.SyncAfter   = now.UtcDateTime.Add(_automaticRefreshInterval);
                    }
                    catch (Exception ex)
                    {
                        retrieveEx = ex;
                        policyConfiguration.SyncAfter = now.UtcDateTime.Add(_automaticRefreshInterval < _refreshInterval ? _automaticRefreshInterval : _refreshInterval);
                    }
                }

                if (config == null)
                {
                    throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, ErrorMessages.IDX10803, policyConfiguration.MetadataAddress ?? "null"), retrieveEx);
                }

                return(config);
            }
            finally
            {
                _refreshLock.Release();
            }
        }
示例#16
0
        public JwtTokenExtractor(TokenValidationParameters tokenValidationParameters, string metadataUrl)
        {
            // Make our own copy so we can edit it
            _tokenValidationParameters = tokenValidationParameters.Clone();

            //TODO: Проверить, может не работать
            var configRetriever = new OpenIdConnectConfigurationRetriever();

            if (!_openIdMetadataCache.ContainsKey(metadataUrl))
            {
                _openIdMetadataCache[metadataUrl] = new ConfigurationManager <OpenIdConnectConfiguration>(metadataUrl, configRetriever);
            }

            _openIdMetadata = _openIdMetadataCache[metadataUrl];

            _tokenValidationParameters.ValidateAudience    = true;
            _tokenValidationParameters.RequireSignedTokens = true;
        }
        private async Task<OpenIdConnectConfiguration> GetConfigurationAsync(string uri, ExpectedException expectedException, OpenIdConnectConfiguration expectedConfiguration, CompareContext context)
        {
            OpenIdConnectConfiguration openIdConnectConfiguration = null;
            try
            {
                openIdConnectConfiguration = await OpenIdConnectConfigurationRetriever.GetAsync(uri, new FileDocumentRetriever(), CancellationToken.None);
                expectedException.ProcessNoException(context);
            }
            catch (Exception exception)
            {
                expectedException.ProcessException(exception, context.Diffs);
            }

            if (expectedConfiguration != null)
                IdentityComparer.AreEqual(openIdConnectConfiguration, expectedConfiguration, context);

            return openIdConnectConfiguration;
        }
示例#18
0
        // Platform's Public Keys used for signing
        public static IEnumerable <SecurityKey> GetPlatformSigningKeys()
        {
            List <SecurityKey> platformSigningKeys = new List <SecurityKey>();

            // The issuer and signingKeys are cached for 24 hours. They are updated if any of the conditions in the if condition is true.
            if (DateTime.UtcNow.Subtract(_stsMetadataRetrievalTime).TotalHours > 24 || !platformSigningKeys.Any())
            {
                // Get tenant information that's used to validate incoming jwt tokens

                HttpDocumentRetriever documentRetriver = new HttpDocumentRetriever {
                    RequireHttps = true
                };
                OpenIdConnectConfigurationRetriever configRetriever             = new OpenIdConnectConfigurationRetriever();
                ConfigurationManager <OpenIdConnectConfiguration> configManager = new ConfigurationManager <OpenIdConnectConfiguration>(PlatformKeySetUrl, configRetriever, documentRetriver);

                OpenIdConnectConfiguration openIdConfig = configManager.GetConfigurationAsync(CancellationToken.None).GetAwaiter().GetResult();

                JArray platformKeys   = (JArray)openIdConfig.AdditionalData["keys"];
                string additionalData = JsonConvert.SerializeObject(openIdConfig.AdditionalData);

                JsonWebKeySet jsonWebKeySet = new JsonWebKeySet(additionalData);
                foreach (JsonWebKey key in jsonWebKeySet.Keys)
                {
                    // filter to only signing keys since there could be others
                    if (key.Use.ToLower() != "sig")
                    {
                        continue;
                    }

                    if (key.HasPrivateKey)
                    {
                        continue;
                    }

                    platformSigningKeys.Add(key);
                }

                _stsMetadataRetrievalTime = DateTime.UtcNow;
            }

            return(platformSigningKeys);
        }
        private async Task<OpenIdConnectConfiguration> GetConfigurationFromHttpAsync(string uri, ExpectedException expectedException, OpenIdConnectConfiguration expectedConfiguration = null)
        {
            OpenIdConnectConfiguration openIdConnectConfiguration = null;
            try
            {
                openIdConnectConfiguration = await OpenIdConnectConfigurationRetriever.GetAsync(uri, CancellationToken.None);
                expectedException.ProcessNoException();
            }
            catch (Exception exception)
            {
                expectedException.ProcessException(exception);
            }

            if (expectedConfiguration != null)
            {
                Assert.True(IdentityComparer.AreEqual(openIdConnectConfiguration, expectedConfiguration));
            }

            return openIdConnectConfiguration;
        }
        private async Task<OpenIdConnectConfiguration> GetConfigurationFromMixedAsync(string primaryDocument, ExpectedException expectedException, OpenIdConnectConfiguration expectedConfiguration = null)
        {
            OpenIdConnectConfiguration openIdConnectConfiguration = null;
            try
            {
                openIdConnectConfiguration = await OpenIdConnectConfigurationRetriever.GetAsync("primary",
                    new TestDocumentRetriever(primaryDocument, new FileDocumentRetriever()), CancellationToken.None);
                expectedException.ProcessNoException();
            }
            catch (Exception exception)
            {
                expectedException.ProcessException(exception);
            }

            if (expectedConfiguration != null)
            {
                Assert.True(IdentityComparer.AreEqual(openIdConnectConfiguration, expectedConfiguration));
            }

            return openIdConnectConfiguration;
        }
        public PolicyConfigurationManager(string authority, IEnumerable <string> policies)
        {
            if (string.IsNullOrEmpty(authority))
            {
                throw new ArgumentNullException(nameof(authority));
            }

            if (policies == null)
            {
                throw new ArgumentNullException(nameof(policies));
            }

            _configurationManagers = new Dictionary <string, IConfigurationManager <OpenIdConnectConfiguration> >();

            foreach (var policy in policies)
            {
                var metadataAddress        = $"{authority}/{policy}/v2.0/.well-known/openid-configuration?dc=cdm&slice=001-000";
                var configurationRetriever = new OpenIdConnectConfigurationRetriever();
                var configurationManager   = new ConfigurationManager <OpenIdConnectConfiguration>(metadataAddress, configurationRetriever);
                _configurationManagers.Add(policy.ToLowerInvariant(), configurationManager);
            }
        }
示例#22
0
        private async Task <ICollection <SecurityKey> > GetSigningKeys(string issuer)
        {
            if (_securityKeys == null)
            {
                var addSlashCharacter    = issuer.EndsWith("/") ? "" : "/";
                var stsDiscoveryEndpoint = $"{issuer}{addSlashCharacter}.well-known/openid-configuration";
                _logger.LogInformation("Downloading OpenID Configuration from {stsDiscoveryEndpoint}",
                                       stsDiscoveryEndpoint);
                var retriever     = new OpenIdConnectConfigurationRetriever();
                var configManager =
                    new ConfigurationManager <OpenIdConnectConfiguration>(stsDiscoveryEndpoint, retriever);

                var config = await configManager
                             .GetConfigurationAsync()
                             .ConfigureAwait(false);

                _logger.LogInformation("Found {count} signing keys for token signature", config.SigningKeys.Count);
                _securityKeys = config.SigningKeys;
            }

            return(_securityKeys);
        }
        public void OpenIdConnect(OpenIdConnectTheoryData theoryData)
        {
            var context = TestUtilities.WriteHeader($"{this}.OpenIdConnect", theoryData);

            try
            {
                OpenIdConnectConfiguration configuration = OpenIdConnectConfigurationRetriever.GetAsync(theoryData.OpenIdConnectMetadataFileName, new FileDocumentRetriever(), CancellationToken.None).Result;
                JwtSecurityTokenHandler    tokenHandler  = new JwtSecurityTokenHandler();
                JwtSecurityToken           jwtToken      =
                    tokenHandler.CreateJwtSecurityToken(
                        configuration.Issuer,
                        Default.Audience,
                        ClaimSets.DefaultClaimsIdentity,
                        DateTime.UtcNow,
                        DateTime.UtcNow + TimeSpan.FromHours(1),
                        DateTime.UtcNow + TimeSpan.FromHours(1),
                        theoryData.SigningCredentials);

                tokenHandler.WriteToken(jwtToken);

                TokenValidationParameters validationParameters =
                    new TokenValidationParameters
                {
                    IssuerSigningKeys = configuration.SigningKeys,
                    ValidAudience     = Default.Audience,
                    ValidIssuer       = configuration.Issuer,
                };

                tokenHandler.ValidateToken(jwtToken.RawData, validationParameters, out SecurityToken _);
                theoryData.ExpectedException.ProcessNoException(context);
            }
            catch (Exception ex)
            {
                theoryData.ExpectedException.ProcessException(ex, context);
            }

            TestUtilities.AssertFailIfErrors(context);
        }
示例#24
0
        private async Task RefreshKeysAsync(CancellationToken cancellationToken)
        {
            var config = await OpenIdConnectConfigurationRetriever.GetAsync(_openIdConfigurationEndpoint, cancellationToken);

            // Get the expiration time for the JWK set
            using (var response = await _httpClient.GetAsync(config.JwksUri, cancellationToken).ConfigureAwait(false))
            {
                if (!response.Content.Headers.TryGetValues("Expires", out var expiresValues))
                {
                    return;
                }
                if (!DateTimeOffset.TryParse(expiresValues.FirstOrDefault(), out var expiration))
                {
                    return;
                }

                lock (_accessLock)
                {
                    _keyExpiration = expiration;
                    _keys          = config.SigningKeys;
                }
            }
        }
        public PolicyConfigurationManager(string authority, IEnumerable <string> policies)
        {
            if (string.IsNullOrEmpty(authority))
            {
                throw new ArgumentNullException(nameof(authority));
            }

            if (policies == null)
            {
                throw new ArgumentNullException(nameof(policies));
            }

            foreach (var policy in policies)
            {
                var metadataAddress        = $"{authority}/{policy}/v2.0/.well-known/openid-configuration";
                var configurationRetriever = new OpenIdConnectConfigurationRetriever();
                var configurationManager   = new ConfigurationManager <OpenIdConnectConfiguration>(metadataAddress, configurationRetriever);

                if (!_configurationManagers.ContainsKey(policy.ToLowerInvariant()))
                {
                    _configurationManagers.Add(policy.ToLowerInvariant(), configurationManager);
                }
            }
        }
示例#26
0
        private async Task <bool> CanConnectUsingOpenId(Connection connection)
        {
            try
            {
                using (var source = new CancellationTokenSource())
                {
                    var discoveryUrl = new Uri(new Uri(connection.Uri), "/" + OpenIdProviderMetadataNames.Discovery);
                    var config       = await OpenIdConnectConfigurationRetriever.GetAsync(discoveryUrl.ToString(), source.Token);

                    var result = false;
                    var closed = false;

                    var authEndpoint = config.AuthorizationEndpoint +
                                       "?scope=email%20profile" +
                                       "&response_type=code" +
                                       "&redirect_uri=http://localhost:" + connection.RedirectPort +
                                       "&client_id=" + WebUtility.UrlEncode(connection.ClientId);

                    await Runtime.InvokeAsync(() =>
                    {
                        var window = new NavigationWindow()
                        {
                            WindowStartupLocation = WindowStartupLocation.CenterOwner,
                            Owner             = Application.Current?.MainWindow,
                            Title             = "Authenticate",
                            ShowsNavigationUI = false,
                            Source            = new Uri(authEndpoint),
                            Width             = 500,
                            Height            = 400
                        };

                        var listener = new HttpListener();
                        listener.Prefixes.Add($"http://*:{ connection.RedirectPort }/");
                        listener.Start();

                        listener.BeginGetContext(x =>
                        {
                            if (!listener.IsListening || closed)
                            {
                                return;
                            }

                            var context = listener.EndGetContext(x);
                            var code    = context.Request.QueryString["code"];

                            Runtime.Invoke(() =>
                            {
                                result = !string.IsNullOrWhiteSpace(code);
                                window.Close();
                            });
                        }, null);

                        window.Closed += (s, e) =>
                        {
                            closed = true;
                            listener.Stop();
                        };

                        window.ShowDialog();
                    });

                    _log.DebugFormat("OpenID connection test {0}", result ? "passed" : "failed");
                    return(await Task.FromResult(result));
                }
            }
            catch (Exception ex)
            {
                _log.Error("OpenID connection test failed", ex);
                return(await Task.FromResult(false));
            }
        }
示例#27
0
        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            //services.AddControllers();
            services.AddControllers()
            .AddNewtonsoftJson(
                options =>
                options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore
                );

            services.AddAuthorization();

            services.AddDbContext <BioDivContext>();

            //string openidConfigUrl = $"https://id.geotest.ch/auth/realms/BioDivCollector/.well-known/openid-configuration";    //and Configuration["JWT:Issuer"] https://id.geotest.ch/auth/realms/BioDivCollector
            string openidConfigUrl = Configuration["JWT:Url"] + "/auth/realms/" + Configuration["JWT:Realm"] + "/.well-known/openid-configuration";

            //Check crucial URLs
            List <string> testUrls = new List <string>()
            {
                openidConfigUrl, Configuration["JWT:Issuer"]
            };

            using (var httpClient = new HttpClient())
            {
                foreach (string testUrl in testUrls)
                {
                    int currentRetry = 0;
                    while (true)
                    {
                        try
                        {
                            var result = (httpClient.GetAsync(testUrl)).Result;
                            if (result.IsSuccessStatusCode)
                            {
                                break;
                            }
                            else
                            {
                                currentRetry++;
                            }
                            if (currentRetry > 10)
                            {
                                throw new Exception(testUrl + " not found");
                            }
                        }
                        catch (Exception ex)
                        {
                            currentRetry++;

                            if (currentRetry > 10)
                            {
                                //logger.LogError($"URL CHECK ON STARTUP: {testUrl} failed after 10 retries.");
                                Debug.WriteLine($"URL CHECK ON STARTUP: {testUrl} failed after 10 retries.");
                                throw ex;
                            }
                        }
                        int retrySeconds = 5 * currentRetry * currentRetry;
                        //logger.LogWarning($"URL CHECK ON STARTUP: {testUrl} failed. Retry in {retrySeconds}s...");
                        Debug.WriteLine($"URL CHECK ON STARTUP: {testUrl} failed. Retry in {retrySeconds}s...");
                        Thread.Sleep(TimeSpan.FromSeconds(retrySeconds));
                    }
                }
            }

            //https://developer.okta.com/blog/2018/03/23/token-authentication-aspnetcore-complete-guide
            //https://jasonwatmore.com/post/2019/10/16/aspnet-core-3-role-based-authorization-tutorial-with-example-api

            var         openidConfiguration = OpenIdConnectConfigurationRetriever.GetAsync(openidConfigUrl, CancellationToken.None);
            SecurityKey signingKey          = openidConfiguration.Result.SigningKeys.First();

            services.AddAuthentication(o =>
            {
                o.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                o.DefaultChallengeScheme    = JwtBearerDefaults.AuthenticationScheme;
            })
            .AddJwtBearer(options =>
            {
                options.RequireHttpsMetadata = true; //<<<<<<<<<<<<<<<<<<<<<<< check
                options.SaveToken            = true;

                options.TokenValidationParameters = new TokenValidationParameters
                {
                    // Clock skew compensates for server time drift.
                    // We recommend 5 minutes or less:
                    ClockSkew = TimeSpan.FromMinutes(5),
                    // Specify the key used to sign the token:
                    IssuerSigningKey         = signingKey,
                    ValidateIssuerSigningKey = true,                                    //needed?
                    RequireSignedTokens      = true,
                    // Ensure the token hasn't expired:
                    RequireExpirationTime = true,
                    ValidateLifetime      = true,
                    // Ensure the token audience matches our audience value (default true):
                    ValidateAudience = true,
                    ValidAudience    = Configuration["JWT:Audience"],
                    // Ensure the token was issued by a trusted authorization server (default true):
                    ValidateIssuer = true,
                    ValidIssuer    = Configuration["JWT:Issuer"]
                };
            });

            //https://stackoverflow.com/a/62864495/8024533
            //https://docs.microsoft.com/en-us/aspnet/core/tutorials/getting-started-with-swashbuckle?view=aspnetcore-3.1&tabs=visual-studio
            services.AddSwaggerGen(s =>
            {
                s.SwaggerDoc("v1", new OpenApiInfo
                {
                    Version     = "v1",
                    Title       = "BDC Connector API",
                    Description = "BioDivCollector Connector Documentation",
                    Contact     = new OpenApiContact
                    {
                        Name  = "Christian Baumann",
                        Email = "*****@*****.**",
                        Url   = new Uri("https://www.geotest.ch")
                    },
                    //License = new OpenApiLicense
                    //{
                    //    Name = "MIT",
                    //    Url = new Uri("")
                    //}
                });

                s.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
                {
                    Description = "JWT Authorization header using the Bearer scheme (Example: 'Bearer 12345abcdef')",
                    Name        = "Authorization",
                    In          = ParameterLocation.Header,
                    Type        = SecuritySchemeType.ApiKey,
                    Scheme      = "Bearer"
                });

                s.AddSecurityRequirement(new OpenApiSecurityRequirement
                {
                    {
                        new OpenApiSecurityScheme
                        {
                            Reference = new OpenApiReference
                            {
                                Type = ReferenceType.SecurityScheme,
                                Id   = "Bearer"
                            }
                        },
                        Array.Empty <string>()
                    }
                });

                var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
                var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
                s.IncludeXmlComments(xmlPath);
            });
        }
        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc();
            var section = Configuration.GetSection("AppOptions");

            services.Configure <AppOptions>(section);

            //TODO: implement autofac or check if possible to use assembly scan in aspnetcore DI container
            services.AddTransient <IMessageBrokerService, MessageBrokerService>();
            services.AddSingleton <IAutoMapperService, AutoMapperService>();
            services.AddSingleton <ITransportationHubOrchestrator, TransportationHubOrchestrator>();
            services.AddSingleton <IAzureActiveDirectoryService, AzureActiveDirectoryService>();
            if (!_testInProcess)
            {
                services.AddSwaggerGen(c =>
                {
                    c.SwaggerDoc("v1", new Info {
                        Title = "CDS API Gateway", Version = "v1"
                    });

                    var filePath = Path.Combine(PlatformServices.Default.Application.ApplicationBasePath,
                                                "Gateway.Service.xml");
                    c.IncludeXmlComments(filePath);
                });
            }

            var retriever     = new OpenIdConnectConfigurationRetriever();
            var configManager = new ConfigurationManager <OpenIdConnectConfiguration>(AzureMetadataAddress, retriever);
            var config        = configManager.GetConfigurationAsync().Result;

            var validIssuer = Configuration["Authentication:AzureAd:AADInstance"]
                              + Configuration["Authentication:AzureAd:TenantId"] + "/";
            var validAudienceMobile = Configuration["Authentication:AzureAd:AudienceMobile"];
            var validAudienceWeb    = Configuration["Authentication:AzureAd:AudienceWeb"];

            services.AddAuthentication(options =>
            {
                options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                options.DefaultChallengeScheme    = JwtBearerDefaults.AuthenticationScheme;
            })
            .AddJwtBearer(cfg =>
            {
                cfg.RequireHttpsMetadata = false;
                cfg.SaveToken            = true;

                cfg.TokenValidationParameters = new TokenValidationParameters
                {
                    ValidIssuer    = validIssuer,
                    ValidateIssuer = true,
                    ValidAudiences = new[]
                    {
                        validAudienceMobile, validAudienceWeb
                    },
                    ValidateAudience  = true,
                    IssuerSigningKeys = config.SigningKeys
                };
            });

            services.AddSignalR().AddRedis(options =>
            {
                options.Options.Ssl = true;
                options.Options.EndPoints.Add(Configuration["Redis:Endpoint"]);
                options.Options.Password = Configuration["Redis:Password"];
            });
        }
示例#29
0
        /// <inheritdoc />
        public async Task <ActionableMessageTokenValidationResult> ValidateTokenAsync(
            string token,
            string targetServiceBaseUrl)
        {
            if (string.IsNullOrEmpty(token))
            {
                throw new ArgumentException("token is null or empty.", "token");
            }

            if (string.IsNullOrEmpty(targetServiceBaseUrl))
            {
                throw new ArgumentException("url is null or empty.", "targetServiceBaseUrl");
            }

            CancellationToken          cancellationToken;
            OpenIdConnectConfiguration o365OpenIdConfig = await OpenIdConnectConfigurationRetriever.GetAsync(O365OpenIdConfiguration.MetadataUrl, cancellationToken);

            ClaimsPrincipal claimsPrincipal;
            ActionableMessageTokenValidationResult result = new ActionableMessageTokenValidationResult();

            var parameters = new System.IdentityModel.Tokens.TokenValidationParameters()
            {
                ValidateIssuer      = true,
                ValidIssuers        = new[] { O365OpenIdConfiguration.TokenIssuer },
                ValidateAudience    = true,
                ValidAudiences      = new[] { targetServiceBaseUrl },
                ValidateLifetime    = true,
                ClockSkew           = TimeSpan.FromMinutes(TokenTimeValidationClockSkewBufferInMinutes),
                RequireSignedTokens = true,
                IssuerSigningKeys   = o365OpenIdConfig.SigningTokens.SelectMany(st => st.SecurityKeys),
            };

            System.IdentityModel.Tokens.JwtSecurityTokenHandler tokenHandler =
                new System.IdentityModel.Tokens.JwtSecurityTokenHandler();
            try
            {
                // This will validate the token's lifetime and the following claims:
                //
                // iss
                // aud
                //
                claimsPrincipal = tokenHandler.ValidateToken(token, parameters, out System.IdentityModel.Tokens.SecurityToken validatedToken);
            }
            catch (SecurityTokenSignatureKeyNotFoundException ex)
            {
                Trace.TraceError("Token signature key not found.");
                result.Exception = ex;
                return(result);
            }
            catch (SecurityTokenExpiredException ex)
            {
                Trace.TraceError("Token expired.");
                result.Exception = ex;
                return(result);
            }
            catch (SecurityTokenInvalidSignatureException ex)
            {
                Trace.TraceError("Invalid signature.");
                result.Exception = ex;
                return(result);
            }
            catch (Exception ex)
            {
                Trace.TraceError(ex.Message);
                result.Exception = ex;
                return(result);
            }

            if (claimsPrincipal == null)
            {
                Trace.TraceError("Identity not found in the token.");
                result.Exception = new InvalidOperationException("Identity not found in the token");
                return(result);
            }

            ClaimsIdentity identity = claimsPrincipal.Identities.OfType <ClaimsIdentity>().FirstOrDefault();

            if (identity == null)
            {
                Trace.TraceError("Claims not found in the token.");
                result.Exception = new InvalidOperationException("Claims not found in the token.");
                return(null);
            }

            if (!string.Equals(GetClaimValue(identity, "appid"), O365OpenIdConfiguration.AppId, StringComparison.OrdinalIgnoreCase))
            {
                Trace.TraceError(
                    "App ID does not match. Expected: {0} Actual: {1}",
                    O365OpenIdConfiguration.AppId,
                    GetClaimValue(identity, "appid"));
                return(null);
            }

            result.ValidationSucceeded = true;
            result.Sender = GetClaimValue(identity, "sender");

            // Get the value of the "sub" claim. Passing in "sub" will not return a value because the TokenHandler
            // maps "sub" to ClaimTypes.NameIdentifier. More info here
            // https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/issues/415.
            result.ActionPerformer = GetClaimValue(identity, ClaimTypes.NameIdentifier);

            return(result);
        }
示例#30
0
        static async Task Main()
        {
            AuthenticationContext context = new AuthenticationContext(authority);
            AuthenticationResult  result  = context.AcquireTokenAsync(
                resource,
                clientId,
                redirectUri,
                new PlatformParameters(PromptBehavior.Auto)).Result;

            // Get the JWT bearer token from the authorization header
            // Use https://jwt.ms to decode
            string jwtToken = result.AccessToken;

            Console.WriteLine($"\n-----\n {jwtToken} \n-----\n");

            // Get tenant information to validate incoming JWT tokens
            string stsDiscoveryEndpoint = $"{authority}/.well-known/openid-configuration";
            OpenIdConnectConfigurationRetriever configRetriever             = new OpenIdConnectConfigurationRetriever();
            ConfigurationManager <OpenIdConnectConfiguration> configManager =
                new ConfigurationManager <OpenIdConnectConfiguration>(stsDiscoveryEndpoint, configRetriever);
            OpenIdConnectConfiguration config = await configManager.GetConfigurationAsync();

            TokenValidationParameters validationParameters = new TokenValidationParameters
            {
                ValidIssuer              = config.Issuer, // gets pulled from https://login.microsoftonline.com/swearjarbank.onmicrosoft.com/.well-known/openid-configuration
                ValidateIssuer           = true,          // compares token issuer claim with https://login.microsoftonline.com/swearjarbank.onmicrosoft.com/.well-known/openid-configuration
                ValidAudience            = resource,
                ValidateAudience         = true,          // compares aud claim to ValidAudience
                ValidateIssuerSigningKey = false,
                IssuerSigningKeys        = config.SigningKeys,
                RequireExpirationTime    = true,
                RequireSignedTokens      = true
            };

            // VALIDATE TOKEN
            // https://stackoverflow.com/a/39870281/4148708
            // "There are two steps to verity the token.
            // First, verify the signature of the token to ensure the token
            // was issued by Azure Active Directory. Second verify the claims
            // in the token based on the business logic."

            SecurityToken           validatedToken   = new JwtSecurityToken();
            JwtSecurityTokenHandler tokenHandler     = new JwtSecurityTokenHandler();
            ClaimsPrincipal         validationResult = null;

            try
            {
                validationResult = tokenHandler.ValidateToken(jwtToken, validationParameters, out validatedToken);
            }
            catch (Exception ex)
            {
                Console.BackgroundColor = ConsoleColor.DarkRed;
                Console.ForegroundColor = ConsoleColor.White;
                Console.WriteLine("TOKEN DID NOT PASS VALIDATION LOGIC.");
                Console.WriteLine(ex.Message);
                Console.ResetColor();
                Console.ReadKey();
                Environment.Exit(-1);
            }

            Console.BackgroundColor = ConsoleColor.DarkGreen;
            Console.ForegroundColor = ConsoleColor.White;
            Console.WriteLine("TOKEN IS VALID.");
            Console.ResetColor();
            Console.WriteLine($"Issuer: {validatedToken.Issuer}\n" +
                              $"ValidFrom: {validatedToken.ValidFrom}\n" +
                              $"ValidTo: {validatedToken.ValidTo}\n" +
                              $"Public Signing Key: {validatedToken.SigningKey.KeyId}\n\n" +
                              "Claims:");
            IEnumerator claims = validationResult.Claims.GetEnumerator();

            while (claims.MoveNext())
            {
                Console.WriteLine($"  {claims.Current}");
            }
            Console.ReadKey();
        }