注册外部登录Web API

Cul*_*tes 12 c# asp.net oauth-2.0 asp.net-web-api google-oauth

我不明白为什么他们不是一个明确的教程或指南,所以我希望我的问题可以在这里得到解答.

因此,尝试通过Web Api注册来自Facebook或谷歌的用户.

问题是,在这个RegisterExternal方法上,这一行:

var info = await Authentication.GetExternalLoginInfoAsync();
Run Code Online (Sandbox Code Playgroud)

它返回null,因此返回a BadRequest()

到目前为止我得到了什么:

Startup.Auth.cs我已经知道了id和秘密,请注意我也尝试过使用Microsoft.Owin.Security.Facebook

var facebookOptions = new Microsoft.Owin.Security.Facebook.FacebookAuthenticationOptions
            {
                AppId = "103596246642104",
                AppSecret = "1c9c8f696e47bbc661702821c5a8ae75",
                Provider = new FacebookAuthenticationProvider()
                {
                    OnAuthenticated = (context) =>
                    {
                        context.Identity.AddClaim(new System.Security.Claims.Claim("urn:facebook:access_token", context.AccessToken, ClaimValueTypes.String, "Facebook"));

                        return Task.FromResult(0);
                    }
                },
            };
            facebookOptions.Scope.Add("email");
            app.UseFacebookAuthentication(facebookOptions);



            app.UseGoogleAuthentication(new GoogleOAuth2AuthenticationOptions()
            {
            ClientId = "328779658984-t9d67rh2nr681bahfusan0m5vuqeck13.apps.googleusercontent.com",
            ClientSecret = "ZYcNHxBqH56Y0J2-tYowp9q0",
            CallbackPath = new PathString("/api/Account/ManageInfo")
        });
Run Code Online (Sandbox Code Playgroud)

facebookOptions来源:这篇文章

额外的facebookOptions没有解决问题.

我能够从谷歌和Facebook检索access_token.我也可以使用此access_token进行身份验证api/Account/UserInfo

GET http://localhost:4856/api/Account/UserInfo
in the header:
Authorization: Bearer R9BTVhI0...
Run Code Online (Sandbox Code Playgroud)

哪个回报: {"Email":"firstname lastname","HasRegistered":false,"LoginProvider":"Facebook"}

我注意到的一个问题是,它将我的名字作为电子邮件返回,而不是实际的电子邮件地址.

现在我想用我的数据库的新用户注册外部登录,我这样做一个POST调用:

POST http://localhost:4856/api/Account/RegisterExternal
[header]
authorization: bearer 6xcJoutY...
Content-Type: application/json
[body]
{"Email":"...@hotmail.com"}
Run Code Online (Sandbox Code Playgroud)

来源:这篇文章

现在,这将在RegisterExternal()内的代码snippit上返回BadRequest:

    public async Task<ActionResult> ExternalLoginConfirmation(ExternalLoginConfirmationViewModel model, string returnUrl)
    {
if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }
            //AuthenticationManger?
            var info = await Authentication.GetExternalLoginInfoAsync();
            if (info == null)
            {
                return InternalServerError();
            }
Run Code Online (Sandbox Code Playgroud)

在调试中,它ExternalLoginConfirmationViewModel确实包含我的电子邮件地址.

我究竟做错了什么?我需要添加一些东西Startup.cs吗?我还有什么需要做的Startup.Auth.cs吗?我错误地打电话了RegisterExternal吗?在MVC中,它是如此顺利,为什么不在Web API中呢?

麻生太郎从这个问题看了这个答案,但我不明白如何实现这个.

Cul*_*tes 5

这种方法并不实用,因为您正在开发一种最有可能用于应用程序的API,您最好的方法是通过API使用者处理Facebook的登录,并让他们向您发送facebook身份验证令牌.

基本上我试图这样做:

  1. 为facebook创建外部登录链接.
  2. 将用户发送到该链接,将他们带到Facebook登录页面.
  3. 登录后,facebook将重定向到api.
  4. 用户将被注册,但消费API的应用/网站如何知道?

你想要做的是:

  1. API使用者创建自己的方法来登录Facebook(通过SDK的应用程序)
  2. API使用者将向API发送facebook令牌以注册/登录.
  3. API将使用facebook图形端点检查令牌.
  4. 如果成功,API将返回API的承载令牌以进行进一步的身份验证请求.

因此,作为API开发人员,您可以像这样验证令牌:

var verifyTokenEndPoint = string.Format("https://graph.facebook.com/debug_token?input_token={0}&access_token={1}", accessToken, appToken);
Run Code Online (Sandbox Code Playgroud)

然后获取userId

var client = new HttpClient();
var uri = new Uri(verifyTokenEndPoint);
var response = await client.GetAsync(uri);

if (response.IsSuccessStatusCode)
{
    var content = await response.Content.ReadAsStringAsync();

    dynamic jObj = (JObject)Newtonsoft.Json.JsonConvert.DeserializeObject(content);

    string user_id = jObj["data"]["user_id"];
    string app_id = jObj["data"]["app_id"];
}
Run Code Online (Sandbox Code Playgroud)

最终你会创建或找到一个这样的用户:

IdentityUser user = await _userManager.FindAsync(new UserLoginInfo(provider, verifiedAccessToken.user_id));
Run Code Online (Sandbox Code Playgroud)

然后由您决定如何创建持票人令牌,如果您按照下面列出的教程,您可以拥有:

var tokenExpiration = TimeSpan.FromMinutes(30);

ClaimsIdentity identity = new ClaimsIdentity(OAuthDefaults.AuthenticationType);

identity.AddClaim(new Claim(ClaimTypes.Name, userName));
identity.AddClaim(new Claim("role", "user"));

var props = new AuthenticationProperties()
{
    IssuedUtc = DateTime.UtcNow,
    ExpiresUtc = DateTime.UtcNow.Add(tokenExpiration),
};

var ticket = new AuthenticationTicket(identity, props);

var accessToken = Startup.OAuthBearerOptions.AccessTokenFormat.Protect(ticket);
Run Code Online (Sandbox Code Playgroud)

来源,这里有完整的教程

我也通过SDK收到了电子邮件,并将其与POST请求一起发送,因为我管理了API和消费者.但警告:Facebook用户可能不想给你一个电子邮件地址.

AndroidIOS登录facebook后获取电子邮件