You can install the package by using the NuGet Package Explorer to search for Okta.AspNet.
Or, you can use the dotnet
command:
dotnet add package Okta.AspNet
These examples will help you to understand how to use this library. You can also check out our ASP.NET samples:
Okta plugs into your OWIN Startup class with the UseOktaMvc()
method:
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
app.UseCookieAuthentication(new CookieAuthenticationOptions());
app.UseOktaMvc(new OktaMvcOptions
{
OktaDomain = "https://{yourOktaDomain}",
ClientId = "{clientId}",
ClientSecret = "{clientSecret}",
AuthorizationServerId = "default", // Use string.Empty if you are using the Org Authorization Server
RedirectUri = "http://localhost:8080/authorization-code/callback",
PostLogoutRedirectUri = "http://localhost:8080/Home"
});
}
}
Note: Starting in v3.0.0 you can now configure the authentication type:
.UseOktaMvc("myScheme", oktaMvcOptions);
.
Placing the [Authorize]
attribute on your controllers or actions will check whether the user is logged in, and redirect them to Okta if necessary.
ASP.NET automatically populates HttpContext.User
with the information Okta sends back about the user. You can check whether the user is logged in with User.Identity.IsAuthenticated
in your actions or views.
If your application requires proxy server settings, specify the Proxy
property on OktaMvcOptions
.
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.UseOktaMvc(new OktaMvcOptions
{
// ... other configuration removed for brevity
Proxy = new ProxyConfiguration
{
Host = "http://{yourProxyHostNameOrIp}",
Port = 3128, // Replace this value with the port that your proxy server listens on
Username = "{yourProxyServerUserName}",
Password = "{yourProxyServerPassword}",
}
});
}
}
Note: The proxy configuration is ignored when an
BackchannelHttpClientHandler
is provided.
Starting in Okta.AspNet 2.0.0/Okta.AspNetCore 4.0.0, you can now provide your own HttpMessageHandler implementation to be used by the uderlying OIDC middleware. This is useful if you want to log all the requests and responses to diagnose problems, or retry failed requests among other use cases. The following example shows how to provide your own logging logic via Http handlers:
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.UseOktaMvc(new OktaMvcOptions
{
BackchannelHttpClientHandler = new MyLoggingHandler((logger),
});
}
}
public class MyLoggingHandler : DelegatingHandler
{
private readonly ILogger _logger;
public MyLoggingHandler(ILogger logger)
{
_logger = logger;
}
protected override async Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request,
CancellationToken cancellationToken)
{
_logger.Trace($"Request: {request}");
try
{
var response = await base.SendAsync(request, cancellationToken);
_logger.Trace($"Response: {response}");
return response;
}
catch (Exception ex)
{
_logger.Error($"Something went wrong: {ex}");
throw;
}
}
}
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
app.UseCookieAuthentication(new CookieAuthenticationOptions()
{
LoginPath = new PathString("/Account/Login"),
});
app.UseOktaMvc(new OktaMvcOptions
{
OktaDomain = "https://{yourOktaDomain}",
ClientId = "{clientId}",
ClientSecret = "{clientSecret}",
AuthorizationServerId = "default", // Use string.Empty if you are using the Org Authorization Server
RedirectUri = "http://localhost:8080/authorization-code/callback",
PostLogoutRedirectUri = "http://localhost:8080/Home",
LoginMode = LoginMode.SelfHosted
});
}
}
Note: If you are using role-based authorization and you need to redirect unauthorized users to an access-denied page or similar, check out CookieAuthenticationProvider.ApplyRedirect.
The login_hint
parameter allows you to pass a username to prepopulate when prompting for authentication. For more details check out the Okta documentation.
Add the following action in your controller:
public ActionResult Login()
{
if (!HttpContext.User.Identity.IsAuthenticated)
{
var properties = new AuthenticationProperties();
properties.Dictionary.Add(OktaParams.LoginHint, "darth.vader@imperial-senate.gov");
properties.RedirectUri = "/Home/About";
HttpContext.GetOwinContext().Authentication.Challenge(properties,
OktaDefaults.MvcAuthenticationType);
return new HttpUnauthorizedResult();
}
return RedirectToAction("Index", "Home");
}
Parameter | Description | Required? |
---|---|---|
acr_values |
When included in the authentication request, increases the level of user assurance. | No |
prompt |
Indicate the pipeline the intent of the request, such as, support enrollment of a new factor. | No |
enroll_amr_values |
A space-delimited, case-sensitive string that represents a list of authenticator method references. | No |
Note: When
prompt
is equals toenroll_authenticator
you have to indicate the URL that Okta should send callback to after the user app sends the enrollment request. Theredirect_uri
cannot be the same as the normal OIDC flow/authorization_code/callback
since there's no code involved in this flow. Instead, you have to specify a callback URI (which has to be added to your application's allowed URLs in your Okta dashboard) in your application where, for example, you can process the response and redirect accordingly. Also, it's expected you already have a session before triggering the authenticator enrollment flow.
For more details see the Okta documentation.
Add the following action in your controller:
public ActionResult TriggerEnroll()
{
if (!HttpContext.User.Identity.IsAuthenticated)
{
var properties = new AuthenticationProperties();
properties.Dictionary.Add(OktaParams.AcrValues, "urn:okta:loa:1fa:pwd");
properties.Dictionary.Add(OktaParams.Prompt, "enroll_authenticator");
properties.Dictionary.Add(OktaParams.EnrollAmrValues, "sms okta_verify");
properties.RedirectUri = "https://localhost:44314/Account/EnrollCallback";
HttpContext.GetOwinContext().Authentication.Challenge(properties,
OktaDefaults.MvcAuthenticationType);
return new HttpUnauthorizedResult();
}
return RedirectToAction("Index", "Home");
}
public ActionResult EnrollCallback()
{
//...
// If enrollment was successful
return RedirectToAction("Index", "Home");
}
Add the following action in your controller:
public ActionResult LoginWithIdp(string idp)
{
if (!HttpContext.User.Identity.IsAuthenticated)
{
var properties = new AuthenticationProperties();
properties.Dictionary.Add(OktaParams.Idp, idp);
properties.RedirectUri = "/Home/About";
HttpContext.GetOwinContext().Authentication.Challenge(properties,
OktaDefaults.MvcAuthenticationType);
return new HttpUnauthorizedResult();
}
return RedirectToAction("Index", "Home");
}
The Okta.AspNet library will include your identity provider id in the authorize URL and the user will prompted with the identity provider login. For more information, check out our guides to add an external identity provider.
For your convenience, the Okta.AspNet library makes OIDC tokens available as user claims accessible from a controller in your application. The following is an example of how to access OIDC tokens from your HomeController
:
public class HomeController : Controller
{
[Authorize]
public async Task<ActionResult> Claim(string claimType)
{
var claim = HttpContext.GetOwinContext().Authentication.User.Claims.First(c => c.Type == claimType);
return View(claim);
}
}
This example assumes you have a view called Claim
whose model is of type System.Security.Claims.Claim
. The claim types for OIDC tokens are id_token
and access_token
as well as refresh_token
if available.
This library exposes OpenIdConnectEvents so you can hook into specific events during the authentication process.
The following is an example of how to use events to add custom claims to the token:
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.UseOktaMvc(new OktaMvcOptions()
{
// ... other configuration options removed for brevity ...
OpenIdConnectEvents = new OpenIdConnectAuthenticationNotifications
{
SecurityTokenValidated = (notification) =>
{
notification.AuthenticationTicket.Identity.AddClaim(new Claim("CodeCustomClaimKey", "CodeCustomClaimValue"));
return Task.CompletedTask;
}
},
});
}
}
Note: For more information see
SecurityTokenValidated
The following is an example of how to use events to handle failures:
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.UseOktaMvc(new OktaMvcOptions()
{
// ... other configuration options removed for brevity ...
OpenIdConnectEvents = new OpenIdConnectAuthenticationNotifications
{
AuthenticationFailed = OnAuthenticationFailed,
},
});
}
public async Task OnAuthenticationFailed(AuthenticationFailedNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> notification)
{
await Task.Run(() =>
{
notification.Response.Redirect("{YOUR-EXCEPTION-HANDLING-ENDPOINT}?message=" + notification.Exception.Message);
notification.HandleResponse();
});
}
}
Note: For more information see
AuthenticationFailed
The OktaMvcOptions
class configures the Okta middleware. You can see all the available options in the table below:
Property | Required? | Details |
---|---|---|
OktaDomain | Yes | Your Okta domain, i.e https://dev-123456.oktapreview.com |
ClientId | Yes | The client ID of your Okta Application |
ClientSecret | Yes | The client secret of your Okta Application |
RedirectUri | Yes | The location Okta should redirect to process a login. This is typically http://{yourApp}/authorization-code/callback . No matter the value, the redirect is handled automatically by this package, so you don't need to write any custom code to handle this route. |
AuthorizationServerId | No | The Okta Authorization Server to use. The default value is default . Use string.Empty if you are using the Org Authorization Server |
PostLogoutRedirectUri | No | The location Okta should redirect to after logout. If blank, Okta will redirect to the Okta login page. |
Scope | No | The OAuth 2.0/OpenID Connect scopes to request when logging in. The default value is openid profile . |
LoginMode | No | LoginMode controls the login redirect behavior of the middleware. The default value is OktaHosted . |
GetClaimsFromUserInfoEndpoint | No | Whether to retrieve additional claims from the UserInfo endpoint after login. The default value is true . |
ClockSkew | No | The clock skew allowed when validating tokens. The default value is 2 minutes. |
OpenIdConnectEvents | No | Specifies the events which the underlying OpenIdConnectHandler invokes to enable developer control over the authentication process. |
Proxy | No | An object describing proxy server configuration. Properties are Host , Port , Username and Password |
BackchannelTimeout | No | Timeout value in milliseconds for back channel communications with Okta. The default value is 1 minute. |
BackchannelHttpClientHandler | No | The HttpMessageHandler used to communicate with Okta. |
You can store these values (except the Token event) in the Web.config
, but be careful when checking in the client secret to the source control.
Note: You can use the The Org Authorization Server for common use cases such as adding authentication to your MVC Application or checking user's profile, but the access token issued by this Authorization Server cannot be used or validated by your own applications. Check out the Okta documentation to learn more.
If you are using .NET framework <4.6 or you are getting the following error: The request was aborted: Could not create SSL/TLS secure channel
. Make sure to include the following code in the Application_Start
or Startup
:
// Enable TLS 1.2
ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls12;