ASP.NET Identity如何获取Blazor WASM托管应用中保存的Spotify第三方访问令牌
问题核心原因
你当前的操作有4个核心错误导致无法取到令牌:
HttpContext.Items、HttpContext.Features都是单次请求生命周期有效,OnCreatingTicket执行在Spotify OAuth回调的请求中,回调完成后会触发302重定向到应用页面,新的请求里这两个存储的值会全部清空,完全没必要通过这两个位置存令牌- 你自定义存储的令牌名拼写错误:将
SpotifyAccessToken错写为SpofityAccessToken,就算存储成功也无法按正确名称读取 - 配置Spotify OAuth时没有开启
SaveTokens = true,导致你存入AuthenticationProperties的令牌不会持久化到认证Cookie中,后续请求自然无法读取 - 新增的自定义声明没有配置映射规则,会被ASP.NET Core默认的声明过滤策略丢弃,导致
User.Claims集合中找不到对应项
修复步骤
1. 修正OAuth配置
在Program.cs的Spotify认证配置中开启令牌保存,配置声明映射:
builder.Services.AddAuthentication() .AddSpotify(options => { options.ClientId = "你的Spotify ClientId"; options.ClientSecret = "你的Spotify ClientSecret"; // 核心配置:开启令牌持久化到Cookie options.SaveTokens = true; // 配置自定义声明映射,避免被过滤 options.ClaimActions.MapCustomJson("SpotifyAccessToken", json => json.GetString("access_token")); options.Events.OnCreatingTicket = ctx => { List<AuthenticationToken> tokens = ctx.Properties.GetTokens().ToList(); tokens.Add(new AuthenticationToken() { Name = "TicketCreated", Value = DateTime.UtcNow.ToString("O") }); ctx.Properties.StoreTokens(tokens); // 新增自定义声明 var spotifyAccessToken = tokens.First(x => x.Name == "access_token").Value; ctx.Identity.AddClaim(new Claim("SpotifyAccessToken", spotifyAccessToken)); return Task.CompletedTask; }; });
2. (可选)如果使用ASP.NET Core Identity,配置自定义声明工厂
如果你的项目集成了Identity,需要自定义声明工厂避免自定义声明被Identity过滤:
public class CustomClaimsPrincipalFactory : UserClaimsPrincipalFactory<IdentityUser> { public CustomClaimsPrincipalFactory(UserManager<IdentityUser> userManager, IOptions<IdentityOptions> optionsAccessor) : base(userManager, optionsAccessor) { } protected override async Task<ClaimsIdentity> GenerateClaimsAsync(IdentityUser user) { var identity = await base.GenerateClaimsAsync(user); return identity; } } // Program.cs中注册工厂 builder.Services.AddScoped<IUserClaimsPrincipalFactory<IdentityUser>, CustomClaimsPrincipalFactory>();
3. 控制器中正确读取令牌
不需要手动调用AuthenticateAsync或者SignInAsync,直接用ASP.NET Core内置的扩展方法或者取Claims即可:
[HttpGet] [Authorize] public async Task Get() { // 方法1:直接读取官方持久化的Spotify access_token,无需自定义存储 var accessToken = await HttpContext.GetTokenAsync("Spotify", "access_token"); // 方法2:读取你自定义存入的声明 var customToken = User.Claims.FirstOrDefault(c => c.Type == "SpotifyAccessToken")?.Value; var client = new SpotifyAPI.Web.SpotifyClient(accessToken); var res2 = await client.Player.GetCurrentPlayback(); }
内容的提问来源于stack exchange,提问作者DLeh
相关产品推荐
相关产品推荐

