public async Task <IActionResult> ExternalLogin(string provider, string returnUrl) { returnUrl = Url.Action("ExternalLoginCallback", new { returnUrl = returnUrl }); //windows authentication is modeled as external in the asp.net core authentication manager, so we need special handling if (AccountOptions.WindowsAuthenticationSchemes.Contains(provider)) { //"but they don't support the redirect uri, so this URL is re-triggered when we call challenge if (HttpContext.User is WindowsPrincipal wp) { var props = new AuthenticationProperties(); props.Items.Add("scheme", AccountOptions.WindowsAuthenticationProviderName); var id = new ClaimsIdentity(provider); id.AddClaim(new Claim(JwtClaimTypes.Subject, HttpContext.User.Identity.Name)); id.AddClaim(new Claim(JwtClaimTypes.Name, HttpContext.User.Identity.Name)); var externalUser = await _externalIdentityProviderService.FindUserBySubjectId(HttpContext.User.Identity.Name); if (externalUser?.FirstName != null) { id.AddClaim(new Claim(JwtClaimTypes.GivenName, externalUser.FirstName)); } if (externalUser?.LastName != null) { id.AddClaim(new Claim(JwtClaimTypes.FamilyName, externalUser.LastName)); } //add the groups as claims -- be careful if the number of groups is too large if (AccountOptions.IncludeWindowsGroups) { var wi = wp.Identity as WindowsIdentity; var groups = wi.Groups.Translate(typeof(NTAccount)); var roles = groups.Select(x => new Claim(JwtClaimTypes.Role, x.Value)); id.AddClaims(_groupFilterService.FilterClaims(roles)); } await HttpContext.Authentication.SignInAsync(IdentityServerConstants.ExternalCookieAuthenticationScheme, new ClaimsPrincipal(id), props); return(Redirect(returnUrl)); } else { //this triggers all of the windows auth schemes we're supporting so the browser can use what it supports return(new ChallengeResult(AccountOptions.WindowsAuthenticationSchemes)); } } else { //start challenge and roundtrip the return URL var props = new AuthenticationProperties { RedirectUri = returnUrl, Items = { { "scheme", provider } } }; return(new ChallengeResult(provider, props)); } }
private async Task <ClaimsResult> GenerateNewClaimsResult(AuthenticateInfo info, AuthorizationRequest context) { // provider and scheme look the same, but if you see the values // FabricIdentityConstants.AuthenticationSchemes.Azure = "AzureActiveDirectory" // you will notice there are 2 different values, one for the provider and the other for the scheme var provider = info.Properties.Items["scheme"]; var schemeItem = info.Properties.Items.FirstOrDefault(i => i.Key == "scheme").Value; var claimsPrincipal = info?.Principal; if (claimsPrincipal == null) { throw new Exception("External authentication error"); } var claims = claimsPrincipal.Claims.ToList(); var userIdClaim = this.GetUserIdClaim(claims); var subjectId = AzureADSubjectId(claims); if (!string.IsNullOrEmpty(subjectId)) { var externalUser = await _externalIdentityProviderService.FindUserBySubjectId(subjectId); if (externalUser != null) { if (externalUser.FirstName != null) { claims.Add(new Claim(JwtClaimTypes.GivenName, externalUser.FirstName)); } if (externalUser.LastName != null) { claims.Add(new Claim(JwtClaimTypes.FamilyName, externalUser.LastName)); } if (externalUser.Email != null) { claims.Add(new Claim(JwtClaimTypes.Email, externalUser.Email)); } } } return(new ClaimsResult { ClientId = context?.ClientId, UserId = userIdClaim.Value, Provider = provider, SchemeItem = schemeItem, Claims = claims, UserIdClaim = userIdClaim }); }