/
AccountController.cs
121 lines (106 loc) · 4.61 KB
/
AccountController.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
using System;
using System.Linq;
using System.Security.Claims;
using System.Security.Cryptography.X509Certificates;
using System.Threading.Tasks;
using System.Web.Mvc;
using Microsoft.AspNet.Identity;
using Microsoft.Owin.Security;
using Okta.Auth.Sdk;
using Okta.Sdk.Abstractions;
using okta_aspnet_mvc_example.Models;
namespace okta_aspnet_mvc_example.Controllers
{
public class AccountController : Controller
{
private readonly IAuthenticationManager _authenticationManager;
private readonly IAuthenticationClient _oktaAuthenticationClient;
public AccountController(IAuthenticationManager authenticationManager, IAuthenticationClient oktaAuthenticationClient)
{
_authenticationManager = authenticationManager;
_oktaAuthenticationClient = oktaAuthenticationClient;
}
// GET: Account
[AllowAnonymous]
public ActionResult Login(string returnUrl)
{
ViewBag.ReturnUrl = returnUrl;
return View();
}
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> LoginAsync(LoginViewModel model)
{
if (!ModelState.IsValid)
{
return View("Login");
}
var authnOptions = new AuthenticateOptions()
{
Username = model.UserName,
Password = model.Password,
};
try
{
var authnResponse = await _oktaAuthenticationClient.AuthenticateAsync(authnOptions).ConfigureAwait(false);
Session["rememberMe"] = model.RememberMe;
if (authnResponse.AuthenticationStatus == AuthenticationStatus.Success)
{
var identity = new ClaimsIdentity(
new[] { new Claim(ClaimTypes.Name, model.UserName) },
DefaultAuthenticationTypes.ApplicationCookie);
_authenticationManager.SignIn(new AuthenticationProperties { IsPersistent = model.RememberMe }, identity);
return RedirectToAction("Index", "Home");
}
else if (authnResponse.AuthenticationStatus == AuthenticationStatus.MfaEnroll)
{
Session["stateToken"] = authnResponse.StateToken;
var factors = authnResponse.Embedded.GetArrayProperty<Factor>("factors");
Session["factors"] = factors?.Where(x => x.Enrollment.ToUpper() == "REQUIRED").ToList();
return RedirectToAction("SelectFactor", "Manage");
}
else if (authnResponse.AuthenticationStatus == AuthenticationStatus.MfaRequired)
{
Session["stateToken"] = authnResponse.StateToken;
var allFactors = authnResponse.Embedded.GetArrayProperty<Factor>("factors");
var defaultMfaFactor = allFactors.FirstOrDefault(x => x.Type == "sms" || x.Type == "email");
if (defaultMfaFactor != null)
{
Session["isMfaRequiredFlow"] = true;
Session["factorId"] = defaultMfaFactor.Id;
return RedirectToAction("VerifyFactor", "Manage");
}
throw new NotImplementedException($"Unhandled Factor during MFA Auth");
}
else if (authnResponse.AuthenticationStatus == AuthenticationStatus.PasswordExpired)
{
Session["stateToken"] = authnResponse.StateToken;
return RedirectToAction("ChangePassword", "Manage");
}
else
{
ModelState.AddModelError(string.Empty, $"Invalid login attempt: {authnResponse.AuthenticationStatus}");
return View("Login", model);
}
}
catch (OktaApiException exception)
{
ModelState.AddModelError(string.Empty, $"Invalid login attempt: {exception.ErrorSummary}");
return View("Login", model);
}
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> LogOffAsync()
{
await _oktaAuthenticationClient.CancelTransactionStateAsync(
new TransactionStateOptions
{
StateToken = Session["stateToken"]?.ToString(),
});
_authenticationManager.SignOut();
return RedirectToAction("Login", "Account");
}
}
}