private ClaimsPrincipal SignInUsingLogon(BasicSignInContext context) { var user = new StringBuilder(NativeMethods.CREDUI_MAX_USERNAME_LENGTH + 1); var domain = new StringBuilder(NativeMethods.CREDUI_MAX_PASSWORD_LENGTH + 1); if (NativeMethods.CredUIParseUserName(context.Username, user, user.Capacity, domain, domain.Capacity) != 0) { return(null); } IntPtr token; if (!NativeMethods.LogonUser(user.ToString(), domain.ToString(), context.Password, NativeMethods.LOGON32_LOGON_NETWORK, NativeMethods.LOGON32_PROVIDER_DEFAULT, out token)) { return(null); } var winIdentity = new WindowsIdentity(token); var principal = new WindowsPrincipal(winIdentity); if (principal.IsInRole(_options.AllowedGroup)) { var claims = new[] { //new Claim(ClaimTypes.Name, context.Username), new Claim(Claims.RUser, ""), // TODO: figure out how to avoid keeping raw credentials around. new Claim(Claims.Password, context.Password), }; var claimsIdentity = new ClaimsIdentity(claims, context.Options.AuthenticationScheme); principal.AddIdentities(new[] { claimsIdentity }); } return(principal); }
private ClaimsPrincipal SignInUsingLogon(BasicSignInContext context) { var user = new StringBuilder(NativeMethods.CREDUI_MAX_USERNAME_LENGTH + 1); var domain = new StringBuilder(NativeMethods.CREDUI_MAX_PASSWORD_LENGTH + 1); if (NativeMethods.CredUIParseUserName(context.Username, user, user.Capacity, domain, domain.Capacity) != 0) { return(null); } IntPtr token; WindowsIdentity winIdentity = null; if (NativeMethods.LogonUser(user.ToString(), domain.ToString(), context.Password, (int)LogonType.LOGON32_LOGON_NETWORK, (int)LogonProvider.LOGON32_PROVIDER_DEFAULT, out token)) { winIdentity = new WindowsIdentity(token); StringBuilder profileDir = new StringBuilder(NativeMethods.MAX_PATH); uint size = (uint)profileDir.Capacity; uint error = NativeMethods.CreateProfile(winIdentity.User.Value, user.ToString(), profileDir, size); // 0x800700b7 - Profile already exists. if (error != 0 && error != 0x800700b7) { return(null); } } else { return(null); } var principal = new WindowsPrincipal(winIdentity); if (principal.IsInRole(_options.AllowedGroup)) { var claims = new[] { //new Claim(ClaimTypes.Name, context.Username), new Claim(Claims.RUser, ""), // TODO: figure out how to avoid keeping raw credentials around. new Claim(Claims.Password, context.Password), }; var claimsIdentity = new ClaimsIdentity(claims, context.Options.AuthenticationScheme); principal.AddIdentities(new[] { claimsIdentity }); } return(principal); }
private async Task <ClaimsPrincipal> SignInUsingLogonAsync(BasicSignInContext context) { var user = new StringBuilder(NativeMethods.CREDUI_MAX_USERNAME_LENGTH + 1); var domain = new StringBuilder(NativeMethods.CREDUI_MAX_DOMAIN_LENGTH + 1); uint error = NativeMethods.CredUIParseUserName(context.Username, user, user.Capacity, domain, domain.Capacity); if (error != 0) { _logger.LogError(Resources.Error_UserNameParse, context.Username, error.ToString("X")); return(null); } IntPtr token; WindowsIdentity winIdentity = null; string profilePath = string.Empty; _logger.LogTrace(Resources.Trace_LogOnUserBegin, context.Username); if (NativeMethods.LogonUser(user.ToString(), domain.ToString(), context.Password, (int)LogonType.LOGON32_LOGON_NETWORK, (int)LogonProvider.LOGON32_PROVIDER_DEFAULT, out token)) { _logger.LogTrace(Resources.Trace_LogOnSuccess, context.Username); winIdentity = new WindowsIdentity(token); StringBuilder profileDir = new StringBuilder(NativeMethods.MAX_PATH * 2); uint size = (uint)profileDir.Capacity; if (NativeMethods.GetUserProfileDirectory(token, profileDir, ref size)) { profilePath = profileDir.ToString(); _logger.LogTrace(Resources.Trace_UserProfileDirectory, context.Username, profilePath); } else { #if DEBUG CancellationTokenSource cts = new CancellationTokenSource(TimeSpan.FromMinutes(10)); #else CancellationTokenSource cts = new CancellationTokenSource(TimeSpan.FromSeconds(10)); #endif _logger.LogTrace(Resources.Trace_UserProfileCreation, context.Username); var result = await _userProfileManager.CreateProfileAsync(new RUserProfileServiceRequest(user.ToString(), domain.ToString(), winIdentity.User.Value), cts.Token); if (result.IsInvalidResponse()) { _logger.LogError(Resources.Error_ProfileCreationFailedInvalidResponse, context.Username, Resources.Info_UserProfileServiceName); return(null); } error = result.Error; // 0x800700b7 - Profile already exists. if (error != 0 && error != 0x800700b7) { _logger.LogError(Resources.Error_ProfileCreationFailed, context.Username, error.ToString("X")); return(null); } else if (error == 0x800700b7 || result.ProfileExists) { _logger.LogInformation(Resources.Info_ProfileAlreadyExists, context.Username); } else { _logger.LogInformation(Resources.Info_ProfileCreated, context.Username); } if (!string.IsNullOrEmpty(result.ProfilePath)) { profilePath = result.ProfilePath; _logger.LogTrace(Resources.Trace_UserProfileDirectory, context.Username, profilePath); } else { if (NativeMethods.GetUserProfileDirectory(token, profileDir, ref size)) { profilePath = profileDir.ToString(); _logger.LogTrace(Resources.Trace_UserProfileDirectory, context.Username, profilePath); } else { _logger.LogError(Resources.Error_GetUserProfileDirectory, context.Username, Marshal.GetLastWin32Error().ToString("X")); } } } } else { _logger.LogError(Resources.Error_LogOnFailed, context.Username, Marshal.GetLastWin32Error().ToString("X")); return(null); } var principal = new WindowsPrincipal(winIdentity); if (principal.IsInRole(_options.AllowedGroup)) { var claims = new[] { //new Claim(ClaimTypes.Name, context.Username), new Claim(Claims.RUser, ""), new Claim(Claims.RUserProfileDir, profilePath) }; var claimsIdentity = new ClaimsIdentity(claims, context.Options.AuthenticationScheme); principal.AddIdentities(new[] { claimsIdentity }); } return(principal); }
public static AuthenticationBuilder AddNegotiatedToken(this AuthenticationBuilder builder, Action <NegotiatedTokenOptions> configureOptions = null) { var options = new NegotiatedTokenOptions(); configureOptions?.Invoke(options); if (options.TokenValidationParameters == null) { options.TokenValidationParameters = new NegotiatedTokenValidationParameters { IssuerSigningKey = options.IssuerSigningKey, ValidateIssuerSigningKey = options.IssuerSigningKey != null && !string.IsNullOrEmpty(options.SigningAlgorithm), ValidIssuer = options.ClaimsIssuer, ValidateIssuer = !string.IsNullOrEmpty(options.ClaimsIssuer), ValidAudience = options.Audience, ValidateAudience = !string.IsNullOrEmpty(options.Audience), AuthenticationType = options.AuthenticationType, }; } builder.AddNegotiate(options.NegotiateAuthenticationScheme, options.NegotiateDisplayName, negotiateOptions => { negotiateOptions.ClaimsIssuer = options.ClaimsIssuer; }); builder.AddJwtBearer(options.JwtBearerAuthenticationScheme, options.JwtBearerDisplayName, jwtBearerOptions => { jwtBearerOptions.TokenValidationParameters = options.TokenValidationParameters; // In case there was already a set of event handlers configured or // the handler we care about already has a handler configured we // want to preserve that and call it later, otherwise create new jwtBearerOptions.Events = options.Events ?? new JwtBearerEvents(); var originalOnTokenValidated = jwtBearerOptions.Events.OnTokenValidated; jwtBearerOptions.Events.OnTokenValidated = ctx => { // Swap out the ClaimsIdentity for a WindowsIdentity var incomingPrincipal = ctx.Principal; var incomingIdentity = incomingPrincipal.Identity; var upn = incomingIdentity.Name; var match = Regex.Match(upn, "([^\\\\]+)\\\\(.+)"); if (match.Success) { // We need to transform DOMAIN\username to username@DOMAIN // to provide a property formatted user principal name (UPN) upn = $"{match.Groups[2].Value}@{match.Groups[1].Value}"; } var authType = incomingPrincipal.Claims .FirstOrDefault(c => c.Type == AuthenticationTypeClaimType); // Based on experimentation, the AuthenticationType does not always resolve // and will throw a UnauthorizedAccessException if accessed from the created // WindowsIdentity, so here we explicitly pass it in from the previously saved var outgoingIdentity = new WindowsIdentity(upn); if (authType != null) { // TODO: this is a cheap way to get the userToken, by creating // the WinID twice but there should be a cleaner way outgoingIdentity = new WindowsIdentity(outgoingIdentity.Token, authType.Value); } var outgoingPrincipal = new WindowsPrincipal(outgoingIdentity); ctx.Principal = outgoingPrincipal; // Preserve the original ClaimsIdentities as an additional identities outgoingPrincipal.AddIdentities(incomingPrincipal.Identities); // Invoke the original handler if there was one return(originalOnTokenValidated?.Invoke(ctx) ?? Task.CompletedTask); }; }); builder.Services.AddSingleton(options); return(builder); }