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

ASP.NET Core 3.1下Identity Server 4集成Orcid联合登录方案咨询

在Identity Server 4(ASP.NET Core 3.1)中集成Orcid联合登录方案

核心逻辑

Identity Server 4原生支持多外部认证提供商集成,只需添加对应认证中间件、扩展登录页选项,并复用现有第三方令牌存储与客户端重定向逻辑,即可在保留原有NetForum流程的基础上新增Orcid/Google登录能力。


具体步骤

1. 安装依赖包

针对Orcid(基于OAuth2协议),安装ASP.NET Core OAuth认证中间件:

Install-Package Microsoft.AspNetCore.Authentication.OAuth

若集成Google,直接安装官方认证包:

Install-Package Microsoft.AspNetCore.Authentication.Google

2. 配置Orcid认证中间件

在Startup.cs的ConfigureServices方法中,在AddIdentityServer()之后添加Orcid认证配置:

services.AddAuthentication()
    // 保留已有的NetForum认证配置
    .AddOAuth("NetForum", options => { /* 现有配置逻辑 */ })
    // 新增Orcid认证配置
    .AddOAuth("Orcid", options =>
    {
        // 从配置文件读取Orcid开发者凭证(建议存放在appsettings.json)
        options.ClientId = Configuration["Orcid:ClientId"];
        options.ClientSecret = Configuration["Orcid:ClientSecret"];
        
        // Orcid OAuth2端点(区分沙箱/生产环境)
        options.AuthorizationEndpoint = "https://orcid.org/oauth/authorize";
        options.TokenEndpoint = "https://orcid.org/oauth/token";
        options.UserInformationEndpoint = "https://pub.orcid.org/v3.0/{orcid}";
        
        // 回调地址,需提前在Orcid开发者平台注册
        options.CallbackPath = "/signin-orcid";
        
        // 请求的权限范围,根据业务需求调整
        options.Scope.Add("/authenticate");
        options.Scope.Add("/read-limited");
        
        // 将Orcid返回的用户信息映射到Identity标准Claims
        options.ClaimActions.MapJsonKey(ClaimTypes.NameIdentifier, "orcid");
        options.ClaimActions.MapJsonKey(ClaimTypes.Name, "name");
        options.ClaimActions.MapJsonKey(ClaimTypes.Email, "email");
        
        // 自定义用户信息解析逻辑(适配Orcid特殊的返回结构)
        options.Events = new OAuthEvents
        {
            OnCreatingTicket = async context =>
            {
                // 调用Orcid用户信息接口获取完整数据
                var request = new HttpRequestMessage(
                    HttpMethod.Get, 
                    context.Options.UserInformationEndpoint.Replace("{orcid}", context.User.GetString("orcid"))
                );
                request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
                request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", context.AccessToken);
                
                var response = await context.Backchannel.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, context.HttpContext.RequestAborted);
                response.EnsureSuccessStatusCode();
                
                var user = JsonDocument.Parse(await response.Content.ReadAsStringAsync()).RootElement;
                // 补充更多业务所需Claims(如机构信息等)
                context.RunClaimActions(user);
            }
        };
    });

3. 扩展登录页,添加Orcid登录选项

在登录视图(如Login.cshtml)中,新增Orcid登录按钮,与现有NetForum按钮并列:

<div class="external-login-group">
    <a asp-action="ExternalLogin" asp-route-provider="NetForum" class="btn btn-primary">通过NetForum登录</a>
    <a asp-action="ExternalLogin" asp-route-provider="Orcid" class="btn btn-secondary">通过Orcid登录</a>
    <!-- 如需Google登录,添加对应按钮 -->
    <a asp-action="ExternalLogin" asp-route-provider="Google" class="btn btn-danger">通过Google登录</a>
</div>

4. 复用外部登录回调逻辑

在AccountController的ExternalLoginCallback方法中,统一处理所有外部提供商的回调,无需修改原有核心流程:

public async Task<IActionResult> ExternalLoginCallback(string returnUrl = null, string remoteError = null)
{
    // 处理外部登录错误
    if (remoteError != null)
    {
        ModelState.AddModelError(string.Empty, $"外部登录错误: {remoteError}");
        return View("Login");
    }
    
    // 获取外部认证结果
    var info = await _signInManager.GetExternalLoginInfoAsync();
    if (info == null)
    {
        return RedirectToAction("Login");
    }
    
    // 获取外部提供商标识与用户ID
    var provider = info.LoginProvider;
    var externalUserId = info.Principal.FindFirstValue(ClaimTypes.NameIdentifier);
    
    // 复用原有令牌存储逻辑:保存外部提供商的AccessToken(和NetForum流程一致)
    await _persistedGrantService.CreateAsync(new PersistedGrant
    {
        Key = Guid.NewGuid().ToString(),
        Type = "external_access_token",
        SubjectId = externalUserId,
        ClientId = GetClientIdFromReturnUrl(returnUrl), // 从returnUrl解析客户端ID
        CreationTime = DateTime.UtcNow,
        Expiration = DateTime.UtcNow.AddHours(1),
        Data = info.AuthenticationTokens.First(t => t.Name == "access_token").Value
    });
    
    // 构建Identity Server所需的身份凭证
    var claims = new List<Claim>
    {
        new Claim(JwtClaimTypes.Subject, externalUserId),
        new Claim(JwtClaimTypes.Name, info.Principal.FindFirstValue(ClaimTypes.Name)),
        // 根据业务需求添加更多Claims
    };
    
    var identity = new ClaimsIdentity(claims, provider);
    var principal = new ClaimsPrincipal(identity);
    
    // 完成登录,触发Identity Server的SSO流程,最终重定向到客户端回调地址
    await HttpContext.SignInAsync(IdentityServerConstants.DefaultCookieAuthenticationScheme, principal);
    
    return RedirectToAction("Redirect", "Account", new { returnUrl });
}

5. 关键注意事项

  • Orcid开发者注册:需在Orcid开发者平台创建应用,获取ClientId和ClientSecret,并配置回调地址(如https://your-sso-domain/signin-orcid)
  • 环境区分:沙箱环境的Orcid端点为https://sandbox.orcid.org/oauth/authorize和https://sandbox.orcid.org/oauth/token,生产环境使用正式端点
  • Claims映射:根据Orcid返回的用户信息结构,调整ClaimActions的映射规则,确保Identity Server能获取到必要的用户标识(如sub)
  • 令牌存储:复用原有NetForum的令牌存储机制,确保后续可获取Orcid的AccessToken用于调用Orcid API

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 21:54:53