Beispiel #1
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);
        }
Beispiel #2
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);
        }
        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);
        }
Beispiel #4
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();
            }
        }
        /// <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);
        }
Beispiel #7
0
 /// <inheritdoc/>
 public void RequestRefresh()
 {
     _configurations.Keys.ForEach(url =>
     {
         OpenIdConnectConfigurationRetriever.GetAsync(url, CancellationToken.None).ContinueWith(result =>
         {
             _configurations[url] = result.Result;
         });
     });
 }
Beispiel #8
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);
        }
        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);
        }
Beispiel #10
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();
            }
        }
        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;
        }
        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 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);
        }
Beispiel #15
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;
                }
            }
        }
Beispiel #16
0
        public async Task RefreshAsync()
        {
            this.cachedResult = await OpenIdConnectConfigurationRetriever.GetAsync(this.DiscoveryUrl, this.httpClientFactory.CreateClient(), new CancellationToken());

            this.nextReload = DateTime.UtcNow.Add(CacheDuration);
        }
Beispiel #17
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));
            }
        }
Beispiel #18
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);
            });
        }
Beispiel #19
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);
        }