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); }
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); }
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); }
// 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(); } }
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); }
public OpenIdConnectCachingSecurityTokenProvider(string metadataEndpoint) { _metadataEndpoint = metadataEndpoint; IConfigurationRetriever<OpenIdConnectConfiguration> pConfigRetriever = new OpenIdConnectConfigurationRetriever(); _configManager = new ConfigurationManager<OpenIdConnectConfiguration>(metadataEndpoint, pConfigRetriever); RetrieveMetadata(); }
/// <inheritdoc/> public void RequestRefresh() { _configurations.Keys.ForEach(url => { OpenIdConnectConfigurationRetriever.GetAsync(url, CancellationToken.None).ContinueWith(result => { _configurations[url] = result.Result; }); }); }
/// <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); }
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); }
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(); } }
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; }
// 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); } }
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); }
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); } } }
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)); } }
// 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"]; }); }
/// <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); }
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(); }