Git Product home page Git Product logo

okta-sdk-dotnet's Introduction

Support API Reference

Okta .NET management SDK

This repository contains the Okta management SDK for .NET. This SDK can be used in your server-side code to interact with the Okta management API and:

Note: For more details about the APIs and models the SDK support, check out the API docs

We also publish these other libraries for .NET:

You can learn more on the Okta + .NET page in our documentation.

Release status

This library uses semantic versioning and follows Okta's library version policy.

✔️ The current stable major version series is: 6.x ✔️ The 5.x series is retiring on June 8th 2023. Until then, we will only fix high-risk security vulnerabilities and other issues will be reviewed on a case-by-case basis. New APIs will be added only on series 6.x, but you can still use the 5.x series to call any new endpoint. The SDK will be still available on Nuget, and the source-code is located in the legacy-5.x-series branch. Please, reach out to the Okta Customer Support Team at [email protected] if you have any questions or issues.

Version Status
7.x ✔️ Stable (migration guide)
6.x ⚠️ Retiring on May 9th 2024

The latest release can always be found on the releases page. For more information about our SDKs' lifecycle, check out our docs.

Need help?

If you run into problems using the SDK, you can

Getting Started

The SDK is compatible with:

  • .NET Standard 2.1
  • .NET Framework 4.6.1 or higher
  • .NET Core 3.0 or higher
  • .NET 5.0 or higher

Visual Studio 2017 or newer is required as previous versions are not compatible with the above frameworks.

Install using Nuget Package Manager

  1. Right-click on your project in the Solution Explorer and choose Manage Nuget Packages...
  2. Search for Okta. Install the Okta.Sdk package.

Install using The Package Manager Console

Simply run install-package Okta.Sdk. Done!

You'll also need:

Initialize an API client

Construct a client instance by passing it your Okta domain name and API token:

using System.Collections.Generic;
using System.Diagnostics;
using Okta.Sdk.Api;
using Okta.Sdk.Client;
using Okta.Sdk.Model;

namespace Example
{
    public class Example
    {
        public static void Main()
        {

            Configuration config = new Configuration();
            config.OktaDomain = "https://your-subdomain.okta.com";
            // Configure API key authorization: API_Token
            config.Token.Add("Authorization", "YOUR_API_KEY");
            
            var apiInstance = new AgentPoolsApi(config);
            var poolId = "poolId_example";  // string | Id of the agent pool for which the settings will apply
            var updateId = "updateId_example";  // string | Id of the update

            try
            {
                // Activate an Agent Pool update
                AgentPoolUpdate result = apiInstance.ActivateAgentPoolsUpdate(poolId, updateId);
                Debug.WriteLine(result);
            }
            catch (ApiException e)
            {
                Debug.Print("Exception when calling AgentPoolsApi.ActivateAgentPoolsUpdate: " + e.Message );
                Debug.Print("Status Code: "+ e.ErrorCode);
                Debug.Print(e.StackTrace);
            }

        }
    }
}

Hard-coding the Okta domain and API token works for quick tests, but for real projects you should use a more secure way of storing these values (such as environment variables). This library supports a few different configuration sources, covered in the configuration reference section.

To use the API client with an HTTP proxy, you can either setup your proxy via different configuration sources, covered in the configuration reference section, or via API constructor. If you have both, the proxy passed via constructor will take precedence.

System.Net.WebProxy webProxy = new System.Net.WebProxy("http://myProxyUrl:80/");
webProxy.Credentials = System.Net.CredentialCache.DefaultCredentials;

var appsApi = new ApplicationApi(webProxy : webProxy);

OAuth 2.0

Okta allows you to interact with Okta APIs using scoped OAuth 2.0 access tokens. Each access token enables the bearer to perform specific actions on specific Okta endpoints, with that ability controlled by which scopes the access token contains.

This SDK supports this feature only for service-to-service applications. Check out our guides to learn more about how to register a new service application using a private and public key pair.

When using this approach you won't need an API Token because the SDK will request an access token for you. In order to use OAuth 2.0, construct an API client instance by passing the following parameters:

var oauthAppsApi = new ApplicationApi(new Configuration
{
    OktaDomain = "https://{{yourOktaDomain}}",
    AuthorizationMode = AuthorizationMode.PrivateKey,
    ClientId = "{{clientId}}",
    Scopes = new List<string> { "okta.users.read", "okta.apps.read" }, // Add all the scopes you need
    PrivateKey =  new JsonWebKeyConfiguration(jsonString)
});

Key object for assigning to the PrivateKey can be created and initialized inline like in this example for RSA key:

var privateKey = new JsonWebKeyConfiguration
{
    P = "{{P}}",
    Kty = "RSA",
    Q = "{{Q}}",
    D = "{{D}}",
    E = "{{E}}",
    Kid = "{{P}}",
    Qi = "{{Qi}}"
};

var configuration = new Configuration
{
    OktaDomain = "https://{{yourOktaDomain}}",
    AuthorizationMode = AuthorizationMode.PrivateKey,
    ClientId = "{{clientId}}",
    Scopes = new List<string> { "okta.users.read", "okta.apps.read" }, // Add all the scopes you need
    PrivateKey = privateKey
};

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.

Note: Starting from 8.x series the Okta management SDK added support for DPoP. If the SDK detects the application has DPoP enabled, it will silently proceed to obtain a DPoP-bound access token, and will generate a new DPoP Proof JWT for every request. There's no additional configuration required for developers.

Usage guide

These examples will help you understand how to use this library. You can also browse the full API reference documentation.

Once you initialize an API client, you can call methods to make requests to the Okta API.

Get a User

// Get the user with a user ID or login
var user = await userApi.GetUserAsync("<Some user ID or login>");

The string argument for GetUserAsync can be the user's ID or the user's login (usually their email).

List all Users

The SDK will automatically paginate Okta collections for you:

// These different styles all perform the same action:
var allUsers = await userApi.ListUsers().ToListAsync();
var allUsers = await userApi.ListUsers().ToArrayAsync();

Filter or search for Users

var foundUsers = await userApi
                        .ListUsers(search: $"profile.nickName eq \"Skywalker\"")
                        .ToArrayAsync();

Create a User

// Create a user with the specified password
var createUserRequest = new CreateUserRequest
            {
                Profile = new UserProfile
                {
                    FirstName = "Anakin",
                    LastName = "Skywalker",
                    Email = "[email protected]",
                    Login = "[email protected]",
                },
                Credentials = new UserCredentials
                {
                    Password = new PasswordCredential
                    {
                        Value = "D1sturB1ng"
                    }
                }
            };

var createdUser = await _userApi.CreateUserAsync(createUserRequest);

Activate a User

// Activate the user
await _userApi.ActivateUserAsync(createdUser.Id, false);

Update a User

// Update profile
createdUser.Profile.NickName = nickName;
var updateUserRequest = new UpdateUserRequest
{
    Profile = createdUser.Profile
};

var updatedUser = await _userApi.UpdateUserAsync(createdUser.Id, updateUserRequest);

Get and set custom attributes

You can't create attributes via code right now, but you can get and set their values. To create them you have to use the Profile Editor in the Developer Console web UI. Once you have created them, you can use the code below:

user.Profile.AdditionalProperties = new Dictionary<string, object>();
user.Profile.AdditionalProperties["homeworld"] = "Planet Earth";

var updateUserRequest = new UpdateUserRequest
{
    Profile = user.Profile
};

var updatedUser = await _userApi.UpdateUserAsync(createdUser.Id, updateUserRequest);

var userHomeworld = updatedUser.Profile.AdditionalProperties["homeworld"];

Remove a User

 await _userApi.DeactivateOrDeleteUserAsync(createdUser.Id);

List all Applications

// List all applications
var appList = await _applicationApi.ListApplications().ToArrayAsync();

Get an Application

var createdApp = await _applicationApi.CreateApplicationAsync(new CreateBasicAuthApplicationOptions()
                {
                    Label = "Sample Basic Auth App",
                    Url = "https://example.com/login.html",
                    AuthUrl = "https://example.com/auth.html",
                });

var retrievedById = await _applicationApi.GetApplicationAsync(createdApp.Id);

Create an OpenID Application

var app = new OpenIdConnectApplication
        {
            Name = "oidc_client",
            SignOnMode = "OPENID_CONNECT",
            Label = $"dotnet-sdk: AddOpenIdConnectApp",
            Credentials = new OAuthApplicationCredentials()
            {
                OauthClient = new ApplicationCredentialsOAuthClient()
                {
                    ClientId = testClientId,
                    TokenEndpointAuthMethod = "client_secret_post",
                    AutoKeyRotation = true,
                },
            },
            Settings = new OpenIdConnectApplicationSettings
            {
                OauthClient = new OpenIdConnectApplicationSettingsClient()
                {
                    ClientUri = "https://example.com/client",
                    LogoUri = "https://example.com/assets/images/logo-new.png",
                    ResponseTypes = new List<string>
                    {
                        "token",
                        "id_token",
                        "code",
                    },
                    RedirectUris = new List<string>
                    {
                        "https://example.com/oauth2/callback",
                        "myapp://callback",
                    },
                    PostLogoutRedirectUris = new List<string>
                    {
                        "https://example.com/postlogout",
                        "myapp://postlogoutcallback",
                    },
                    GrantTypes = new List<string>
                    {
                        "implicit",
                        "authorization_code",
                    },
                    ApplicationType = "native",

                    TosUri = "https://example.com/client/tos",
                    PolicyUri = "https://example.com/client/policy",
                },
            }
        };

var createdApp = await _applicationApi.CreateApplicationAsync(app);

Manual pagination

Collections can be fetched with manually controlled pagination, see the following.

var retrievedUsers = new List<IUser>();
var users = _userApi.ListUsers(limit: 5); // 5 records per a page
var enumerator = users.GetPagedEnumerator();

while (await enumerator.MoveNextAsync())
{
    retrievedUsers.AddRange(enumerator.CurrentPage.Items);
    // ....................
}

Note: For more API samples checkout our tests

Rate Limiting

The Okta API will return 429 responses if too many requests are made within a given time. Please see Rate Limiting at Okta for a complete list of which endpoints are rate limited. When a 429 error is received, the X-Rate-Limit-Reset header will tell you the time at which you can retry. This section discusses methods for handling rate limiting with this SDK.

Built-In Retry

This SDK uses the built-in retry strategy to automatically retry on 429 errors. You can use the default configuration options for the built-in retry strategy, or provide your desired values via client configuration.

You can configure the following options when using the built-in retry strategy:

Configuration Option Description
RequestTimeout The waiting time in milliseconds for a request to be resolved by the client. Less than or equal to 0 means "no timeout". The default value is 0 (None).
MaxRetries The number of times to retry.

Check out the Configuration Reference section for more details about how to set these values via configuration.

Custom Retry

You can implement your own retry strategy via Polly, and assign it to the RetryConfiguration.AsyncPolicy property.

 AsyncPolicy<IRestResponse> retryAsyncPolicy = Policy
                .Handle<ApiException>(ex => ex.ErrorCode == 429)
                .OrResult<IRestResponse>(r => (int)r.StatusCode == 429)
                .WaitAndRetryAsync(configuration.MaxRetries.Value, 
                                   sleepDurationProvider: (retryAttempt, response,
                                   context) => MyCalculateDelayMethod(retryAttempt, response, context)
                );

RetryPolicy.AsyncPolicy = retryAsyncPolicy;

You will have to read the X-Rate-Limit-Reset header on the 429 response. This will tell you the time at which you can retry. Because this is an absolute time value, we recommend calculating the wait time by using the Date header on the response, as it is in sync with the API servers, whereas your local clock may not be. We also recommend adding 1 second to ensure that you will be retrying after the window has expired (there may be a sub-second relative time skew between the X-Rate-Limit-Reset and Date headers).

Configuration reference

This library looks for configuration in the following sources:

  1. An okta.yaml file in a .okta folder in the current user's home directory (~/.okta/okta.yaml or %userprofile%\.okta\okta.yaml)
  2. An appsettings.json file in the application or project's root directory
  3. An okta.yaml file in a .okta folder in the application or project's root directory
  4. Environment variables
  5. Configuration explicitly passed to the constructor (see the example in Getting started)

Higher numbers win. In other words, configuration passed via the constructor will override configuration found in environment variables, which will override configuration in okta.yaml (if any), and so on.

Note that json files cannot be used if they contain JavaScript comments. Comments are not allowed by JSON format.

YAML configuration

When you use an API Token instead of OAuth 2.0 the full YAML configuration looks like:

okta:
  client:
    connectionTimeout: 30000 # milliseconds
    oktaDomain: "https://{yourOktaDomain}"
    proxy:
        port: null
        host: null
        username: null
        password: null
    token: {apiToken}
    requestTimeout: 0 # milliseconds
    rateLimit:
      maxRetries: 4

When you use OAuth 2.0 the full YAML configuration looks like this when using EC key:

okta:
  client:
    connectionTimeout: 30000 # milliseconds
    oktaDomain: "https://{yourOktaDomain}"
    proxy:
      port: null
      host: null
      username: null
      password: null
    authorizationMode: "PrivateKey"
    clientId: "{yourClientId}"
    Scopes:
    - scope1
    - scope2
    PrivateKey: # This SDK supports both RSA and EC keys.
        kty: "EC"
        crv: "P-256"
        x: "{x}"
        y: "{y}"
    requestTimeout: 0 # milliseconds
    rateLimit:
      maxRetries: 4

Or like this for RSA key:

okta:
  client:
    connectionTimeout: 30000 # milliseconds
    oktaDomain: "https://{yourOktaDomain}"
    proxy:
      port: null
      host: null
      username: null
      password: null
    authorizationMode: "PrivateKey"
    clientId: "{yourClientId}"
    Scopes:
    - scope1
    - scope2
    PrivateKey: 
      "p": "{p}"
      "kty": "RSA"
      "q": "{q}"
      "d": "{d}"
      "e": "{e}"
      "kid": "{kid}"
      "qi": "{qi}"
    requestTimeout: 0 # milliseconds
    rateLimit:
      maxRetries: 4

Environment variables

Each one of the configuration values above can be turned into an environment variable name with the _ (underscore) character:

  • OKTA_CLIENT_CONNECTIONTIMEOUT
  • OKTA_CLIENT_TOKEN
  • and so on

Building the SDK

In most cases, you won't need to build the SDK from source. If you want to build it yourself just clone the repo and compile using Visual Studio.

Contributing

We're happy to accept contributions and PRs! Please see the contribution guide to understand how to structure a contribution.

okta-sdk-dotnet's People

Contributors

andriizhegurov-okta avatar bdemers avatar bretterer avatar bryanapellanes avatar bryanapellanes-okta avatar cbarbara-okta avatar dbrownx avatar eng-svc-terminus-github-admin-okta avatar gabrielsroka avatar jmelberg-okta avatar joelfranusic-okta avatar johngronberg-okta avatar justinhelgerson avatar laura-rodriguez avatar laurarodriguez-okta avatar lboyette-okta avatar leebrandt avatar marksztainbok-okta avatar nbarbettini avatar okgodoit avatar raphaellondner-okta avatar rlepage-okta avatar robertjd avatar rus7am avatar ryannewington avatar vijetmahabaleshwar-okta avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

okta-sdk-dotnet's Issues

User integration test: Get User

  1. Create user with credentials → POST /api/v1/users?activate=false
const newUser = {
    profile: {
        firstName: 'John',
        lastName: 'Get-User',
        email: '[email protected]',
        login: '[email protected]'
    },
    credentials: {
        password: { value: 'Abcd1234' }
    }
};
  1. Get the user by ID → GET /api/v1/users/{{userId}}
  2. Get the user by login name → GET /api/v1/users/{{login}}
  3. Deactivate & delete the user → POST /api/v1/users/{{userId}}/lifecycle/deactivate + DELETE /api/v1/users/{{userId}}
  4. Verify that the user is deleted by calling get on user (Exception thrown with 404 error message) → GET /api/v1/users/{{userId}}

convert some internal classes to public

Hello,

Can the class Okta.Core.Utils be converted to public? This would allow custom code methods to be used to deserialize content in a uniform manner with SDK. This will help when new api endpoints are needed that are not yet supported by SDK but needed for custom projects.

namespace Okta.Core
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net.Http;
    using System.Reflection;
    using System.Text.RegularExpressions;
    using System.Threading;

    using Newtonsoft.Json;

    internal class Utils
    {
         ...

Also, the constructor for ApiObject is internal and can't be used to create objects to pass into authClient.Execute method.

internal ApiObject()
{
    this.UnmappedProperties = new Dictionary<string, JProperty>();
    this.ChangedProperties = new HashSet<string>();
}

public virtual AuthResponse Execute(string stateToken, Uri uri, ApiObject apiObject = null)
{

User integration test: Activate User

  1. Create user with credentials → POST /api/v1/users?activate=false
const newUser = {
    profile: {
        firstName: 'John',
        lastName: 'Activate',
        email: '[email protected]',
        login: '[email protected]'
    },
    credentials: {
        password: { value: 'Abcd1234' }
    }
};
  1. Activate the user → POST /api/v1/users/{{userId}}/lifecycle/activate?sendEmail=false
  2. Verify that the user is in the list of ACTIVE users with query parameter → GET /api/v1/users?filter=status eq "ACTIVE"
  3. Deactivate & delete the user → POST /api/v1/users/{{userId}}/lifecycle/deactivate + DELETE /api/v1/users/{{userId}}

Switch repo over to SDK v1

  • Archive current version in 0.x branch
  • Merge mvp branch to master
  • Update readme to explain what's in master and what's in 0.x

User integration test: Update User Profile

  1. Create user with credentials → POST /api/v1/users?activate=false
const newUser = {
    profile: {
        firstName: 'John',
        lastName: 'Profile-Update',
        email: '[email protected]',
        login: '[email protected]'
    },
    credentials: {
        password: { value: 'Abcd1234' }
    }
};
  1. Update the user's profile by adding a nickname → PUT /api/v1/users/{{userId}}
    user.profile.nickName = 'Batman';
  2. Verify that user profile is updated by calling get on the user → GET /api/v1/users/{{userId}}
  3. Deactivate & delete the user → POST /api/v1/users/{{userId}}/lifecycle/deactivate + DELETE /api/v1/users/{{userId}}

Unable to Query users with Get-OktaUser

Connect-Okta -Token $APIKey -FullDomain 'https://myorg.okta.com'
Get-OktaUser [email protected]

The error code is Get-OktaUser : Method not found: 'Okta.Core.EnumerableResults1<!0> Okta.Core.Clients.ApiClient1.GetFilteredEnumerator(Okta.Core.FilterBuilder, Int32, System.String, System.String, System.Nullable`1<System.DateTime>)'.

Windows 10
Okta.Core.Automation 0.1.0.2 [Approved]

With the full error being

PSMessageDetails      : 
Exception             : System.MissingMethodException: Method not found: 'Okta.Core.EnumerableResults`1<!0> Okta.Core.Clients.ApiClient`1.GetFilteredEnumerator(Okta.Core.FilterBuilder, Int32, System.String, System.String, 
                        System.Nullable`1<System.DateTime>)'.
                           at Okta.Core.Automation.GetOktaUser.ProcessRecord()
                           at System.Management.Automation.CommandProcessor.ProcessRecord()
TargetObject          : 
CategoryInfo          : NotSpecified: (:) [Get-OktaUser], MissingMethodException
FullyQualifiedErrorId : System.MissingMethodException,Okta.Core.Automation.GetOktaUser
ErrorDetails          : 
InvocationInfo        : System.Management.Automation.InvocationInfo
ScriptStackTrace      : at <ScriptBlock>, <No file>: line 3
PipelineIterationInfo : {}

Split up the client object

Instead of having an OktaClient object with hundreds of methods, create a UsersClient, SessionsClient, and so on.

PowerShell wrapper issues - Get-OktaUser : Method not found: 'Okta.Core.EnumerableResults

I have installed the API but can't use the Get-OktaUser cmdlet. I always get this response:

Get-OktaUser : Method not found: 'Okta.Core.EnumerableResults1<!0> Okta.Core.Clients.ApiClient1.GetFilteredEnumerator(Okta.Core.FilterBuilder, Int32, System.String, System.String, System.Nullable1<System.DateTime>)'.`

I used PowerShell to create .NET settings and client objects and then connected so I don't think it's an issue with the 4.0 runtime.

$client = New-Object Okta.Core.Clients.OktaClient($settings)

Newtonsoft.json dependency issues

You guys might consider using ILMERGE to get rid of dependency issues on Newtonsoft.json - and/or have the package deal with assembly binding redirects or require latest json.net?

This is a popular library many people reference and the dependency tends to cause mismatch issues. In my case I had a unit test project that had no reference to Newtonsoft.Json. That project referenced another project (to be tested) that referenced a 9.0.0.1 version of Newtonsoft.Json. By default I think installing Okta.Core.Client nuget package installed the lowest compatible version of Json.net. I ended up having to manually add an assembly binding redirect and then uninstalling Okata.Core.Client, install the latest version of Newtonsoft.Json into the unit test project, then re-install Okata.Core.Client.

System.TypeInitializationException : The type initializer for 'Okta.Core.Constants' threw an exception.
----> System.TypeInitializationException : The type initializer for 'Okta.Core.Utils' threw an exception.
----> System.IO.FileLoadException : Could not load file or assembly 'Newtonsoft.Json, Version=9.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)
at Okta.Core.Constants.get_UserAgent()
at Okta.Core.OktaSettings..ctor()
at Okta.Core.Clients.AuthenticatedClient..ctor(String apiToken, String subdomain)
at Okta.Core.Clients.OktaClient..ctor(String apiToken, String subdomain)
at Hakata.Web.Services.Security.MFA.MultiFactorAuthService..ctor(String apiToken, String appSubdomain) in C:\Source2013\Cyrus\Cyrus3\tools\TwoFactorAuthDisco\B-10014-C3-OKTA\Hakata.Web\Services\Security\MFA\IMultiFactorAuthService.cs:line 29
at Hakata.Test.Integration.Security.MultiFactorAuthTests.CreateService() in C:\Source2013\Cyrus\Cyrus3\tools\TwoFactorAuthDisco\B-10014-C3-OKTA\Hakata.Test.Integration\Security\MultiFactorAuthTests.cs:line 23
at Hakata.Test.Integration.Security.MultiFactorAuthTests.Previously_Enrolled_User_Has_Sms_Factor() in C:\Source2013\Cyrus\Cyrus3\tools\TwoFactorAuthDisco\B-10014-C3-OKTA\Hakata.Test.Integration\Security\MultiFactorAuthTests.cs:line 13
--TypeInitializationException
at Okta.Core.Utils.GetAssemblyVersion()
at Okta.Core.Constants..cctor()
--FileLoadException
at Okta.Core.Utils..cctor()

Generate User-Agent from SDK assembly version

From this list of baseline SDK features: https://oktawiki.atlassian.net/wiki/display/PM/Baseline+Management+SDK+features

  • The RequestExecutor needs to attach the UserAgent header to every outgoing request.
  • The User-Agent value should contain the SDK version and potentially some other info. Generated at startup time and cached
  • Check with the other SDK authors to see what format they are using for the User-Agent value

We did a similar thing in the Stormpath SDK: https://github.com/stormpath/stormpath-sdk-dotnet/blob/develop/src/Stormpath.SDK.Core/Impl/Client/DefaultUserAgentBuilder.cs#L39-L58

Rename repo

This repo should be oktasdk-dotnet. Github can redirect the existing name to the new name.

Add IUser.ChangePassword method

This method needs special handling to make it nice for the developer.

Original generated method:

/// <inheritdoc />
public Task<UserCredentials> ChangePasswordAsync(ChangePasswordOptions options, CancellationToken cancellationToken = default(CancellationToken))
    => new UserClient(GetDataStore()).ChangePasswordAsync(this, Id, cancellationToken);

Code cleanup

After recent PRs are merged,

  • Remove GetBodyAsync
  • Rename QueryParams -> QueryParameters
  • Rename PathParams -> PathParameters
  • Rename ResourceDictionaryType -> ResourceBehavior

orgFactorsClient.GetFactor always null

I'm calling orgFactorsClient.GetFactor("okta_sms") and it returns null. In Fiddler I can see this JSON comes back:

"id": "okta_sms",
"provider": "OKTA",
"factorType": "sms",
"status": "ACTIVE",

but the object is null. The internal implementation looks like this - it has a check on id matching but it doesn't set factor = result or return result so it's always null.

public virtual Factor GetFactor(string strMfaType)
    {
      Factor factor = (Factor) null;
      foreach (OktaObject result in (IEnumerable<Factor>) this.GetList((Uri) null, 200, (FilterBuilder) null, SearchType.Filter, (string) null, (string) null, new DateTime?()).Results)
      {
        if (result.Id == strMfaType)
          break;
      }
      return factor;
    }

This method is also a bit misleading as it makes me think I'm fetching a single factor but really it's pulling back all of them and then filtering the list down in memory. So it's a bit wasteful from a resource and performance standpoint.

Pin base URL

  • Check that the resource/request URL matches the client's configured Okta org URL when sending requests
  • Write an integration test

Add IGroup.AssignRole method

This method needs special handling to make it nice for the developer.

Original generated method:

/// <inheritdoc />
public Task<MediationRoleAssignment> AssignRoleToUserAsync(CancellationToken cancellationToken = default(CancellationToken))
    => new UserClient(GetDataStore()).AssignRoleToUserAsync(this, Id, cancellationToken);

Expose logging interface

The SDK should expose a logging interface that the developer can plug a logger into, to get trace logs and other details from inside the SDK.

Update readme/quickstart for v1.0

  • Instantiating the client
  • Instantiating + configuring the client
  • Getting a user
  • Creating a new user
  • Updating a user
  • Deleting a user
  • Adding a user to a group

Add IUser.ForgotPasswordWithRecoveryAnswer method

This method needs special handling to make it nice for the developer.

Original generated method:

/// <inheritdoc />
public Task<BaseCredentialsObject> ForgotPasswordWithRecoveryAnswerAsync(bool? sendEmail, CancellationToken cancellationToken = default(CancellationToken))
    => new UserClient(GetDataStore()).ForgotPasswordWithRecoveryAnswerAsync(this, Id, sendEmail, cancellationToken);

Add IUser.AddRole method

This method needs special handling to make it nice for the developer.

Original generated method:

/// <inheritdoc />
public Task<Role> AddRoleAsync(CancellationToken cancellationToken = default(CancellationToken))
    => new UserClient(GetDataStore()).AddRoleToUserAsync(this, Id, cancellationToken);

Get-OktaUser : Error making an HTTP request: One or more errors occurred.

The Get-OktaUser cmdlet no longer retrieves all users. It still works when I specify a single user.

The direct API still seems to work via curl.

curl -v -X GET -H "Accept: application/json" -H "Content-Type: application/json" -H "Authorization: SSWS %1" "https://%2.okta.com/api/v1/users/"

This is the PS exception I get. Has anyone else seen this?

PS C:\temp> Get-OktaUser
Get-OktaUser : Error making an HTTP request: One or more errors occurred.
At line:1 char:1
+ Get-OktaUser
+ ~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [Get-OktaUser], OktaException
    + FullyQualifiedErrorId : Okta.Core.OktaException,Okta.Core.Automation.Get
   OktaUser

Security review

Since there is an entirely new codebase for v1.0.0, we need a security review on the new code.

Client slow after 3 requests

I have a program that gets a list of my groups, then prints each group Id. The program runs quickly (~ 3 seconds) the first 3 times I run it, but after that it takes ~28 seconds to run. This only occurs if I am running the exe several times, if I put the code in a for loop and run it 10 times the first loop iteration takes ~28 seconds, then each subsequent iteration takes less than a second.
My code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OktaAPI;
using Okta.Core;
using Okta.Core.Clients;
using Okta.Core.Models;

namespace OktaAPIOut
{
    class Program
    {
        static void Main(string[] args)
        {
            var oktaClient = new OktaClient("oktapikey", new Uri("myoktatenant"));

            var groupClient = oktaClient.GetGroupsClient();
            var groupList = groupClient.GetList();
            foreach (var group in groupList.Results)
            {
                Console.WriteLine("group:" + group.Id);
            }
            Console.ReadKey();
        }
    }
}

The issue is similar to this: http://stackoverflow.com/questions/28384438/net-httpclient-postasync-slow-after-3-requests

my .NET version is 4.0.30319

UserClient.SetCredentials gives exception

I get an exception when I try to use UserClient.SetCredentials(string id, LoginCredentials credentials)
It works when I pass in a user but not when i just pass in an Id.

It does a Put request to the wrong url and will always receive a 404 response.

I think BaseClient.Put(id, userWithCredentials.ToJson());
should be replaced with BaseClient.Put(GetResourceUri(id), userWithCredentials.ToJson());

Factors have Id property set to null

Hello Im using version 3.1 of the c sharp cleint.

Im using

var allFactors = factorsClient.GetFactorCatalog();

which works but all the Id properties are null. Without the Id property the challenge Apis calls return an error

Hope you can help

Thanks

OktaClient Does Not Send Authorization Header After Authentication

If an OktaClient is used to submit an Authentication request (which does not require an API key), any subsequent calls from the same client will not have an authorization header.

Steps to reproduce:

  1. Create OktaClient object
  2. Use the client to call a method that requires an API key (e.g. UsersClient.Get()) - this will work
  3. Use the client to call a method that does not require an API key (e.g. AuthClient.Authenticate()) - this will work
  4. Use the client to repeat the same method as in step 2 above - this will fail with "E0000005 - Invalid Session" error because the Authorization header is missing

Tracing through the code, this appears to be caused when during the Authenticate() call, the code calls the underlying Post method with a bAddAuthorizationHeader value of false, which instructs code in the underlying OktaHttpClient to remove the Authorization header from the DefaultRequestHeaders collection, which effectively removes it from all subsequent calls from this client. The only way to get the Authorization header back, is to set the ApiToken property again on the OktaHttpClient, but even this approach can cause issues when more than one thread is accessing the client.

The solution is to add the Authorization header on a per-request as-needed basis instead of a per-client default (DefaultRequestHeaders) as it is implemented now.

Update: Looks like this may also be the root cause for #33.

OktaHttpClient miscalculates the wait when rate-limited

Execute() calculates the wait time thusly:

var unixTime = (Int64)DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1)).TotalMilliseconds;
var millisToWait = unixTime - ((Int64)waitUntilUnixTime * 1000);

Unfortunately if waitUntilUnixTime is the typical 60 seconds into the future, millisToWait will be negative. This doesn't adversely affect things, as Utils.Sleep() ignores negative values, but it does mean the code is continuing to make the same request and receiving 429 errors until the rate limit reset time is reached.

chocolatey install user profile

Ran into an issue on chocolatey install. A user's powershell profile isn't always rooted from the $home dir. The $profile variable might be better. Ex. CocolateyInstall.ps1 line 4
$folder = $profile.Substring(0,($profile.LastIndexOf(""))) + "\Modules$($packageName)"

Write tests against mock server

After mockta is ready, write integration tests to cover these scenarios:

  • Get a user
  • Update a user
  • Delete a user
  • Create a user from scratch
  • Todo (many more)...

Is a simpler example available?

This is not really an issue, more of a request: Can you please provide a simpler example for Okta in C#/ASP.Net that doesn't utilize the music store project?

Not being familiar with the music store project, I find myself spending a ton of time sifting through the code trying to determine where the Okta code resides. It's very confusing for a n00b like me.

My particular use case is a small intranet site locked down via web.config authentication, such as:

<system.webServer>
    <security>
        <authorization>
            <remove users="*" roles="" verbs="" />
            <add accessType="Allow" users="" roles="Administrators" />
        </authorization>
    </security>
</system.webServer>

Can you provide any examples for integrating Okta with this type of authentication?

Thanks!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.