This library is built for server-side projects in .NET to communicate with Okta as an OAuth 2.0 + OpenID Connect provider. It works with the Okta's Identity Engine to authenticate and register users.
To see this library working in a sample, check out our ASP.NET Samples. You can also check out our guides for step-by-step instructions:
❕ The use of this SDK requires usage of the Okta Identity Engine. This functionality is in general availability but is being gradually rolled out to customers. If you want to request to gain access to the Okta Identity Engine, please reach out to your account manager. If you do not have an account manager, please reach out to oie@okta.com for more information.
This library is currently GA. See release status for more information.
- Release status
- Need help?
- Getting started
- Usage guide
- Configuration reference
- Building the SDK
- Contributing
This library uses semantic versioning and follows Okta's Library Version Policy.
✔️ The current stable major version series is: 1.x
| Version | Status |
|---|---|
| 1.0.0 | ✔️ 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)
You will need:
- An Okta account, called an organization (sign up for a free developer organization if you need one)
These examples will help you understand how to use this library.
Once you initialize a Client, you can call methods to make requests to the Okta API. Check out the Configuration reference section for more details.
var client = new IdxClient(new IdxConfiguration()
{
Issuer = "{YOUR_ISSUER}", // e.g. https://foo.okta.com/oauth2/default, https://foo.okta.com/oauth2/ausar5vgt5TSDsfcJ0h7
ClientId = "{YOUR_CLIENT_ID}",
ClientSecret = "{YOUR_CLIENT_SECRET}", //Required for confidential clients.
RedirectUri = "{YOUR_REDIRECT_URI}", // Must match the redirect uri in client app settings/console
Scopes = "openid profile offline_access",
});var authnOptions = new AuthenticationOptions
{
Username = "username@mail.com",
Password = "superSecretPassword",
};
var authnResponse = await _idxClient.AuthenticateAsync(authnOptions).ConfigureAwait(false);
if (authn.AuthenticationStatus == AuthenticationStatus.Success)
{
var accessToken = authnResponse.TokenInfo.AccessToken;
}The AuthenticationResponse you get when using the IdxClient will indicate how to proceed to continue with the authentication flow. When using the AuthenticateAsync method you can get the following statuses:
Type: AuthenticationStatus.Success
The user was successfully authenticated and you can retrieve the tokens from the response by calling authnResponse.TokenInfo.
Type: AuthenticationStatus.PasswordExpired
The user needs to change their password to continue with the authentication flow and retrieve tokens.
Type: AuthenticationStatus.AwaitingAuthenticatorEnrollment
The user needs to enroll an authenticator to continue with the authentication flow and retrieve tokens. You can retrieve the authenticators information by calling authnResponse.Authenticators.
Type: AwaitingChallengeAuthenticatorSelection
The user needs to select and challenge an additional authenticator to continue with the authentication flow and retrieve tokens. You can retrieve the authenticators information by calling authnResponse.Authenticators.
There other statuses that you can get when calling other methods of the IdxClient:
Type: AwaitingAuthenticatorVerification
The user has successfully selected an authenticator to challenge so they now need to verify the selected authenticator. For example, if the user selected phone, this status indicates that they have to provide they code they received to verify the authenticator.
Type: AwaitingAuthenticatorEnrollmentData
The user needs to provide additional authenticator information. For example, when a user selects to enroll phone they will have to provide their phone number to complete the enrollment process. You can retrieve current authenticator information by calling authnResponse.CurrentAuthenticator.
Type: AwaitingChallengeAuthenticatorData
The user needs to provide additional authenticator information. For example, when a user selects to challenge phone they will have to choose if they want to receive the code via voice or SMS. You can retrieve current authenticator enrollment information by calling authnResponse.CurrentAuthenticatorEnrollment.
Type: AwaitingPasswordReset
The user needs to reset their password to continue with the authentication flow and retrieve tokens.
await _idxClient.RevokeTokensAsync(TokenType.AccessToken, accessToken);// UserProfile is a dynamic class that allows you set properties dinamically
var userProfile = new UserProfile();
userProfile.SetProperty("firstName", model.FirstName);
userProfile.SetProperty("lastName", model.LastName);
userProfile.SetProperty("email", model.Email);
var registerResponse = await _idxClient.RegisterAsync(userProfile);
if (registerResponse.AuthenticationStatus == AuthenticationStatus.Success)
{
// Retrieve tokens
}Note: Check the response's
AuthenticatonStatusproperty to determine what the next step is.
var recoverPasswordOptions = new RecoverPasswordOptions { Username = model.UserName, };
var authnResponse = await _idxClient.RecoverPasswordAsync(recoverPasswordOptions);Note: Check the response's
AuthenticatonStatusproperty to determine what the next step is.
The SDK throws an OktaException everytime the server responds with an invalid status code, or there is an internal error. You can get more information by calling exception.Message.
UnexpectedRemediationException is an OktaException derived class that usually indicates inconsistencies in the configuration. It is recommended to verify your policy configuration when you face with this error.
RedeemInteractionCodeException is an OktaException derived class that indicates there was an error when redeeming the interaction code.
TerminalStateException is an OktaException derived class that indicates that the user cannot continue the current flow, possibly due to an error or required additional actions outside of the authentication flow.
This exception object contains an array of messages that can be shown to the user as they are. Each message object in the array also contains a key property that can be used for internationalization. Here is an example of accessing the exception data. All the properties can be null. Null checks are not shown in the example.
try
{
// Trying to sign-on with a non-existent user name.
// The exact error depends on the Org settings and may differ.
}
catch (TerminalStateException exception)
{
string combinedTextMessage = exception.Message; // "There is no account with the Username non-existentuser@somewhere.com."
IList<IMessage> allMessages = exception.IdxMessages.Messages;
IMessage firstMessage = allMessages.First();
string firstMessageText = firstMessage.Text; // "There is no account with the Username non-existentuser@somewhere.com."
IIdxI18n firstMessageI18nInfo = firstMessage.I18n;
string firstMessageI18nKey = firstMessageI18nInfo.Key; // "idx.unknown.user"
IList<string> firstMessageI18nParams = firstMessageI18nInfo.Params; // an empty list
//.........................
}For more usage examples check out our ASP.NET Sample Application.
This library looks for configuration in the following sources:
- An
okta.yamlfile in a.oktafolder in the current user's home directory (~/.okta/okta.yamlor%userprofile%\.okta\okta.yaml) - An
okta.yamlfile in a.oktafolder 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:
idx:
issuer: "https://{yourOktaDomain}/oauth2/{authorizationServerId}" # e.g. https://foo.okta.com/oauth2/default, https://foo.okta.com/oauth2/ausar5vgt5TSDsfcJ0h7
clientId: "{clientId}"
clientSecret: "{clientSecret}" # Required for confidential clients
scopes:
- "{scope1}"
- "{scope2}"
redirectUri: "{redirectUri}"Each one of the configuration values above can be turned into an environment variable name with the _ (underscore) character:
OKTA_IDX_ISSUEROKTA_IDX_CLIENTIDOKTA_IDX_CLIENTSECRETOKTA_IDX_REDIRECTURI
You can optionally set OKTA_IDX_SCOPES via env vars. Since this is an array you have to specify it in the following way:
OKTA_IDX_SCOPES_0 = "{scope0}"
OKTA_IDX_SCOPES_1 = "{scope1}"
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 are happy to accept contributions and PRs! Please see the contribution guide to understand how to structure a contribution.
