- Release status
- Need help?
- Getting started
- Usage guide
- Configuration reference
- Building the SDK
- Contributing
This repository contains the Okta Authentication SDK for .NET which is used in your server-side code to interact with the Okta Authentication API.
For high level information about the features of the Okta Authentication product see Okta Authentication.
⚠️ NOTE: Using OAuth 2.0 or OpenID Connect to integrate your application instead of this library requires much less work, and has a smaller risk profile. Please see this guide to see if using this API is right for your use case. You could also use our ASP.NET Integration out of the box.
Okta's Authentication API is built around a state machine. In order to use this library you will need to be familiar with the available states.
For more information about multifactor authentication see the multifactor authentication guide.
We also publish these other libraries for .NET:
You can learn more on the Okta + .NET page in our documentation.
This library uses semantic versioning and follows Okta's library version policy.
✔️ The current stable major version series is: 2.x
Version | Status |
---|---|
1.x | |
2.x | ✔️ Stable |
The latest release can always be found on the releases page.
If you run into problems using the SDK, you can
- Ask questions on the Okta Developer Forums
- Post issues here on GitHub (for code errors)
The SDK is compatible with:
- .NET Standard 2.0 and 2.1
- .NET Framework 4.6.1 or higher
- .NET Core 3.0 or higher
- .NET 5.0
- Right-click on your project in the Solution Explorer and choose Manage Nuget Packages...
- Search for Okta. Install the
Okta.Auth.Sdk
package.
Simply run install-package Okta.Auth.Sdk
. Done!
You'll also need:
- An Okta account, called an organization (sign up for a free developer organization if you need one)
Construct a client instance by passing it your Okta domain name:
var client = new AuthenticationClient(new OktaClientConfiguration
{
OktaDomain = "https://{{yourOktaDomain}}",
});
Hard-coding the Okta domain works for quick tests, but for real projects you should use a more secure way of storing your Organization values (such as environment variables). This library supports a few different configuration sources, covered in the configuration reference section.
These examples will help you understand how to use this library.
Once you initialize an AuthenticationClient
, you can call methods to make requests to the Okta API.
var authnOptions = new AuthenticateOptions()
{
Username = $"darth.vader@imperial-senate.gov",
Password = "D1sturB1ng!",
};
var authnResponse = await authClient.AuthenticateAsync(authnOptions);
var authnOptions = new AuthenticateWithActivationTokenOptions()
{
ActivationToken = "foo",
};
var authnResponse = await authClient.AuthenticateAsync(authnOptions);
var changePasswordOptions = new ChangePasswordOptions()
{
StateToken = "foo",
OldPassword = "Okta4321!",
NewPassword = "Okta1234!",
};
var authnResponse = await authClient.ChangePasswordAsync(changePasswordOptions);
var enrollOptions = new EnrollSecurityQuestionFactorOptions()
{
Question = "name_of_first_plush_toy",
Answer = "blah",
StateToken = "foo",
};
var authnResponse = await authnClient.EnrollFactorAsync(enrollOptions);
var enrollOptions = new EnrollSMSFactorOptions()
{
PhoneNumber = "+1 415 555 5555",
StateToken = "foo",
};
var authnResponse = await authnClient.EnrollFactorAsync(enrollOptions);
var enrollFactorOptions = new EnrollCallFactorOptions()
{
PhoneNumber = "+1-555-415-1337",
StateToken = "foo",
};
var authnResponse = await authnClient.EnrollFactorAsync(enrollFactorOptions);
var enrollOptions = new EnrollTotpFactorOptions()
{
StateToken = "foo",
Provider = OktaDefaults.GoogleProvider,
};
var authnResponse = await authnClient.EnrollFactorAsync(enrollOptions);
var enrollOptions = new EnrollPushFactorOptions()
{
StateToken = "foo",
};
var authnResponse = await authnClient.EnrollFactorAsync(enrollOptions);
var enrollOptions = new EnrollRsaFactorOptions()
{
StateToken = "foo",
CredentialId = "dade.murphy@example.com",
PassCode = "bar",
};
var authnResponse = await authnClient.EnrollFactorAsync(enrollOptions);
var enrollOptions = new EnrollSymantecFactorOptions()
{
StateToken = "foo",
CredentialId = "dade.murphy@example.com",
PassCode = "bar",
NextPassCode = "baz",
};
var authnResponse = await authnClient.EnrollFactorAsync(enrollOptions);
var enrollOptions = new EnrollYubiKeyFactorOptions()
{
PassCode = "bar",
StateToken = "foo",
};
var authnResponse = await authnClient.EnrollFactorAsync(enrollOptions);
var enrollOptions = new EnrollDuoFactorOptions()
{
StateToken = "foo",
};
var authnResponse = await authnClient.EnrollFactorAsync(enrollOptions);
var enrollOptions = new EnrollU2FFactorOptions()
{
StateToken = "foo",
};
var authnResponse = await authnClient.EnrollFactorAsync(enrollOptions);
var activateFactorOptions = new ActivateU2fFactorOptions()
{
FactorId = "ostf1fmaMGJLMNGNLIVG",
StateToken = "foo",
RegistrationData = "bar",
ClientData = "baz",
};
var authResponse = await authnClient.ActivateFactorAsync(activateFactorOptions);
var activatePushFactorOptions = new ActivatePushFactorOptions()
{
StateToken = "foo",
FactorId = "bar",
};
var authResponse = await authnClient.ActivateFactorAsync(activatePushFactorOptions);
var activateFactorOptions = new ActivateFactorOptions()
{
StateToken = "00xdqXOE5qDXX8-PBR1bYv8AESqIEinDy3yul01tyh",
FactorId = "foo",
PassCode = "bar",
};
var authResponse = await authnClient.ActivateFactorAsync(activateFactorOptions);
var verifyFactorOptions = new VerifySmsFactorOptions()
{
StateToken = "foo",
FactorId = "bar",
};
var authResponse = await authnClient.VerifyFactorAsync(verifyFactorOptions);
var verifyFactorOptions = new VerifyCallFactorOptions()
{
FactorId = "ostf1fmaMGJLMNGNLIVG",
StateToken = "foo",
PassCode = "bar",
RememberDevice = true,
};
var authResponse = await authnClient.VerifyFactorAsync(verifyFactorOptions);
var verifyFactorOptions = new VerifySecurityQuestionFactorOptions()
{
FactorId = "ostf1fmaMGJLMNGNLIVG",
StateToken = "foo",
Answer = "bar",
};
var authResponse = await authnClient.VerifyFactorAsync(verifyFactorOptions);
var verifyFactorOptions = new VerifySmsFactorOptions()
{
FactorId = "ostf1fmaMGJLMNGNLIVG",
StateToken = "foo",
PassCode = "bar",
RememberDevice = true,
};
var authResponse = await authnClient.VerifyFactorAsync(verifyFactorOptions);
var verifyFactorOptions = new VerifyPushFactorOptions()
{
FactorId = "ostf1fmaMGJLMNGNLIVG",
StateToken = "foo",
AutoPush = true,
RememberDevice = true,
};
var authResponse = await authnClient.VerifyFactorAsync(verifyFactorOptions);
var verifyFactorOptions = new VerifyDuoFactorOptions()
{
FactorId = "ostf1fmaMGJLMNGNLIVG",
StateToken = "foo",
};
var authResponse = await authnClient.VerifyFactorAsync(verifyFactorOptions);
var verifyFactorOptions = new VerifyU2FFactorOptions()
{
FactorId = "ostf1fmaMGJLMNGNLIVG",
StateToken = "foo",
ClientData = "bar",
SignatureData = "baz",
RememberDevice = true,
};
var authResponse = await authnClient.VerifyFactorAsync(verifyFactorOptions);
var unlockAccountOptions = new UnlockAccountOptions()
{
FactorType = new FactorType(factorType),
RelayState = "/myapp/some/deep/link/i/want/to/return/to",
Username = "dade.murphy@example.com",
};
await authnClient.UnlockAccountAsync(unlockAccountOptions);
var resetPasswordOptions = new ResetPasswordOptions()
{
NewPassword = "1234",
StateToken = "00xdqXOE5qDXX8-PBR1bYv8AESqIEinDy3yul01tyh",
};
var authResponse = await authnClient.ResetPasswordAsync(resetPasswordOptions);
var verifyFactorOptions = new VerifyRecoveryTokenOptions()
{
RecoveryToken = "foo",
};
await authnClient.VerifyRecoveryTokenAsync(verifyFactorOptions);
var verifyFactorOptions = new VerifyRecoveryFactorOptions()
{
StateToken = "foo",
PassCode = "bar",
FactorType = new FactorType(factorType),
};
await authnClient.VerifyRecoveryFactorAsync(verifyFactorOptions);
var answerRecoveryQuestionOptions = new AnswerRecoveryQuestionOptions()
{
StateToken = "foo",
Answer = "bar",
};
await authnClient.AnswerRecoveryQuestionAsync(answerRecoveryQuestionOptions);
var transactionStateOptions = new TransactionStateOptions()
{
StateToken = "foo",
};
await authnClient.GetTransactionStateAsync(transactionStateOptions);
var transactionStateOptions = new TransactionStateOptions()
{
StateToken = "foo",
};
await authnClient.GetPreviousTransactionStateAsync(transactionStateOptions);
var transactionStateOptions = new TransactionStateOptions()
{
StateToken = "foo",
};
await authnClient.SkipTransactionStateAsync(transactionStateOptions);
var transactionStateOptions = new TransactionStateOptions()
{
StateToken = "foo",
};
await authnClient.CancelTransactionStateAsync(transactionStateOptions);
The scenarios described in this section require you to send additional information in the user-agent
, x-forwarded-for
and x-device-fingerprinting
headers. This SDK allows you to define these headers via method parameters or construct and send custom requests using the AuthenticationClient
.
For more information on this feature and the underlying API call, see the related developer documentation.
var authOptions = new AuthenticateOptions()
{
Username = $"darth.vader@imperial-senate.gov",
Password = "D1sturB1ng!",
MultiOptionalFactorEnroll = false,
WarnBeforePasswordExpired = false,
DeviceToken = "26q43Ak9Eh04p7H6Nnx0m69JqYOrfVBY",
UserAgent = "Chrome/46.0.2490.86",
XForwardedFor = "23.235.46.133",
};
await authnClient.AuthenticateAsync(authOptions);
For more information on this feature and the underlying API call, see the related developer documentation.
var authOptions = new AuthenticateOptions()
{
ActivationToken = "o7AFoTGE9xjQiHQK6dAa",
UserAgent = "Chrome/46.0.2490.86",
XForwardedFor = "23.235.46.133",
};
await authnClient.AuthenticateAsync(authOptions);
For more information on this feature and the underlying API call, see the related developer documentation.
var authOptions = new AuthenticateOptions()
{
Username = $"darth.vader@imperial-senate.gov",
Password = "D1sturB1ng!",
UserAgent = "Chrome/46.0.2490.86",
XForwardedFor = "23.235.46.133",
DeviceFingerprint = "device_fingerprint"
};
await authnClient.AuthenticateAsync(authOptions);
For more information on this feature and the underlying API call, see the related developer documentation.
var forgotPasswordOptions = new ForgotPasswordOptions()
{
FactorType = FactorType.Call,
RelayState = "/myapp/some/deep/link/i/want/to/return/to",
UserName = "bob-user@test.com",
UserAgent = "Chrome/46.0.2490.86",
XForwardedFor = "23.235.46.133",
};
await authnClient.ForgotPasswordAsync(forgotPasswordOptions);
For more information on this feature and the underlying API call, see the related developer documentation.
var unlockAccountOptions = new UnlockAccountOptions()
{
FactorType = new FactorType("sms"),
RelayState = "/myapp/some/deep/link/i/want/to/return/to",
Username = "dade.murphy@example.com",
UserAgent = "Chrome/46.0.2490.86",
XForwardedFor = "23.235.46.133",
};
await authnClient.UnlockAccountAsync(unlockAccountOptions);
The Authentication Client object allows you to send custom requests that you can construct and set your desired headers. Check out Call other API endpoints section for more details.
The Authentication Client object allows you to construct and send a request to an Authentication API endpoint that isn't represented by a method in the SDK.
Also, you can make calls to any Okta API (not just the endpoints officially supported by the SDK) via the GetAsync
, PostAsync
, PutAsync
and DeleteAsync
methods.
For example, to send a forgot password request using the PostAsync
method (instead of ForgotPasswordAsync
):
var forgotPasswordOptions = new ForgotPasswordOptions()
{
FactorType = FactorType.Email,
RelayState = "/myapp/some/deep/link/i/want/to/return/to",
UserName = "bob-user@test.com",
};
var request = new HttpRequest()
{
Uri = "/api/v1/authn/recovery/password",
Payload = forgotPasswordOptions,
};
request.Headers["User-Agent"] = "MyUserAgentInfo";
var authResponse = await authnClient.PostAsync<AuthenticationResponse>(request);
In this case, there is no benefit to using PostAsync
instead of ForgotPasswordAsync
. However, this approach can be used to call any endpoints that are not represented by methods in the SDK.
This library looks for configuration in the following sources:
- An
okta.yaml
file in a.okta
folder in the current user's home directory (~/.okta/okta.yaml
or%userprofile\.okta\okta.yaml
) - An
okta.yaml
file in a.okta
folder in the application or project's root directory - Environment variables
- 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.
The full YAML configuration looks like:
okta:
client:
connectionTimeout: 30 # seconds
oktaDomain: "https://{yourOktaDomain}"
proxy:
port: null
host: null
token: {apiToken} # optional
Each one of the configuration values above can be turned into an environment variable name with the _
(underscore) character:
OKTA_CLIENT_CONNECTIONTIMEOUT
OKTA_CLIENT_OKTADOMAIN
- and so on
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.
We're happy to accept contributions and PRs! Please see the contribution guide to understand how to structure a contribution.