public async Task FailIfStatusCodeIs4xx(HttpStatusCode statusCode) { var response = @"{""error"":""invalid_client"",""error_description"":""The audience claim for client_assertion must be the endpoint invoked for the request.""}"; var messageHandler = new MockHttpMessageHandler(response, statusCode); var httpClient = new HttpClient(messageHandler); var configuration = new OktaClientConfiguration(); configuration.OktaDomain = "https://myOktaDomain.oktapreview.com"; configuration.AuthorizationMode = AuthorizationMode.PrivateKey; configuration.ClientId = "foo"; configuration.PrivateKey = TestCryptoKeys.GetMockRSAPrivateKeyConfiguration(); configuration.Scopes = new List <string> { "foo" }; var oktaClient = new OktaClient(configuration); var logger = Substitute.For <ILogger>(); var resourceFactory = new ResourceFactory(oktaClient, logger); var tokenProvider = new DefaultOAuthTokenProvider(configuration, resourceFactory, httpClient); Func <Task <string> > function = async() => await tokenProvider.GetAccessTokenAsync(); function.Should().Throw <OktaOAuthException>().Where(x => x.StatusCode == (int)statusCode && x.Error == "invalid_client" && x.ErrorDescription == "The audience claim for client_assertion must be the endpoint invoked for the request."); }
/// <summary> /// Initializes a new instance of the <see cref="OktaClient"/> class. /// </summary> /// <param name="apiClientConfiguration"> /// The client configuration. If <c>null</c>, the library will attempt to load /// configuration from an <c>okta.yaml</c> file or environment variables. /// </param> /// <param name="logger">The logging interface to use, if any.</param> /// <param name="serializer">The JSON serializer to use, if any. Using the <c>DefaultSerializer</c> is still strongly recommended since it has all the behavior this SDK needs to work properly. /// If a custom serializer is used, the developer is responsible to add the required logic for this SDK to continue working properly. See <see cref="DefaultSerializer"/> to check out what can be configured. /// </param> public OktaClient(OktaClientConfiguration apiClientConfiguration = null, ILogger logger = null, ISerializer serializer = null) { Configuration = GetConfigurationOrDefault(apiClientConfiguration); OktaClientConfigurationValidator.Validate(Configuration); logger = logger ?? NullLogger.Instance; serializer = serializer ?? new DefaultSerializer(); var defaultClient = DefaultHttpClient.Create( Configuration.ConnectionTimeout, Configuration.Proxy, logger); var resourceFactory = new ResourceFactory(this, logger); IOAuthTokenProvider oAuthTokenProvider = (Configuration.AuthorizationMode == AuthorizationMode.PrivateKey) ? new DefaultOAuthTokenProvider(Configuration, resourceFactory, logger: logger) : NullOAuthTokenProvider.Instance; var requestExecutor = new DefaultRequestExecutor(Configuration, defaultClient, logger, oAuthTokenProvider: oAuthTokenProvider); _dataStore = new DefaultDataStore( requestExecutor, serializer, resourceFactory, logger); PayloadHandler.TryRegister <PkixCertPayloadHandler>(); PayloadHandler.TryRegister <PemFilePayloadHandler>(); PayloadHandler.TryRegister <X509CaCertPayloadHandler>(); }
public async Task ReturnAccessTokenWhenRequestSuccess() { var response = @"{""token_type"":""Bearer"",""expires_in"":3600,""access_token"":""foo"",""scope"":""okta.users.read okta.users.manage""}"; var messageHandler = new MockHttpMessageHandler(response, HttpStatusCode.OK); var httpClient = new HttpClient(messageHandler); var configuration = new OktaClientConfiguration(); configuration.OktaDomain = "https://myOktaDomain.oktapreview.com"; configuration.AuthorizationMode = AuthorizationMode.PrivateKey; configuration.ClientId = "foo"; configuration.PrivateKey = TestCryptoKeys.GetMockRSAPrivateKeyConfiguration(); configuration.Scopes = new List <string> { "foo" }; var oktaClient = new OktaClient(configuration); var logger = Substitute.For <ILogger>(); var resourceFactory = new ResourceFactory(oktaClient, logger); var tokenProvider = new DefaultOAuthTokenProvider(configuration, resourceFactory, httpClient); var token = await tokenProvider.GetAccessTokenAsync(); token.Should().Be("foo"); }
public async Task FailIfAccessTokenNotFound() { var response = @"{""foo"":""bar""}"; var messageHandler = new MockHttpMessageHandler(response, HttpStatusCode.OK); var httpClient = new HttpClient(messageHandler); var configuration = new OktaClientConfiguration(); configuration.OktaDomain = "https://myOktaDomain.oktapreview.com"; configuration.AuthorizationMode = AuthorizationMode.PrivateKey; configuration.ClientId = "foo"; configuration.PrivateKey = TestCryptoKeys.GetMockRSAPrivateKeyConfiguration(); configuration.Scopes = new List <string> { "foo" }; var oktaClient = new OktaClient(configuration); var logger = Substitute.For <ILogger>(); var resourceFactory = new ResourceFactory(oktaClient, logger); var tokenProvider = new DefaultOAuthTokenProvider(configuration, resourceFactory, httpClient); Func <Task <string> > function = async() => await tokenProvider.GetAccessTokenAsync(); function.Should().Throw <MissingFieldException>(); }
private static IDataStore PrepareIDataStore(OktaClientConfiguration apiClientConfiguration) { OktaClientConfiguration oktaClientConfiguration = PrepareOktaClientConfiguration(apiClientConfiguration); Microsoft.Extensions.Logging.ILogger logger = Microsoft.Extensions.Logging.Abstractions.NullLogger.Instance; HttpClient httpClient = DefaultHttpClient.Create( oktaClientConfiguration.ConnectionTimeout, oktaClientConfiguration.Proxy, logger); AbstractResourceTypeResolverFactory resourceTypeResolverFactory = null; BaseOktaClient baseOktaClient = new BaseOktaClient(); dynamic resourceFactory = new ResourceFactory(baseOktaClient, logger, resourceTypeResolverFactory); var requestExecutor = new DefaultRequestExecutor(oktaClientConfiguration, httpClient, logger); UserAgentBuilder userAgentBuilder = new UserAgentBuilder( "custom", typeof(CustomAuthnClient).GetTypeInfo().Assembly.GetName().Version); IDataStore dataStore = new DefaultDataStore( requestExecutor, new DefaultSerializer(), resourceFactory, logger, userAgentBuilder); return(dataStore); }
private static OktaClientConfiguration GetConfigurationOrDefault(OktaClientConfiguration apiClientConfiguration = null) { string configurationFileRoot = Directory.GetCurrentDirectory(); var homeOktaYamlLocation = HomePath.Resolve("~", ".okta", "okta.yaml"); var applicationAppSettingsLocation = Path.Combine(configurationFileRoot ?? string.Empty, "appsettings.json"); var applicationOktaYamlLocation = Path.Combine(configurationFileRoot ?? string.Empty, "okta.yaml"); var configBuilder = new ConfigurationBuilder() .AddYamlFile(homeOktaYamlLocation, optional: true) .AddJsonFile(applicationAppSettingsLocation, optional: true) .AddYamlFile(applicationOktaYamlLocation, optional: true) .AddEnvironmentVariables("okta", "_", root: "okta") .AddEnvironmentVariables("okta_testing", "_", root: "okta") .AddObject(apiClientConfiguration, root: "okta:client") .AddObject(apiClientConfiguration, root: "okta:testing") .AddObject(apiClientConfiguration); var compiledConfig = new OktaClientConfiguration(); configBuilder.Build().GetSection("okta").GetSection("client").Bind(compiledConfig); configBuilder.Build().GetSection("okta").GetSection("testing").Bind(compiledConfig); configBuilder.Build().Bind(compiledConfig); return(compiledConfig); }
public async Task NotRetryRequestOnceWhenResponseIsNot401AndAuthorizationModeIsPrivateKeyAsync(HttpStatusCode statusCode) { var requestMessageHandler = new MockHttpMessageHandler(string.Empty, statusCode); var httpClientRequest = new HttpClient(requestMessageHandler); var configuration = new OktaClientConfiguration(); configuration.OktaDomain = "https://myOktaDomain.oktapreview.com"; configuration.AuthorizationMode = AuthorizationMode.PrivateKey; configuration.ClientId = "foo"; configuration.PrivateKey = TestCryptoKeys.GetMockRSAPrivateKeyConfiguration(); configuration.Scopes = new List <string> { "foo" }; var oktaClient = new OktaClient(configuration); var logger = Substitute.For <ILogger>(); var resourceFactory = new ResourceFactory(oktaClient, logger); var tokenResponse = @"{""token_type"":""Bearer"",""expires_in"":3600,""access_token"":""foo"",""scope"":""okta.users.read okta.users.manage""}"; var tokenMessageHandler = new MockHttpMessageHandler(tokenResponse, HttpStatusCode.OK); var httpClientToken = new HttpClient(tokenMessageHandler); var tokenProvider = new DefaultOAuthTokenProvider(configuration, resourceFactory, httpClientToken); var requestExecutor = new DefaultRequestExecutor(configuration, httpClientRequest, logger, new NoRetryStrategy(), tokenProvider); var response = await requestExecutor.GetAsync("foo", null, default(CancellationToken)); response.StatusCode.Should().Be((int)statusCode); tokenMessageHandler.NumberOfCalls.Should().Be(1); requestMessageHandler.NumberOfCalls.Should().Be(1); }
public async Task CallRequestMessageProviderOnPostAsync() { var httpClientRequest = new HttpClient(); var configuration = new OktaClientConfiguration { OktaDomain = "https://okta.okta.com", Token = "foo", }; var logger = Substitute.For <ILogger>(); var mockHttpRequestMessageProvider = Substitute.For <IHttpRequestMessageProvider>(); mockHttpRequestMessageProvider .CreateHttpRequestMessage(Arg.Any <HttpRequest>(), Arg.Any <string>()) .Returns(new HttpRequestMessage()); var testRequestExecutor = new DefaultRequestExecutor(configuration, httpClientRequest, logger, new NoRetryStrategy(), null, mockHttpRequestMessageProvider); var testHttpRequest = new HttpRequest { Uri = "/api/v1" }; await testRequestExecutor.PostAsync(testHttpRequest, CancellationToken.None); mockHttpRequestMessageProvider .Received(1) .CreateHttpRequestMessage(Arg.Is(testHttpRequest), Arg.Is <string>("api/v1")); }
public void GenerateECSignedJWT() { var mockPrivateKeyConfiguration = TestCryptoKeys.GetMockECPrivateKeyConfiguration(); var configuration = new OktaClientConfiguration(); configuration.OktaDomain = "https://myOktaDomain.oktapreview.com"; configuration.AuthorizationMode = AuthorizationMode.PrivateKey; configuration.ClientId = "foo"; configuration.PrivateKey = mockPrivateKeyConfiguration; configuration.Scopes = new List <string> { "foo" }; var signedJwt = new DefaultJwtGenerator(configuration).GenerateSignedJWT(); // Verify signature with public key var claimsPrincipal = new JwtSecurityTokenHandler().ValidateToken( signedJwt, new TokenValidationParameters { ValidAudience = $"{configuration.OktaDomain}oauth2/v1/token", ValidIssuer = configuration.ClientId, IssuerSigningKey = TestCryptoKeys.GetMockECPublicKey(), }, out _); claimsPrincipal.Should().NotBeNull(); }
/// <summary> /// Initializes a new instance of the <see cref="BaseOktaClient"/> class, called internally from this or any derived class's constructor. /// </summary> /// <param name="apiClientConfiguration"> /// The client configuration. If <c>null</c>, the library will attempt to load /// configuration from an <c>okta.yaml</c> file or environment variables. /// </param> /// <param name="httpClient">The HTTP client to use for requests to the Okta API.</param> /// <param name="logger">The logging interface to use, if any.</param> /// <param name="userAgentBuilder">The builder for the user agent, which would be specific to any derived classes</param> /// <param name="resourceTypeResolverFactory">The factory with can resolve and enumerate all Resources in the assembly</param> protected BaseOktaClient( OktaClientConfiguration apiClientConfiguration, HttpClient httpClient, ILogger logger, UserAgentBuilder userAgentBuilder, AbstractResourceTypeResolverFactory resourceTypeResolverFactory) { Configuration = GetConfigurationOrDefault(apiClientConfiguration); OktaClientConfigurationValidator.Validate(Configuration); logger = logger ?? NullLogger.Instance; httpClient = httpClient ?? DefaultHttpClient.Create( Configuration.ConnectionTimeout, Configuration.Proxy, logger); var requestExecutor = new DefaultRequestExecutor(Configuration, httpClient, logger); var resourceFactory = new ResourceFactory(this, logger, resourceTypeResolverFactory); _dataStore = new DefaultDataStore( requestExecutor, new DefaultSerializer(), resourceFactory, logger, userAgentBuilder); }
public static (IDataStore, OktaClientConfiguration, RequestContext) GetDefaultCustomClientParams(OktaClientConfiguration oktaClientConfiguration) { OktaClientConfiguration clientConfiguration = PrepareOktaClientConfiguration(oktaClientConfiguration); IDataStore dataStore = PrepareIDataStore(clientConfiguration); RequestContext requestContext = null; return(dataStore, clientConfiguration, requestContext); }
public TestDefaultRequestExecutor(OktaClientConfiguration configuration, HttpClient httpClient, ILogger logger, IRetryStrategy retryStrategy = null, IOAuthTokenProvider oAuthTokenProvider = null) { VerbExecutionCounts = new Dictionary <HttpVerb, int> { { HttpVerb.Get, 0 }, { HttpVerb.Post, 0 }, { HttpVerb.Put, 0 }, { HttpVerb.Delete, 0 }, }; }
public void FailIfOktaDomainHasTypo(string oktaDomain) { var configuration = new OktaClientConfiguration(); configuration.OktaDomain = oktaDomain; Action action = () => OktaClientConfigurationValidator.Validate(configuration); action.Should().Throw <ArgumentException>().Where(e => e.ParamName == nameof(configuration.OktaDomain)); }
public void NotFailIfOktaDomainIsNotStartingWithHttpsAndDisableHttpsCheckIsTrue(string oktaDomain) { var configuration = new OktaClientConfiguration(); configuration.OktaDomain = oktaDomain; configuration.DisableHttpsCheck = true; Action action = () => OktaClientConfigurationValidator.Validate(configuration); action.Should().NotThrow <ArgumentException>(); }
public void FailIfTokenIsNullOrEmpty(string token) { var configuration = new OktaClientConfiguration(); configuration.OktaDomain = "https://foo.oktapreview.com"; configuration.Token = token; Action action = () => OktaClientConfigurationValidator.Validate(configuration); action.Should().Throw <ArgumentNullException>().Where(e => e.ParamName == nameof(configuration.Token)); }
public void FailIfOktaDomainContainsAdminKeyword(string oktaDomain) { var configuration = new OktaClientConfiguration(); configuration.OktaDomain = oktaDomain; configuration.Token = "foo"; Action action = () => OktaClientConfigurationValidator.Validate(configuration); action.Should().Throw <ArgumentException>().Where(e => e.ParamName == nameof(configuration.OktaDomain)); }
public void FailIfOktaDomainIsNotStartingWithHttps(string oktaDomain) { var configuration = new OktaClientConfiguration(); configuration.OktaDomain = oktaDomain; configuration.DisableHttpsCheck = false; Action action = () => OktaClientConfigurationValidator.Validate(configuration); action.Should().Throw <ArgumentException>().Where(e => e.ParamName == nameof(configuration.OktaDomain)); }
/// <summary> /// Initializes a new instance of the <see cref="DefaultOAuthTokenProvider"/> class. /// </summary> /// <param name="configuration">The Okta configuration.</param> /// <param name="resourceFactory">The resource factory.</param> /// <param name="httpClient">The http client.</param> /// <param name="jwtGenerator">The JWT generator.</param> /// <param name="logger">The logger.</param> public DefaultOAuthTokenProvider(OktaClientConfiguration configuration, ResourceFactory resourceFactory, HttpClient httpClient = null, IJwtGenerator jwtGenerator = null, ILogger logger = null) { Configuration = configuration; _resourceFactory = resourceFactory; _logger = logger ?? NullLogger.Instance; _httpClient = httpClient ?? new HttpClient(); _httpClient.BaseAddress = new Uri(Configuration.OktaDomain); _httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); _jwtGenerator = jwtGenerator ?? new DefaultJwtGenerator(configuration); }
private static void ThrowIfInvalidConfiguration(OktaClientConfiguration configuration) { if (string.IsNullOrEmpty(configuration.OrgUrl)) { throw new ArgumentNullException(nameof(configuration.OrgUrl), "You must supply an Okta Org URL, like https://dev-12345.oktapreview.com"); } if (string.IsNullOrEmpty(configuration.Token)) { throw new ArgumentNullException(nameof(configuration.Token), "You must supply an Okta API token. You can create one in the Okta developer dashboard."); } }
/// <summary> /// Initializes a new instance of the <see cref="AuthenticationClient"/> class using the specified <see cref="HttpClient"/>. /// </summary> /// <param name="apiClientConfiguration"> /// The client configuration. If <c>null</c>, the library will attempt to load /// configuration from an <c>okta.yaml</c> file or environment variables. /// </param> /// <param name="httpClient">The HTTP client to use for requests to the Okta API.</param> /// <param name="logger">The logging interface to use, if any.</param> public AuthenticationClient( OktaClientConfiguration apiClientConfiguration = null, HttpClient httpClient = null, ILogger logger = null) : base( apiClientConfiguration, httpClient, logger, new UserAgentBuilder("okta-auth-dotnet", typeof(AuthenticationClient).GetTypeInfo().Assembly.GetName().Version), new AbstractResourceTypeResolverFactory(ResourceTypeHelper.GetAllDefinedTypes(typeof(Resource)))) { }
/// <summary> /// Initializes a new instance of the <see cref="DefaultRequestExecutor"/> class. /// </summary> /// <param name="configuration">The client configuration.</param> /// <param name="httpClient">The HTTP client to use, if any.</param> /// <param name="logger">The logging interface.</param> public DefaultRequestExecutor(OktaClientConfiguration configuration, HttpClient httpClient, ILogger logger) { if (configuration == null) { throw new ArgumentNullException(nameof(configuration)); } _oktaDomain = configuration.OktaDomain; _logger = logger; _httpClient = httpClient ?? throw new ArgumentNullException(nameof(httpClient)); ApplyDefaultClientSettings(_httpClient, _oktaDomain, configuration); }
public void ThrowForNullScopesWhenAuthorizationModeIsPrivateKey() { var configuration = new OktaClientConfiguration(); configuration.OktaDomain = "https://myOktaDomain.oktapreview.com"; configuration.AuthorizationMode = AuthorizationMode.PrivateKey; configuration.ClientId = "foo"; configuration.PrivateKey = new JsonWebKeyConfiguration(); configuration.Scopes = null; Action action = () => OktaClientConfigurationValidator.Validate(configuration); action.Should().Throw <ArgumentNullException>(); }
/// <summary> /// Initializes a new instance of the <see cref="DefaultJwtGenerator"/> class. /// </summary> /// <param name="configuration">The Okta client configuration.</param> public DefaultJwtGenerator(OktaClientConfiguration configuration) { if (configuration == null) { throw new ArgumentNullException("The Okta configuration cannot be null."); } if (!_supportedKeys.Contains(configuration.PrivateKey?.Kty)) { throw new NotSupportedException($"The kty {configuration.PrivateKey?.Kty} is not supported. Use 'EC' or 'RSA'."); } _configuration = configuration; }
internal static OktaConnectionContext GetConnectionContext(KeyedCollection <string, ConfigParameter> configParameters) { ProxyConfiguration proxyConfig = null; if (!string.IsNullOrWhiteSpace(OktaMAConfigSection.Configuration.ProxyUrl)) { proxyConfig = new ProxyConfiguration() { Host = OktaMAConfigSection.Configuration.ProxyUrl }; logger.Info($"Using proxy host {proxyConfig.Host}"); } logger.Info($"Setting up connection to {configParameters[ConfigParameterNames.TenantUrl].Value}"); System.Net.ServicePointManager.DefaultConnectionLimit = OktaMAConfigSection.Configuration.ConnectionLimit; GlobalSettings.ExportThreadCount = OktaMAConfigSection.Configuration.ExportThreads; NLog.Extensions.Logging.NLogLoggerProvider f = new NLog.Extensions.Logging.NLogLoggerProvider(); ILogger nlogger = f.CreateLogger("ext-logger"); OktaClientConfiguration oktaConfig = new OktaClientConfiguration { OktaDomain = configParameters[ConfigParameterNames.TenantUrl].Value, Token = configParameters[ConfigParameterNames.ApiKey].SecureValue.ConvertToUnsecureString(), Proxy = proxyConfig, ConnectionTimeout = OktaMAConfigSection.Configuration.HttpClientTimeout, MaxRetries = 8, }; HttpClient httpClient; if (OktaMAConfigSection.Configuration.HttpDebugEnabled) { logger.Warn("WARNING: HTTPS Debugging enabled. Service certificate validation is disabled"); httpClient = OktaConnectionContext.CreateDebugHttpClient(nlogger, oktaConfig); } else { httpClient = DefaultHttpClient.Create(oktaConfig.ConnectionTimeout, proxyConfig, nlogger); } return(new OktaConnectionContext() { Client = new OktaClient(oktaConfig, httpClient, nlogger, new DefaultRetryStrategy(oktaConfig.MaxRetries ?? 8, 0, 1)) }); }
/// <summary> /// Initializes a new instance of the <see cref="DefaultRequestExecutor"/> class. /// </summary> /// <param name="configuration">The client configuration.</param> /// <param name="httpClient">The HTTP client to use, if any.</param> /// <param name="logger">The logging interface.</param> /// <param name="retryStrategy">The retry strategy interface.</param> /// <param name="oAuthTokenProvider">The OAuth token provider interface.</param> public DefaultRequestExecutor(OktaClientConfiguration configuration, HttpClient httpClient, ILogger logger, IRetryStrategy retryStrategy = null, IOAuthTokenProvider oAuthTokenProvider = null, IHttpRequestMessageProvider httpRequestMessageProvider = null) { if (configuration == null) { throw new ArgumentNullException(nameof(configuration)); } _oktaDomain = configuration.OktaDomain; _logger = logger; _httpClient = httpClient ?? throw new ArgumentNullException(nameof(httpClient)); _retryStrategy = retryStrategy ?? new DefaultRetryStrategy(configuration.MaxRetries.Value, configuration.RequestTimeout.Value); _oAuthTokenProvider = oAuthTokenProvider ?? NullOAuthTokenProvider.Instance; _oktaConfiguration = configuration; _httpRequestMessageProvider = httpRequestMessageProvider ?? HttpRequestMessageProvider.Default; ApplyDefaultClientSettings(_httpClient, _oktaDomain, configuration); }
/// <summary> /// Initializes a new instance of the <see cref="OktaClient"/> class using the specified <see cref="HttpClient"/>. /// </summary> /// <param name="apiClientConfiguration"> /// The client configuration. If <c>null</c>, the library will attempt to load /// configuration from an <c>okta.yaml</c> file or environment variables. /// </param> /// <param name="httpClient">The HTTP client to use for requests to the Okta API.</param> /// <param name="logger">The logging interface to use, if any.</param> public OktaClient(OktaClientConfiguration apiClientConfiguration, HttpClient httpClient, ILogger logger = null) { Configuration = GetConfigurationOrDefault(apiClientConfiguration); ThrowIfInvalidConfiguration(Configuration); logger = logger ?? NullLogger.Instance; var requestExecutor = new DefaultRequestExecutor(Configuration, httpClient, logger); var resourceFactory = new ResourceFactory(this, logger); _dataStore = new DefaultDataStore( requestExecutor, new DefaultSerializer(), resourceFactory, logger); }
public void FailForEmptyOrInvalidClientIdWhenAuthorizationModeIsPrivateKey(string clientId) { var configuration = new OktaClientConfiguration(); configuration.OktaDomain = "https://myOktaDomain.oktapreview.com"; configuration.AuthorizationMode = AuthorizationMode.PrivateKey; configuration.ClientId = clientId; configuration.PrivateKey = new JsonWebKeyConfiguration(); configuration.Scopes = new List <string> { "foo" }; Action action = () => OktaClientConfigurationValidator.Validate(configuration); action.Should().Throw <ArgumentNullException>(); }
public void NotFailWhenValidConfigWhenAuthorizationModeIsPrivateKey() { var configuration = new OktaClientConfiguration(); configuration.OktaDomain = "https://myOktaDomain.oktapreview.com"; configuration.AuthorizationMode = AuthorizationMode.PrivateKey; configuration.ClientId = "foo"; configuration.PrivateKey = new JsonWebKeyConfiguration(); configuration.Scopes = new List <string> { "foo" }; Action action = () => OktaClientConfigurationValidator.Validate(configuration); action.Should().NotThrow(); }
/// <summary> /// Initializes a new instance of the <see cref="OktaClient"/> class. /// </summary> /// <param name="apiClientConfiguration">The client configuration.</param> /// <param name="logger">The logging interface.</param> /// <remarks> /// Configuration can also be specified with a YAML file, or by environment variables. /// </remarks> public OktaClient(OktaClientConfiguration apiClientConfiguration = null, ILogger logger = null) { var compiled = CompileFromConfigurationSources(apiClientConfiguration); var config = new OktaClientConfiguration(); compiled.GetSection("okta").GetSection("client").Bind(config); ThrowIfInvalidConfiguration(config); Configuration = config.DeepClone(); logger = logger ?? NullLogger.Instance; var requestExecutor = new DefaultRequestExecutor(config, logger); var resourceFactory = new ResourceFactory(this, logger); _dataStore = new DefaultDataStore(requestExecutor, new DefaultSerializer(), resourceFactory, logger); }
/// <summary> /// Validates the OktaClient configuration /// </summary> /// <param name="configuration">The configuration to be validated</param> public static void Validate(OktaClientConfiguration configuration) { if (string.IsNullOrEmpty(configuration.OktaDomain)) { throw new ArgumentNullException(nameof(configuration.OktaDomain), "Your Okta URL is missing. You can copy your domain from the Okta Developer Console. Follow these instructions to find it: https://bit.ly/finding-okta-domain"); } configuration.OktaDomain = EnsureTrailingSlash(configuration.OktaDomain); if (!configuration.DisableHttpsCheck && !configuration.OktaDomain.StartsWith("https://", StringComparison.OrdinalIgnoreCase)) { throw new ArgumentException($"Your Okta URL must start with https. Current value: {configuration.OktaDomain}. You can copy your domain from the Okta Developer Console. Follow these instructions to find it: https://bit.ly/finding-okta-domain", nameof(configuration.OktaDomain)); } if (configuration.OktaDomain.IndexOf("{yourOktaDomain}", StringComparison.OrdinalIgnoreCase) >= 0) { throw new ArgumentNullException(nameof(configuration.OktaDomain), "Replace {yourOktaDomain} with your Okta domain. You can copy your domain from the Okta Developer Console. Follow these instructions to find it: https://bit.ly/finding-okta-domain"); } if (configuration.OktaDomain.IndexOf("-admin.okta.com", StringComparison.OrdinalIgnoreCase) >= 0 || configuration.OktaDomain.IndexOf("-admin.oktapreview.com", StringComparison.OrdinalIgnoreCase) >= 0 || configuration.OktaDomain.IndexOf("-admin.okta-emea.com", StringComparison.OrdinalIgnoreCase) >= 0) { throw new ArgumentNullException(nameof(configuration.OktaDomain), $"Your Okta domain should not contain -admin. Current value: {configuration.OktaDomain}. You can copy your domain from the Okta Developer Console. Follow these instructions to find it: https://bit.ly/finding-okta-domain"); } if (configuration.OktaDomain.IndexOf(".com.com", StringComparison.OrdinalIgnoreCase) >= 0) { throw new ArgumentNullException(nameof(configuration.OktaDomain), $"It looks like there's a typo in your Okta domain. Current value: {configuration.OktaDomain}. You can copy your domain from the Okta Developer Console. Follow these instructions to find it: https://bit.ly/finding-okta-domain"); } if (Regex.Matches(configuration.OktaDomain, "://").Count != 1) { throw new ArgumentNullException(nameof(configuration.OktaDomain), $"It looks like there's a typo in your Okta domain. Current value: {configuration.OktaDomain}. You can copy your domain from the Okta Developer Console. Follow these instructions to find it: https://bit.ly/finding-okta-domain"); } if (string.IsNullOrEmpty(configuration.Token)) { throw new ArgumentNullException(nameof(configuration.Token), "Your Okta API token is missing. You can generate one in the Okta Developer Console. Follow these instructions: https://bit.ly/get-okta-api-token"); } if (configuration.Token.IndexOf("{apiToken}", StringComparison.OrdinalIgnoreCase) >= 0) { throw new ArgumentException("Replace {apiToken} with your Okta API token. You can generate one in the Okta Developer Console. Follow these instructions: https://bit.ly/get-okta-api-token", nameof(configuration.Token)); } }