You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

OpenIddict 4.0.0设备流中user code为JWT,能否配置为短字符串?

关于OpenIddict 4.0.0设备授权流中User Code类型配置的问题

我正在使用OpenIddict.Server.AspNetCore 4.0.0实现设备授权流,授权类型设置为urn:ietf:params:oauth:grant-type:device_code,当前收到的响应如下:

{
    "device_code": "eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkEyNTZDQ..",
    "expires_in": 599,
    "user_code": "eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkEyNTZDQk...",
    "verification_uri": "https://localhost:3000/verify",
    "verification_uri_complete": "https://localhost:3000/verify?user_code=eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkEyNTZDQk..."
}

其中user_code是JWT令牌而非短字符串,请问是否可以通过某种方式配置user_code的类型?

我的Program.cs配置如下:

if (builder.Environment.IsDevelopment())
{
    services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie();
    services.AddSingleton<IPrincipalProvider, LocalPrincipalProvider>();
}
else
{
    services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
         .AddMicrosoftIdentityWebApp(options => builder.Configuration.Bind("AzureAd", options));
    services.AddSingleton<IPrincipalProvider, AADPrincipalProvider>();
}

services.AddOpenIddict()
    .AddServer(options =>
    {
        options.SetAuthorizationEndpointUris("/authorize")
               .SetTokenEndpointUris("/token")
               .SetLogoutEndpointUris("/logout")
               .SetDeviceEndpointUris("/device")
               .SetVerificationEndpointUris("/verify");

        options.AllowDeviceCodeFlow();
    })

解答

可以通过自定义设备代码生成器修改user_code的格式,OpenIddict 4.0.0支持替换默认的代码生成逻辑,具体步骤如下:

  • 实现自定义IDeviceCodeGenerator接口
    创建类实现OpenIddict.Server.Services.IDeviceCodeGenerator接口,在GenerateAsync方法中生成短格式user_code,同时保留device_code的JWT格式(设备代码需要承载认证上下文信息)。示例代码:
public class CustomDeviceCodeGenerator : IDeviceCodeGenerator
{
    private readonly RandomNumberGenerator _rng = RandomNumberGenerator.Create();

    public async ValueTask<DeviceCodeGenerationResult> GenerateAsync(DeviceCodeGenerationContext context)
    {
        // 生成6位字母数字组合的短格式user_code
        var userCode = GenerateShortCode(6);
        
        // 调用默认生成器获取标准device_code
        var defaultGenerator = new OpenIddictServerDeviceCodeGenerator();
        var result = await defaultGenerator.GenerateAsync(context);
        
        // 替换user_code为自定义短代码
        return new DeviceCodeGenerationResult
        {
            DeviceCode = result.DeviceCode,
            UserCode = userCode,
            ExpiresIn = result.ExpiresIn
        };
    }

    private string GenerateShortCode(int length)
    {
        const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        var data = new byte[length];
        _rng.GetBytes(data);
        return new string(data.Select(b => chars[b % chars.Length]).ToArray());
    }
}
  • 注册自定义生成器到依赖注入容器
    在AddOpenIddict().AddServer()的配置中,替换默认的设备代码生成器:
services.AddOpenIddict()
    .AddServer(options =>
    {
        // 保留原有端点配置
        options.SetAuthorizationEndpointUris("/authorize")
               .SetTokenEndpointUris("/token")
               .SetLogoutEndpointUris("/logout")
               .SetDeviceEndpointUris("/device")
               .SetVerificationEndpointUris("/verify");

        options.AllowDeviceCodeFlow();
        
        // 替换为自定义设备代码生成器
        options.Services.AddSingleton<IDeviceCodeGenerator, CustomDeviceCodeGenerator>();
    });
  • 注意事项
    • user_code需保证全局唯一性,避免重复导致验证冲突;
    • 短代码建议设置6-8位,平衡用户输入便捷性和安全性;
    • 生产环境中请使用异步逻辑,避免同步调用阻塞线程。

内容的提问来源于stack exchange,提问作者JustAsking

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 16:54:56