You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

ASP.NET OpenIdConnect重定向URI格式错误问题求助(西里尔域名场景)

解决OpenIdConnectHandler处理西里尔域名Punycode重定向URI的格式问题

我之前也遇到过类似的国际化域名在OpenID Connect中触发重定向URI校验失败的问题,结合你的场景给你几个可行的解决方向:

1. 检查客户端配置的重定向URI白名单

首先要确认你的OIDC客户端(对应client_id=RosgrantService)配置里,已经把Punycode格式的完整重定向URI(也就是http://xn----7sbhbm9amwu.xn--p1ai:5002/signin-oidc)添加到允许的重定向URI列表中。很多OIDC服务端会做严格的白名单匹配,哪怕Punycode和原西里尔域名是等价的,也必须显式配置Punycode版本的URI,不能只填原文域名。

2. 手动控制域名的Punycode转换与URI编码

有时候OIDC中间件的自动编码逻辑可能对IDN(国际化域名)处理不彻底,你可以在发起授权请求前手动完成转换和编码:
比如在.NET环境下,用IdnMapping类来转Punycode:

var idnConverter = new IdnMapping();
// 将西里尔域名转成Punycode
string punycodeHost = idnConverter.GetAscii("грант-лев.рф");
// 拼接完整的重定向URI
string rawRedirectUri = $"http://{punycodeHost}:5002/signin-oidc";
// 确保URI按照application/x-www-form-urlencoded标准编码
string encodedRedirectUri = Uri.EscapeDataString(rawRedirectUri);

用这个手动编码后的URI发起授权请求,能避免中间件自动转换时的异常。

3. 自定义OpenIdConnectHandler的校验逻辑

如果上述方法都无效,可能需要重写OpenIdConnectHandler的重定向URI校验逻辑,兼容Punycode格式:

public class CustomOpenIdConnectHandler : OpenIdConnectHandler
{
    public CustomOpenIdConnectHandler(IOptionsMonitor<OpenIdConnectOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock) 
        : base(options, logger, encoder, clock)
    {
    }

    protected override async Task<AuthenticateResult> ValidateRedirectUriAsync(OpenIdConnectMessage message)
    {
        // 先执行原有校验逻辑
        var baseResult = await base.ValidateRedirectUriAsync(message);
        
        // 如果原有校验失败,且URI包含Punycode标识(xn--),则执行自定义校验
        if (baseResult.Failed && !string.IsNullOrEmpty(message.RedirectUri) && message.RedirectUri.Contains("xn--"))
        {
            try
            {
                var redirectUri = new Uri(message.RedirectUri);
                // 这里替换成你的白名单校验逻辑,比如检查Host是否在允许的Punycode列表中
                if (IsAllowedPunycodeHost(redirectUri.Host))
                {
                    return AuthenticateResult.Success();
                }
            }
            catch (UriFormatException)
            {
                // 保留原有错误逻辑
                return baseResult;
            }
        }

        return baseResult;
    }

    private bool IsAllowedPunycodeHost(string host)
    {
        // 这里添加你的允许列表判断,比如:
        return host == "xn----7sbhbm9amwu.xn--p1ai";
    }
}

然后在Startup中替换默认的Handler:

services.AddAuthentication()
    .AddOpenIdConnect(options =>
    {
        // 其他配置...
        options.ForwardDefaultSelector = context => typeof(CustomOpenIdConnectHandler).FullName;
    });

4. 确认OIDC服务端的IDN支持

最后要检查你的OIDC服务端(比如IdentityServer、Keycloak等)是否开启了IDN支持。有些服务端默认会禁用对Punycode URI的支持,需要在服务端配置中开启相关选项,比如IdentityServer中可以检查是否允许非ASCII域名的重定向URI。

额外注意事项

  • 测试时可以直接用Punycode格式的域名访问你的应用,确认应用本身能正常解析这个域名,排除DNS层面的问题;
  • 确保整个请求链路中,客户端、中间件、服务端的编码逻辑一致,避免出现URI多次编码或解码的情况。

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

火山引擎 最新活动