I am creating a blazor web app is using microsoft examples for authentication.Authentication works great, both with a username/password and with 3rd party (google) auth. I also have a maui native app that uses the web login flow (using WebAuthenticator) and I need to pass back an access token so that the maui app can use the Web API's. The login flow works successfully.
Here is the component in /account that is called after a user successfully logs in. This components responsibility is to retrieve the token and send it back to the mobile app. However .GetTokenValue("access_token") is always null, despite the user being successfully logged in.
public partial class ReturnToMobileApp : ComponentBase{ [CascadingParameter] public HttpContext? HttpContext { get; set; } protected override async Task OnInitializedAsync() { var auth = await HttpContext.AuthenticateAsync(IdentityConstants.ApplicationScheme); var claims = auth.Principal.Identities.FirstOrDefault()?.Claims; var email = string.Empty; email = claims?.FirstOrDefault(c => c.Type == System.Security.Claims.ClaimTypes.Email)?.Value; // Get parameters to send back to the callback var qs = new Dictionary<string, string> { { "access_token", auth.Properties.GetTokenValue("access_token") }, { "refresh_token", auth.Properties.GetTokenValue("refresh_token") ?? string.Empty }, { "expires_in", (auth.Properties.ExpiresUtc?.ToUnixTimeSeconds() ?? -1).ToString() }, { "email", email } }; // Build the result url var url = "myapp://#" + string.Join("&", qs.Where(kvp => !string.IsNullOrEmpty(kvp.Value) && kvp.Value != "-1") .Select(kvp => $"{WebUtility.UrlEncode(kvp.Key)}={WebUtility.UrlEncode(kvp.Value)}")); // Redirect to final url HttpContext.Response.Redirect(url); }}I have considered maybe something is wrong with my app startup configuration that's causing it not to store tokens, but any changes here have not affected the attempt to retrieve the access token from HttpContext.
services.AddAuthorizationCore();services.AddCascadingAuthenticationState();services.AddIdentity<IdentityUser, IdentityRole>(options => { options.SignIn.RequireConfirmedAccount = false; }) .AddEntityFrameworkStores<MyIdentityDbContext>() .AddSignInManager() .AddDefaultUI() .AddDefaultTokenProviders() .AddApiEndpoints();services.AddScoped<IdentityUserAccessor>();services.AddScoped<IdentityRedirectManager>();services.AddScoped<AuthenticationStateProvider, IdentityRevalidatingAuthenticationStateProvider>();services.Configure<IdentityOptions>(options =>{ // Password settings. options.Password = new PasswordOptions { RequireDigit = true, RequireLowercase = true, RequireNonAlphanumeric = true, RequireUppercase = true, RequiredLength = 8, 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;});services.ConfigureApplicationCookie(options =>{ // Cookie settings options.Cookie.Name = "MyApp.Cookie"; options.Cookie.HttpOnly = true; options.ExpireTimeSpan = TimeSpan.FromMinutes(5); options.LoginPath = "/Account/Login"; options.AccessDeniedPath = "/Account/AccessDenied"; options.SlidingExpiration = true;});Here is my login code, the user is successfully logged in and then redirected to the ReturnToMobileApp component to attempt to get the bearer token (I also tried to get the token here before the redirect, to no avail)
[Inject]public required SignInManager<IdentityUser> SignInManager { get; set; }.... var result = await SignInManager.PasswordSignInAsync(Input.Email, Input.Password, Input.RememberMe, lockoutOnFailure: false);if (result.Succeeded){ Logger.LogInformation("User logged in."); RedirectManager.RedirectTo("Account/ReturnToMobileApp");I can also use postman to access the /login identity endpoint and it succeeds with a 200 OK, but does not return an access token. Examples I've seen show this endpoint should return a token.
UPDATE: I am now able to get a token via postman. It still does not work from within the components. I believe the following lines of code allowed the bearer token to be returned via postman:
.AddBearerToken(IdentityConstants.BearerScheme, o =>{ o.BearerTokenExpiration = TimeSpan.FromMinutes(5);});



