I try to login User from Microsoft account into my app.
First : I'm following this info, and that'a working well. https://learn.microsoft.com/fr-fr/azure/active-directory/develop/web-app-quickstart?pivots=devlang-aspnet-core
But, when I try merge it with the classic Identity Login, on the external Login, this function return null all the time. And the login info on the starup is correct. I think it was a schema problem but I try to change it and it was not.
var info = await _signInManager.GetExternalLoginInfoAsync();
public async Task<IActionResult> OnGetCallbackAsync(string returnUrl = null, string remoteError = null)
{
returnUrl = returnUrl ?? Url.Content("~/");
if (remoteError != null)
{
ErrorMessage = $"Error from external provider: {remoteError}";
return RedirectToPage("./Login", new { ReturnUrl = returnUrl });
}
var userl = _signInManager.IsSignedIn(User);
//ExternalLoginInfo info = new ExternalLoginInfo(User, "Microsoft", User.Claims.Where(x => x.Type == "http://schemas.microsoft.com/identity/claims/objectidentifier").FirstOrDefault().Value.ToString(), "Microsoft");
var info = await _signInManager.GetExternalLoginInfoAsync();
if (info == null)
{
ErrorMessage = "Error loading external login information.";
return RedirectToPage("./Login", new { ReturnUrl = returnUrl });
}
// Sign in the user with this external login provider if the user already has a login.
var result = await _signInManager.ExternalLoginSignInAsync(info.LoginProvider, info.ProviderKey, isPersistent: false, bypassTwoFactor: true);
if (result.Succeeded)
{
_logger.LogInformation("{Name} logged in with {LoginProvider} provider.", info.Principal.Identity.Name, info.LoginProvider);
return LocalRedirect(returnUrl);
}
if (result.IsLockedOut)
{
return RedirectToPage("./Lockout");
}
else
{
// If the user does not have an account, then ask the user to create an account.
ReturnUrl = returnUrl;
ProviderDisplayName = info.ProviderDisplayName;
if (info.Principal.HasClaim(c => c.Type == ClaimTypes.Email))
{
Input = new InputModel
{
Email = info.Principal.FindFirstValue(ClaimTypes.Email)
};
}
return Page();
}
}
Startup.cs
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(connectionString));
builder.Services.AddDbContext<DatabaseContext>(options => options.UseSqlServer(connectionString));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services.AddDefaultIdentity<ApplicationUser>(options => options.SignIn.RequireConfirmedAccount = false)
.AddRoles<IdentityRole>()
.AddErrorDescriber<FrenchIdentityErrorDescriber>()
.AddEntityFrameworkStores<ApplicationDbContext>();
builder.Services.AddRazorPages();
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services
.AddControllersWithViews()
.AddRazorRuntimeCompilation()
.AddJsonOptions(options =>
{
options.JsonSerializerOptions.PropertyNameCaseInsensitive = true;
options.JsonSerializerOptions.PropertyNamingPolicy = null;
});
builder.Services.AddMvc();
builder.Services.AddDistributedMemoryCache();
builder.Services.AddSession(options =>
{
options.IdleTimeout = TimeSpan.FromHours(8);
options.Cookie.HttpOnly = true;
options.Cookie.IsEssential = true;
//options.Cookie.Name = "WebSignature.Session";
});
builder.Services.Configure<IdentityOptions>(options =>
{
// Password settings.
options.Password.RequireDigit = true;
options.Password.RequireLowercase = true;
options.Password.RequireNonAlphanumeric = true;
options.Password.RequireUppercase = true;
options.Password.RequiredLength = 6;
options.Password.RequiredUniqueChars = 1;
// Lockout settings.
options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(5);
options.Lockout.MaxFailedAccessAttempts = 5;
options.Lockout.AllowedForNewUsers = true;
// User settings.
options.User.AllowedUserNameCharacters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@ ";
options.User.RequireUniqueEmail = false;
});
builder.Services.ConfigureApplicationCookie(options =>
{
// Cookie settings
options.Cookie.HttpOnly = true;
options.ExpireTimeSpan = TimeSpan.FromHours(12);
options.LoginPath = ApplicationRedirection.PageConnexion;
options.LogoutPath = "/Identity/Account/Logout";
options.AccessDeniedPath = "/Erreurs/403";
options.SlidingExpiration = true;
});
builder.Services
.AddAuthentication()
.AddJwtBearer(options =>
{
var SecretKey = builder.Configuration.GetSection("JwtToken").GetValue<string>("SecretKey") ?? string.Empty;
var Audience = builder.Configuration.GetSection("JwtToken").GetValue<string>("Audience") ?? string.Empty;
var Issuer = builder.Configuration.GetSection("JwtToken").GetValue<string>("Issuer") ?? string.Empty;
options.RequireHttpsMetadata = false;
options.SaveToken = true;
options.TokenValidationParameters = new TokenValidationParameters
{
ClockSkew = TimeSpan.Zero,
ValidateAudience = true,
ValidAudience = Audience,
ValidateIssuer = true,
ValidIssuer = Issuer,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(SecretKey))
};
});
builder.Services.AddAuthentication()
.AddMicrosoftIdentityWebApp(options =>
{
var config = builder.Configuration.GetSection("AzureAd");
options.Instance = config["Instance"];
options.Domain = config["Domain"];
options.ClientId = config["ClientId"];
options.TenantId = config["TenantId"];
options.ClientSecret = config["ClientSecret"];
options.CallbackPath = config["CallbackPath"];
options.RequireHttpsMetadata = true;
options.GetClaimsFromUserInfoEndpoint = true;
options.SaveTokens = true;
options.UsePkce = true;
options.ResponseType = OpenIdConnectResponseType.Code;
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true
};
})
.EnableTokenAcquisitionToCallDownstreamApi(builder.Configuration.GetValue<string>("DownstreamApi:Scopes")?.Split(' '))
.AddMicrosoftGraph(builder.Configuration.GetSection("DownstreamApi"))
.AddInMemoryTokenCaches();
builder.Services.AddControllersWithViews(options =>
{
var policy = new AuthorizationPolicyBuilder().RequireAuthenticatedUser().Build();
options.Filters.Add(new AuthorizeFilter(policy));
});
builder.Services.AddAuthorization(options =>
{
options.AddPolicy(PolicyApplication.Administrateur, policy => policy.RequireAuthenticatedUser().RequireRole(RoleUtilisateur.Administrateur)/*.AddAuthenticationSchemes(IdentityConstants.ApplicationScheme)*/);
options.AddPolicy(PolicyApplication.Utilisateur, policy => policy.RequireAuthenticatedUser().RequireRole(RoleUtilisateur.Utilisateur)/*.AddAuthenticationSchemes(IdentityConstants.ApplicationScheme)*/);
/// Récupère tous les roles de la class
var AllRole = typeof(RoleUtilisateur).GetFields().Select(x => x.GetValue(x.Name)?.ToString() ?? "").ToArray();
options.AddPolicy(PolicyApplication.All, policy => policy.RequireAuthenticatedUser().RequireRole(AllRole)/*.AddAuthenticationSchemes(IdentityConstants.ApplicationScheme)*/);
/// Pour l'API
options.AddPolicy(PolicyApplication.API, policy => policy.RequireAuthenticatedUser().AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme));
});
builder.Services.Configure<GzipCompressionProviderOptions>(o => o.Level = CompressionLevel.Optimal);
builder.Services.AddKendo();
builder.Services.AddAntiforgery(o => o.HeaderName = "XSRF-TOKEN");
builder.Services.AddRazorPages()
.AddMicrosoftIdentityUI();
var app = builder.Build();
var supportedCultures = new[] { new CultureInfo("fr-FR") };
app.UseRequestLocalization(new RequestLocalizationOptions()
{
DefaultRequestCulture = new RequestCulture(new CultureInfo("fr-FR")),
SupportedCultures = supportedCultures,
SupportedUICultures = supportedCultures
});
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseMigrationsEndPoint();
}
else
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseSwagger();
app.UseSwaggerUI();
app.UseStatusCodePages(context =>
{
...
return Task.CompletedTask;
});
app.UseSession();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
endpoints.MapRazorPages();
});
app.Run();
I the problem is due to the claims who was empty. But i don't know why. enter image description here
So what is wrong, any ideas ?
CodePudding user response:
Finally I found.
Simply use that
builder.Services.AddAuthentication()
.AddMicrosoftAccount(options =>
{
var config = builder.Configuration.GetSection("AzureAd");
options.ClientId = config["ClientId"] ?? string.Empty;
options.ClientSecret = config["ClientSecret"] ?? string.Empty;
options.CallbackPath = config["CallbackPath"] ?? string.Empty;
});
than
builder.Services.AddAuthentication()
.AddMicrosoftIdentityWebApp(options =>
{
var config = builder.Configuration.GetSection("AzureAd");
options.Instance = config["Instance"];
options.Domain = config["Domain"];
options.ClientId = config["ClientId"];
options.TenantId = config["TenantId"];
options.ClientSecret = config["ClientSecret"];
options.CallbackPath = config["CallbackPath"];
options.RequireHttpsMetadata = true;
options.GetClaimsFromUserInfoEndpoint = true;
options.SaveTokens = true;
options.UsePkce = true;
options.ResponseType = OpenIdConnectResponseType.Code;
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true
};
})
.EnableTokenAcquisitionToCallDownstreamApi(builder.Configuration.GetValue<string>("DownstreamApi:Scopes")?.Split(' '))
.AddMicrosoftGraph(builder.Configuration.GetSection("DownstreamApi"))
.AddInMemoryTokenCaches();