OWIN openid连接外部登录不执行指定的回调url

Posted

技术标签:

【中文标题】OWIN openid连接外部登录不执行指定的回调url【英文标题】:OWIN openid connect external login doesn't execute specified callback url 【发布时间】:2017-11-10 23:54:52 【问题描述】:

我正在使用 owin openid 连接身份验证,其中身份验证提供程序托管在单独的域上。身份验证过程运行良好。在身份服务器上成功登录后,我可以查看受限页面。

但我希望外部身份服务器返回到“帐户/SignInCallback”控制器操作,以便我可以执行与会员帐户相关的几行代码。在浏览器的网络活动中,它向我显示“帐户/SignInCallback”的“302 Found”,但它没有命中附加的断点。它直接转到请求发起 url,例如“帐户/仪表板”。

有没有一种方法可以强制系统在登录后返回到特定的 url,即使请求的 url 不同?

public class AccountController : BaseController

    public AccountController() : base()
    
    

    [Authorize]
    public ActionResult Dashboard()
    
        return View();
    

    [HttpPost]
    [AllowAnonymous]
    public ActionResult SignInCallback()
    
        if (User.Identity.IsAuthenticated)
        
            // Read claims and execute member specific codes
        
        return View();
    

    [AllowAnonymous]
    public ActionResult Unauthorized()
    
        return View();
    

启动类如下:

public sealed class Startup
   
    public void Configuration(IAppBuilder app)
    
        string ClientCallbackUri = @"https://client.local/account/SignInCallback";
        string IdServBaseUri = @"https://idm.website.com/core";
        string TokenEndpoint = @"https://idm.website.com/core/connect/token";
        string UserInfoEndpoint = @"https://idm.website.com/core/connect/userinfo";
        string ClientId = @"WebPortalDemo";
        string ClientSecret = @"aG90apW2+DbX1wVnwwLD+eu17g3vPRIg7p1OnzT14TE=";

        JwtSecurityTokenHandler.InboundClaimTypeMap = new Dictionary<string, string>();

        app.UseCookieAuthentication(new CookieAuthenticationOptions
        
            AuthenticationType = "Cookies"
        );

        app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
        
            ClientId = ClientId,
            Authority = IdServBaseUri,
            RedirectUri = ClientCallbackUri,
            PostLogoutRedirectUri = ClientUri,
            ResponseType = "code id_token token",
            Scope = "openid profile roles",
            TokenValidationParameters = new TokenValidationParameters
            
                NameClaimType = "name",
                RoleClaimType = "role"
            ,
            SignInAsAuthenticationType = "Cookies",

            Notifications = new OpenIdConnectAuthenticationNotifications
            
                AuthorizationCodeReceived = async n =>
                
                    // use the code to get the access and refresh token
                    var tokenClient = new TokenClient(
                        TokenEndpoint,
                        ClientId,
                        ClientSecret);

                    var tokenResponse = await tokenClient.RequestAuthorizationCodeAsync(n.Code, n.RedirectUri);

                    if (tokenResponse.IsError)
                    
                        throw new Exception(tokenResponse.Error);
                    

                    // use the access token to retrieve claims from userinfo
                    var userInfoClient = new UserInfoClient(UserInfoEndpoint);

                    var userInfoResponse = await userInfoClient.GetAsync(tokenResponse.AccessToken);

                    // create new identity
                    var id = new ClaimsIdentity(n.AuthenticationTicket.Identity.AuthenticationType);
                    //id.AddClaims(userInfoResponse.GetClaimsIdentity().Claims);
                    id.AddClaims(userInfoResponse.Claims);

                    id.AddClaim(new Claim("access_token", tokenResponse.AccessToken));
                    id.AddClaim(new Claim("expires_at", DateTime.Now.AddSeconds(tokenResponse.ExpiresIn).ToLocalTime().ToString()));
                    id.AddClaim(new Claim("refresh_token", tokenResponse.RefreshToken));
                    id.AddClaim(new Claim("id_token", n.ProtocolMessage.IdToken));
                    id.AddClaim(new Claim("sid", n.AuthenticationTicket.Identity.FindFirst("sid").Value));

                    n.AuthenticationTicket = new AuthenticationTicket(
                        new ClaimsIdentity(id.Claims, n.AuthenticationTicket.Identity.AuthenticationType, "name", "role"),
                        n.AuthenticationTicket.Properties);
                
            
        );
    

【问题讨论】:

【参考方案1】:

看起来你只需要设置

n.AuthenticationTicket.Properties.RedirectUri = n.RedirectUri;

在您的AuthorizationCodeReceived 代表中

【讨论】:

【参考方案2】:

各个身份验证模板通过启用 cookie 中间件而不是其他身份验证中间件(在本例中为 OIDC)上的 AutomaticChallenge 来执行此操作。 Cookie 将他们重定向到 AccountController 登录页面,然后他们选择 auth 方法,执行 auth 重定向,返回帐户控制器以执行您要添加的其他步骤,然后他们通过重定向回原始页面完成。

这是 ASP.NET Core 模板的更新版本: https://github.com/aspnet/Templates/blob/rel/1.0.5/src/Rules/StarterWeb/IndividualAuth/Controllers/AccountController.cs https://github.com/aspnet/Templates/blob/rel/1.0.5/src/Rules/StarterWeb/IndividualAuth/Startup.cs

请注意,其中大部分是由身份框架管理的,但这不是必需的。

【讨论】:

以上是关于OWIN openid连接外部登录不执行指定的回调url的主要内容,如果未能解决你的问题,请参考以下文章

openid connect owin 如何验证来自 Azure AD 的令牌?

在弹出窗口中使用 Owin 外部登录的 Asp.net 登录提供程序

Auth0 express-openid-connect 指定 IDP 与连接

使用 OWIN 身份从多个 API 客户端注册 Web API 2 外部登录

OpenID Connect 的 OWIN 中间件 - 代码流(流类型 - AuthorizationCode)文档?

我实施 OAuth/OpenId 有多差?