Integration ASP.NET MVC + WebAPI + Okta


#1

HI All, I am newbie, doing third party Authentication for the first time,

I am developing a .NET MVC project which contains also a .NET WebAPI endpoint, I have successfully integrated the single sign on following this guidelines:

This is the authentication code I am using in the backend (I am using cookies as authentication approach):

public static void Configure(IAppBuilder app, IAppConfiguration appConfig)
{
	app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);

	app.UseCookieAuthentication(new CookieAuthenticationOptions
	{
		AuthenticationType = CookieAuthenticationDefaults.AuthenticationType
	});

	app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
	{
		ClientId = appConfig.OktaClientId,
		ClientSecret = appConfig.OktaClientSecret,
		Authority = appConfig.OktaIssuer,
		RedirectUri = appConfig.OktaRedirectUri,
		ResponseType = OpenIdConnectResponseType.CodeIdToken,
		Scope = OpenIdConnectScope.OpenIdProfile,
		PostLogoutRedirectUri = appConfig.OktaLogoutRedirectUri,
		TokenValidationParameters = new TokenValidationParameters
		{
			NameClaimType = "name"
		},

		Notifications = new OpenIdConnectAuthenticationNotifications
		{
			AuthorizationCodeReceived = async n =>
			{
				var tokenClient = new TokenClient(appConfig.OktaOrganizationUri + "/v1/token", appConfig.OktaClientId, appConfig.OktaClientSecret);
				var tokenResponse = await tokenClient.RequestAuthorizationCodeAsync(n.Code, appConfig.OktaRedirectUri).ConfigureAwait(false);

				if (tokenResponse.IsError)
				{
					throw new AuthenticationException(tokenResponse.Error);
				}

				var userInfoClient = new UserInfoClient(appConfig.OktaOrganizationUri + "/v1/userinfo");
				var userInfoResponse = await userInfoClient.GetAsync(tokenResponse.AccessToken).ConfigureAwait(false);

				var identity = new ClaimsIdentity();
				identity.AddClaims(userInfoResponse.Claims);

				identity.AddClaim(new Claim("id_token", tokenResponse.IdentityToken));
				identity.AddClaim(new Claim("access_token", tokenResponse.AccessToken));

				if (!string.IsNullOrEmpty(tokenResponse.RefreshToken))
				{
					identity.AddClaim(new Claim("refresh_token", tokenResponse.RefreshToken));
				}

				var nameClaim = new Claim(ClaimTypes.Name, userInfoResponse.Claims.FirstOrDefault(c => c.Type == "name")?.Value);
				identity.AddClaim(nameClaim);

				n.AuthenticationTicket = new AuthenticationTicket(
					new ClaimsIdentity(identity.Claims, n.AuthenticationTicket.Identity.AuthenticationType),
					n.AuthenticationTicket.Properties);
			},

			RedirectToIdentityProvider = n =>
			{
				if (n.ProtocolMessage.RequestType == OpenIdConnectRequestType.Logout)
				{
					var idTokenClaim = n.OwinContext.Authentication.User.FindFirst("id_token");

					if (idTokenClaim != null)
					{
						n.ProtocolMessage.IdTokenHint = idTokenClaim.Value;
					}
				}

				return Task.CompletedTask;
			}
		}
	});
}

My login action controller is as follows:

[Route("accounts"), Route("accounts/login")]
public ActionResult Login()
{
	if (!HttpContext.User.Identity.IsAuthenticated)
	{
		HttpContext.GetOwinContext().Authentication.Challenge(OpenIdConnectAuthenticationDefaults.AuthenticationType);
		return new HttpUnauthorizedResult();
	}

	if (HttpContext.Session["loggedUser"] == null)
	{
		var principal = HttpContext.GetOwinContext().Authentication.User;

		HttpContext.Session["loggedUser"] = new OktaLoggedUser(principal);
	}

	return RedirectToAction("Index", "Installations");
}

However, in order to consume the API, I need get the access token from the Javascript code since the API controllers are authenticated if there is a valid Okta access token in the Authorization header:

ajax: {
	url: "/resources",
	type: "GET",
	datatype: "json",
	beforeSend: function (request) {
		request.setRequestHeader("Auhtorization", OKTA_ACCESS_TOKEN);
	},
}

I ignore if there is any okta javascript library I can use to get the access token or maybe the backend configuration I am using is wrong …

I gave a try to the Sign-in widget, but even after using the method setCookiesAndRedirect, the web request is not authenticated in the back-end …

Regards


#2

Carlos, I am running into the same issue - I’m using the Okta hosted login page to get authenticated, but now I need to call an API with the access token, and I’m not sure how to get access the access token.

Did you ever find the solution to this?

Chad