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
相关产品推荐
相关产品推荐

