using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Identity; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using System.Collections.Generic; using System.Linq; using System.Security.Claims; using System.Threading.Tasks; namespace zero.Identity; // TODO although the login per application works // the authentication breaks when another application signs in a user // they share one cookie on both sites/applications, maybe this is an issue public class SchemedSignInManager : SignInManager where TUser : ZeroIdentityUser { protected ZeroAuthOptions AuthOptions { get; private set; } protected IZeroContext Zero { get; private set; } public SchemedSignInManager(UserManager userManager, IHttpContextAccessor contextAccessor, IUserClaimsPrincipalFactory claimsFactory, IOptions optionsAccessor, ILogger> logger, IAuthenticationSchemeProvider schemes, IUserConfirmation confirmation, IOptions> authOptions, IZeroContext zero) : base(userManager, contextAccessor, claimsFactory, optionsAccessor, logger, schemes, confirmation) { AuthOptions = authOptions.Value; Zero = zero; } /// public override bool IsSignedIn(ClaimsPrincipal principal) { if (principal?.Identities == null) { return false; } if (!principal.Identities.Any(x => x.AuthenticationType == AuthOptions.Scheme)) { return false; } string userAppId = principal.FindFirstValue(Constants.Auth.Claims.AppId); return userAppId == null || Zero.AppId.Equals(userAppId, StringComparison.InvariantCultureIgnoreCase); } /// public override async Task RefreshSignInAsync(TUser user) { var auth = await Context.AuthenticateAsync(AuthOptions.Scheme); IList claims = Array.Empty(); var authenticationMethod = auth?.Principal?.FindFirst(ClaimTypes.AuthenticationMethod); var amr = auth?.Principal?.FindFirst("amr"); if (authenticationMethod != null || amr != null) { claims = new List(); if (authenticationMethod != null) { claims.Add(authenticationMethod); } if (amr != null) { claims.Add(amr); } } await SignInWithClaimsAsync(user, auth?.Properties, claims); } /// public override async Task SignInWithClaimsAsync(TUser user, AuthenticationProperties authenticationProperties, IEnumerable additionalClaims) { var userPrincipal = await CreateUserPrincipalAsync(user); foreach (var claim in additionalClaims) { userPrincipal.Identities.First().AddClaim(claim); } await Context.SignInAsync(AuthOptions.Scheme, userPrincipal, authenticationProperties ?? new AuthenticationProperties()); } /// public override async Task SignOutAsync() { await Context.SignOutAsync(AuthOptions.Scheme); } }