具有社交登录且没有MVC依赖关系的ASP.NET WebAPI 2.2 SPA

时间:2016-09-11 01:22:59

标签: c# asp.net .net asp.net-web-api

我一直在设计一个应用程序,它只是一个静态服务的客户端页面,旨在使用承载令牌通过支持API进行身份验证,但是最近我一直在尝试向后端添加社交登录选项但是发现它非常很难找到任何不使用MVC依赖的例子,如果可能的话我想避免使用它。

这个问题对入门很有帮助:ASP.NET Web API social authentication for Web and Mobile

然而,我一直在努力让我的项目在同一庄园中工作,基本上在我引用的问题中他已经配置了OAuthAuthorizationServerOptions.AuthorizeEndpointPath这样:

OAuthOptions = new OAuthAuthorizationServerOptions
            {
                TokenEndpointPath = new PathString("/token"),
                Provider = new ApplicationOAuthProvider(PublicClientId),
                AuthorizeEndpointPath = new PathString("/api/account/externallogin"),
                AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),
                //AllowInsecureHttp = false
            };

同样在他的支持api账户控制器中,他有以下行动:

[OverrideAuthentication]
        [HostAuthentication(DefaultAuthenticationTypes.ExternalCookie)]
        [AllowAnonymous]
        [Route("ExternalLogin", Name = "ExternalLogin")]
        public async Task<IHttpActionResult> GetExternalLogin(string provider, string error = null)

在这个例子中,我无法弄清楚RouteAttribute(模板)的第一个参数在项目中实际引用的内容,如果有的话,有人可能会解释它在这种情况下的作用吗?

现在,当运行问题中提供的示例项目时,发送GET请求到&#39; api / Account / ExternalLogin&#39;请求将在他的API帐户控制器中的操作上处理,我认为它与OverrideAuthentication有关,但我在这里得到了一点点,并努力寻找这个属性的其他用法的强有力的例子。

但是我相当确定我已经按照他描述的方式正确配置了我的WebAPI项目,但是当我向我的OAuthAuthorizationServerOptions.AuthorizeEndpointPath发送GET请求时,它不在我的API帐户控制器上处理,而是通过我的实现OAuthAuthorizationServerProvider返回&#39; invalid_request&#39;错误。

任何人都可以想到我可能忽略的一些因素导致我的API帐户控制器操作被忽略了吗?

我也阅读了这篇文章,但它似乎是用旧版本的WebAPI编写的: https://thompsonhomero.wordpress.com/2015/01/21/creating-a-clean-web-api-2-project-with-external-authentication-part-2/

感谢您的帮助, 亚历克斯。

1 个答案:

答案 0 :(得分:3)

如果没有真正看到您的GET请求,我只能假设它们不符合OAuth提供商的期望。

提供者首先验证正在进行的请求, THEN 它将控制权交给端点的控制器。您的代码很可能是正确的,只是请求格式不正确。

我创建了一个新项目,并通过向AuthorizeEndpointPath发出get请求来复制您描述的问题。不幸的是,关于为什么没有太大的意义,但是如果你反编译源代码,或者设法找到源代码,你可以看到这里发生了什么。

反编译ApplicationOAuthProvider.ValidateClientRedirectUri我的调用代码:

  await this.Options.Provider.ValidateClientRedirectUri(clientContext);
  if (!clientContext.IsValidated)
  {
    LoggerExtensions.WriteVerbose(this._logger, "Unable to validate client information");
    flag = await this.SendErrorRedirectAsync(clientContext, (BaseValidatingContext<OAuthAuthorizationServerOptions>) clientContext);
  }
  else
  {
    OAuthValidateAuthorizeRequestContext validatingContext = new OAuthValidateAuthorizeRequestContext(this.Context, this.Options, authorizeRequest, clientContext);
    if (string.IsNullOrEmpty(authorizeRequest.ResponseType))
    {
      LoggerExtensions.WriteVerbose(this._logger, "Authorize endpoint request missing required response_type parameter");
      validatingContext.SetError("invalid_request");
    }
    else if (!authorizeRequest.IsAuthorizationCodeGrantType && !authorizeRequest.IsImplicitGrantType)
    {
      LoggerExtensions.WriteVerbose(this._logger, "Authorize endpoint request contains unsupported response_type parameter");
      validatingContext.SetError("unsupported_response_type");
    }
    else
      await this.Options.Provider.ValidateAuthorizeRequest(validatingContext);
    if (!validatingContext.IsValidated)
    {
      flag = await this.SendErrorRedirectAsync(clientContext, (BaseValidatingContext<OAuthAuthorizationServerOptions>) validatingContext);
    }
    else
    {
      this._clientContext = clientContext;
      this._authorizeEndpointRequest = authorizeRequest;
      OAuthAuthorizeEndpointContext authorizeEndpointContext = new OAuthAuthorizeEndpointContext(this.Context, this.Options, authorizeRequest);
      await this.Options.Provider.AuthorizeEndpoint(authorizeEndpointContext);
      flag = authorizeEndpointContext.IsRequestCompleted;
    }
  }

在此代码中,您可以看到,如果请求已经过验证且未提供请求的指定ResponseType,则将上下文的错误设置为“invalid_request”。

我能够使用以下请求URI成功获取成功进入ExternalLogin控制器方法的请求:

http://localhost:18086/api/Account/ExternalLogin?provider=none&client_id=self&redirect_uri=http://localhost:18086/&response_type=token`

P.S。就控制器上的route属性而言,“template”字段指定将用作模板的字符串,以匹配传入的请求URI,以确定请求的路由位置。

P.P.S。可以在here

找到反编译代码段的实际源代码