First up, I am NOT going to be maintaining roles (claims) from within Azure AD, as I have to maintain it within SQL Server. So, for Authentication, I am using Azure AD. Once authenticated, I query my claims tables (aspnetmembership) and add it to the identity.
Right now, the below code seems to be working fine. But I don't feel confident at all due to these questions I have, as I just don't know if I have coded it right.
Here's my code and here are my questions:
Like we do with Forms auth, once authenticated, am I supposed to set the Thread.Currentprincipal, as well as Context.User even with Azure AD authentication or does this line of code automatically do that for me (I sign in once azure ad authenticates fine)
HttpContext.Current.GetOwinContext().Authentication.SignIn(identity);
If yes to the above question, I am really confused as to how I must sequence the above Signin line of code with setting the Principal (as well as Context.User) with the Azure AD authenticated identity?
I never knew this but does the [Authorize] attribute in MVC 5.0 automatically do the call to check if the request is 'authenticated' as well?
How do I access the custom claims that I added in Startup, within my controllers?
Can you please explain how I need to be handling the cookies with AZure AD authentication?
Thanks in advance!
Here's my code:
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);
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
//app.UseCookieAuthentication(new CookieAuthenticationOptions
//{
// CookieDomain = "localhost",
// SlidingExpiration = true,
// ExpireTimeSpan = TimeSpan.FromHours(2)
//});
app.UseCookieAuthentication(new CookieAuthenticationOptions());
app.UseOpenIdConnectAuthentication(
new OpenIdConnectAuthenticationOptions
{
// Sets the ClientId, authority, RedirectUri as obtained from web.config
ClientId = clientId,
Authority = authority,
RedirectUri = null,
// PostLogoutRedirectUri is the page that users will be redirected to after sign-out. In this case, it is using the home page
PostLogoutRedirectUri = redirectUri,
Scope = OpenIdConnectScope.OpenIdProfile,
// ResponseType is set to request the code id_token - which contains basic information about the signed-in user
ResponseType = OpenIdConnectResponseType.CodeIdToken,
// ValidateIssuer set to false to allow personal and work accounts from any organization to sign in to your application
// To only allow users from a single organizations, set ValidateIssuer to true and 'tenant' setting in web.config to the tenant name
// To allow users from only a list of specific organizations, set ValidateIssuer to true and use ValidIssuers parameter
TokenValidationParameters = new TokenValidationParameters()
{
//NameClaimType = "preferred_username",
ValidateIssuer = false // TODO: SET THIS TO TRUE EVENTUALLY.
},
// OpenIdConnectAuthenticationNotifications configures OWIN to send notification of failed authentications to OnAuthenticationFailed method
Notifications = new OpenIdConnectAuthenticationNotifications
{
AuthenticationFailed = OnAuthenticationFailed,
SecurityTokenValidated = async (x) =>
{
var identity = x.AuthenticationTicket.Identity; //Check this.
await Task.FromResult(0);
var claims = identity.Claims;
var name = claims.First(claim => claim.Type == "name").Value;
var email = claims.First(claim => claim.Type == "preferred_username").Value;
var user = UserManager.FindByEmail(email);
var customClaims = UserManager.GetClaims(user.Id);
foreach (var claim in customClaims)
{
identity.AddClaim(new Claim(claim.Type, claim.Value));
}
HttpContext.Current.GetOwinContext().Authentication.SignIn(identity); //THis is the key here.
var principal = new ClaimsPrincipal(identity);
System.Threading.Thread.CurrentPrincipal = principal;
if (System.Web.HttpContext.Current != null)
System.Web.HttpContext.Current.User = principal;
}
}
}
);
}
And in my controller methods I am accessing my claims that I added above, using this method. Please confirm if this is correct or should I use the Thread.CurrentPrincipal somehow?
[Authorize]
public class HomeController : BaseController
{
private ApplicationUserManager _userManager;
public ActionResult Index()
{
//{
var identity = User.Identity as ClaimsIdentity;
var count = identity.Claims.Count(); //I get to see all the claims here that I set in startup
return View();
}