Hello,
We are in the process of migrating a .Net 4.8 MVC application that uses local users accounts to Okta authentication. My goal is to authenticate the users via Okta and then link the external user with the internal ones (local db).
Using the code below, I encountered 2 issues:
1 - I always get a 400 error when logging out from Okta
2 - First login works fine, then I logout using the code below. On a 2nd attempt to login, in the ExternalLoginCallback method, the loginInfo object is null.
ExternalLoginInfo loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync();
I am using ASPNet.Okta middleware.
//----------------------------------------------------------------
// Startup.cs
//----------------------------------------------------------------
public void ConfigureAuth(IAppBuilder app)
{
//Configure the db context, user manager and signin manager to use a single instance per request
app.CreatePerOwinContext(ApplicationDbContext.Create);
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);
// Enable the application to use a cookie to store information for the signed in user
// and to use a cookie to temporarily store information about a user logging in with a third party login provider
// Configure the sign in cookie
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
//CookieManager = new SystemWebCookieManager(),
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/Account/Login"),
Provider = new CookieAuthenticationProvider
{
// Enables the application to validate the security stamp when the user logs in.
// This is a security feature which is used when you change a password or add an external login to your account.
OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
validateInterval: TimeSpan.FromMinutes(30),
regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager)),
}
});
//app.SetDefaultSignInAsAuthenticationType(DefaultAuthenticationTypes.ExternalCookie);
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
app.UseOktaMvc(new OktaMvcOptions()
{
OktaDomain = ConfigurationManager.AppSettings["okta:OktaDomain"],
ClientId = ConfigurationManager.AppSettings["okta:ClientId"],
ClientSecret = ConfigurationManager.AppSettings["okta:ClientSecret"],
AuthorizationServerId = ConfigurationManager.AppSettings["okta:AuthorizationServerId"],
RedirectUri = ConfigurationManager.AppSettings["okta:RedirectUri"],
PostLogoutRedirectUri = ConfigurationManager.AppSettings["okta:PostLogoutRedirectUri"],
GetClaimsFromUserInfoEndpoint = true,
Scope = new List<string> { "openid", "profile", "email" },
OpenIdConnectEvents = new OpenIdConnectAuthenticationNotifications
{
// add email
SecurityTokenValidated = (notification) =>
{
var claims = new List<Claim>();
var email = notification.AuthenticationTicket.Identity.Claims.FirstOrDefault(x => x.Type == "email").Value;
claims.Add(new Claim(ClaimTypes.Email, email));
notification.AuthenticationTicket.Identity.AddClaims(claims);
return Task.CompletedTask;
},
},
});
}
//----------------------------------------------------------------
// Account controller
//----------------------------------------------------------------
// POST: /Account/ExternalLogin
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult ExternalLogin(string provider, string returnUrl)
{
// Request a redirect to the external login provider
return new ChallengeResult(provider, Url.Action("ExternalLoginCallback", "Account", new { ReturnUrl = returnUrl }));
}
// GET: /Account/ExternalLoginCallback
[AllowAnonymous]
public async Task<ActionResult> ExternalLoginCallback(string returnUrl)
{
ExternalLoginInfo loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync();
if (loginInfo == null)
{
return RedirectToAction("Login");
}
// Sign in the user with this external login provider if the user already has a login
var result = await SignInManager.ExternalSignInAsync(loginInfo, isPersistent: false);
switch (result)
{
case SignInStatus.Success:
return RedirectToAction("Index", "Claims");
// code removed for simplicity
}
}
//
// POST: /Account/LogOff
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult LogOff()
{
if (HttpContext.User.Identity.IsAuthenticated)
{
AuthenticationManager.SignOut(DefaultAuthenticationTypes.ApplicationCookie,
DefaultAuthenticationTypes.ExternalCookie
/*, OktaDefaults.MvcAuthenticationType*/); // error 400 received from Okta
return RedirectToAction("Index", "Home");
}
return RedirectToAction("Index", "Home");
}