diff --git a/README.md b/README.md index e950a7404..2e0328b56 100644 --- a/README.md +++ b/README.md @@ -193,6 +193,167 @@ var oauthAppsApi = new ApplicationApi(configuration); It is possible to use an access token you retrieved outside of the SDK for authentication. For that, set `Configuration.AuthorizationMode` configuration property to `AuthorizationMode.BearerToken` and `Configuration.AccessToken` to the token string. +## Using secret.json for local or appsettings.Development.json or appsettings.Stagging.json etc., Program.cs example for ASPNET API Core. +``` csharp +using Microsoft.Extensions.Configuration.UserSecrets; +using Okta.Sdk.Api; +using Okta.Sdk.Client; +using System.Reflection; + +var builder = WebApplication.CreateBuilder(args); + +// Add services to the container. +builder.Services.AddEndpointsApiExplorer(); +builder.Services.AddControllers(); + +builder.Services.AddSwaggerGen(); + +builder.Services.AddScoped(); +builder.Services.AddScoped(); + +var app = builder.Build(); + +SetConfigurationFilePathForOktaApiServices(); + +// Configure the HTTP request pipeline. +if (!app.Environment.IsProduction()) +{ + app.UseSwagger(); + app.UseSwaggerUI(); +} +app.UseRouting(); +app.UseHttpsRedirection(); +app.MapControllers(); + +app.Run(); + +void SetConfigurationFilePathForOktaApiServices() +{ + var environmentName = app.Environment.EnvironmentName; + + if (string.Equals(environmentName, "Local", StringComparison.OrdinalIgnoreCase)) + { + var secretsId = Assembly.GetExecutingAssembly().GetCustomAttribute()?.UserSecretsId; + var configFilePath = PathHelper.GetSecretsPathFromSecretsId(secretsId); + + SetFilePath(configFilePath); + } + else + { + var configurationFileRoot = app.Environment.ContentRootPath; + var applicationAppSettingsLocation = Path.Combine(configurationFileRoot ?? string.Empty, string.IsNullOrEmpty(environmentName) ? "appsettings.json" : $"appsettings.{environmentName}.json"); + + SetFilePath(applicationAppSettingsLocation); + } +} + +void SetFilePath(string filePath) +{ + System.Diagnostics.Debug.Assert(!string.IsNullOrEmpty(filePath), $"{nameof(filePath)} missing parameter."); + + if (File.Exists(filePath)) + { + Configuration.GetConfigFilePath = () => filePath; + } +} +``` + +## Consume IUserApi, IGroupApi in OktaController.cs +``` csharp +using Microsoft.AspNetCore.Mvc; +using Okta.Sdk.Api; +using Okta.Sdk.Model; + +namespace OktaUserManagement; + +public class OktaController : Controller +{ + private readonly IUserApi _userApi; + private readonly IGroupApi _groupApi; + + public OktaController(IUserApi userApi, IGroupApi groupApi) + { + _userApi = userApi; + _groupApi = groupApi; + } + + [HttpGet("GetUsers")] + public async Task> GetUsers() + { + var users = await _userApi.ListUsers(limit: 2).ToListAsync(); + return users; + } + + [HttpGet("GetGroups")] + public async Task> GetGroups() + { + var groups = await _groupApi.ListGroups().ToListAsync(); + return groups; + } +} +``` + +## Set okta settings in secrets.json for local development, appsettings.Stagging.json, appsetttings.XXXXX.json, appsetttings.YYYYY.json settings files for deployment environments +```json +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*", + + "okta": { + "client": { + "connectionTimeout": 30000, + "oktaDomain": "{{yourOktaDomain}}", + "proxy": null, + "port": null, + "host": null, + "username": null, + "password": null, + "authorizationMode": "PrivateKey", + "clientId": "{{clientId}}", + "Scopes": { + "scopeId1": "okta.users.read", + "scopeId2": "okta.users.manage", + "scopeId3": "okta.groups.read", + "scopeId4": "okta.groups.manage" + }, + "PrivateKey": { + "d": "{{d}}", + "p": "{{p}}", + "q": "{{q}}", + "dp": "{{dp}}", + "dq": "{{dq}}", + "qi": "{{qi}}", + "kty": "RSA", + "e": "AQAB", + "kid": "{{kid}}", + "n": "{{n}}" + } + } + } +} +``` +## ASPNETCORE_ENVIRONMENT is set to local for a developer machine environment in launchSettings.json +```json +{ + "profiles": { + "OktaUserManagement": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "swagger", + "applicationUrl": "https://localhost:7127", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Local" + } + } + } +} +``` ## Usage guide These examples will help you understand how to use this library. You can also browse the full [API reference documentation][dotnetdocs]. diff --git a/src/Okta.Sdk/Client/Configuration.cs b/src/Okta.Sdk/Client/Configuration.cs index efd667105..12188cfe2 100644 --- a/src/Okta.Sdk/Client/Configuration.cs +++ b/src/Okta.Sdk/Client/Configuration.cs @@ -787,6 +787,12 @@ protected void AddApiKeyPrefix(string key, string value) #endregion Methods #region Static Members + + /// + /// Allows a client application/api to set a configuration file path (i.e. secrets.json or appSettings.xxxxxx.json) + /// + public static Func GetConfigFilePath { get; set; } + /// /// Merge configurations. /// @@ -832,34 +838,55 @@ public static IReadableConfiguration MergeConfigurations(IReadableConfiguration }; return config; } - + public static Configuration GetConfigurationOrDefault(Configuration configuration = null) { - string configurationFileRoot = Directory.GetCurrentDirectory(); + var compiledConfig = new Configuration(); + var configBuilder = new ConfigurationBuilder(); - var homeOktaYamlLocation = HomePath.Resolve("~", ".okta", "okta.yaml"); + if (GetConfigFilePath != null) + { + string applicationAppSettingsLocation = GetConfigFilePath(); - var applicationAppSettingsLocation = Path.Combine(configurationFileRoot ?? string.Empty, "appsettings.json"); - var applicationOktaYamlLocation = Path.Combine(configurationFileRoot ?? string.Empty, "okta.yaml"); + if (!File.Exists(applicationAppSettingsLocation)) + throw new FileNotFoundException($"Could not find configuration file at {applicationAppSettingsLocation}"); - 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(configuration, root: "okta:client") - .AddObject(configuration, root: "okta:testing") - .AddObject(configuration); + var builtConfig = configBuilder.AddJsonFile(applicationAppSettingsLocation) + .AddObject(configuration) + .Build(); - var compiledConfig = new Configuration(); - configBuilder.Build().GetSection("okta").GetSection("client").Bind(compiledConfig); - configBuilder.Build().GetSection("okta").GetSection("testing").Bind(compiledConfig); - configBuilder.Build().Bind(compiledConfig); + builtConfig.GetSection("okta").GetSection("client").Bind(compiledConfig); - return compiledConfig; + return compiledConfig; + } + else + { + 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"); + + configBuilder.AddYamlFile(homeOktaYamlLocation, optional: true) + .AddJsonFile(applicationAppSettingsLocation, optional: true) + .AddYamlFile(applicationOktaYamlLocation, optional: true) + .AddEnvironmentVariables("okta", "_", root: "okta") + .AddEnvironmentVariables("okta_testing", "_", root: "okta") + .AddObject(configuration, root: "okta:client") + .AddObject(configuration, root: "okta:testing") + .AddObject(configuration); + + var config = configBuilder.Build(); + config.GetSection("okta").GetSection("client").Bind(compiledConfig); + config.GetSection("okta").GetSection("testing").Bind(compiledConfig); + config.Bind(compiledConfig); + + + return compiledConfig; + } } - + #endregion Static Members }