如何将WebApi ChallengeResult整合到Angular2 SPA中?

时间:2017-07-05 20:03:22

标签: c# angular asp.net-core asp.net-core-webapi

上下文

我们正在使用Asp.Net Core(Web Api)迁移Web应用程序以使用Angular2  单页应用程序(SPA)前端。该应用程序最初使用"个人用户帐户"进行。我们一直在将cshtml视图转换为Angular2组件,生成Json的控制器方法,甚至将JWT用于身份验证。

我一直在使用这个Configuring Google authentication微软文档。

问题

以下两种控制器方法说明了这个问题。 LinkLogin方法返回ChallengeResult操作。显然这不能转换为JSON。我推测此结果应该会导致浏览器重定向到外部登录提供程序,然后自动重定向到LinkLoginCallback

    [HttpPost]
    public async Task<IActionResult> LinkLogin([FromBody] string provider)
    {
        // Clear the existing external cookie to ensure a clean login process
        await HttpContext.Authentication.SignOutAsync(externalCookieScheme);

        // Request a redirect to the external login provider to link a login for the current user
        string redirectUrl = Url.Action(nameof(LinkLoginCallback), "Manage");
        var properties = signInManager.ConfigureExternalAuthenticationProperties(provider, redirectUrl, userManager.GetUserId(User));
        return Challenge(properties, provider);
    }

    [HttpPost]
    [Produces("application/json")]
    public async Task<ActionResult> LinkLoginCallback()
    {
        User user = await userManager.GetUserAsync(User);
        if (user == null)
            return Json(false);

        ExternalLoginInfo info = await signInManager.GetExternalLoginInfoAsync(await userManager.GetUserIdAsync(user));
        if (info == null)
            return Json(false);

        IdentityResult result = await userManager.AddLoginAsync(user, info);
        if (result.Succeeded)
        {
            // Clear the existing external cookie to ensure a clean login process
            await HttpContext.Authentication.SignOutAsync(externalCookieScheme);
            return Json(true);
        }

        return Json(false);
    }

如果我确实尝试从Angular拨打LinkLogin,我会收到此回复:

  

对预检请求的响应没有通过访问控制检查:否&#39;访问控制 - 允许 - 来源&#39;标头出现在请求的资源上。起源&#39; http://localhost:53462&#39;因此不允许访问。响应的HTTP状态代码为405。

1 个答案:

答案 0 :(得分:0)

所以我最终想出了一个通过修改Angular2和WebApi之间的流程来避免“ChallengeResult”的解决方案。

  1. angular2-social-login npm包添加到角度应用中(跟随所有easy instructions for setup)。
  2. 将两种控制器方法合并为一种。 ExternalLoginViewModel参数是一个带有Email,ProviderKey和LoginProvider属性的简单类(在步骤3中以Angular填充):

    [HttpPost]
    [Produces("application/json")]
    public async Task<ActionResult> LinkLogin([FromBody] ExternalLoginViewModel info)
    {
        if (ModelState.IsValid)
        {
            User user = await userManager.GetUserAsync(User);
            if (user != null)
            {
                IdentityResult result = await userManager.AddLoginAsync(user, new UserLoginInfo(info.LoginProvider, info.ProviderKey, info.LoginProvider));
                if (result.Succeeded)
                    return Json(true);
            }
        }
        return Json(false);
    }
    
  3. 更改了Angular2客户端以使用社交媒体包获取Web api所需的凭据。以下是展示连接的LinkProvider方法:( this.service.LinkLogin调用LinkLogin控制器方法)

    public async LinkProvider(providerName: string): Promise<void>
    {
        const result: any = await this.auth.login(providerName).toPromise();
        const success: boolean = await this.service.LinkLogin({
             email: result.email,
             loginProvider: result.provider,
             providerKey: result.uid
        });
    
        // Handle link response here
    }