使用外部身份验证提供程序从MVC5框架OAuth/OWin身份提供程序获取ExtraData

30

我正在尝试在VS 2013预览版中使用新的MVC5框架。

成员身份验证框架已经进行了全面改进,并被OWin所取代。

特别是,我打开了外部认证提供程序Google auth。

这很容易做到。

只需取消注释Startup.Auth.cs文件中App_Start目录中默认新MVC项目中的以下行:app.UseGoogleAuthentication();

因此,我想访问来自认证提供程序的“额外数据”,例如要在我的应用程序中显示用户头像的URL。

在旧OAuth实现中针对asp.net Membership提供程序,可以使用此ExtraData字典来捕获它,该字典在此处找到:ProviderDetail.ExtraData Property

我找不到关于OAuth和OWin如何协同工作以及如何访问此额外数据的文档。

有人能启发我吗?

7个回答

17

最近我也需要访问 Google 账户的个人头像,这里是我解决方法:

如果你只是在 Startup.Auth.cs 文件中启用代码app.UseGoogleAuthentication(); ,这是不够的,因为在这种情况下,Google 不会返回任何关于个人头像的信息(或者我没有找到如何获取它的方法)。

你真正需要的是使用 OAuth2 集成而不是默认启用的 Open ID。这里是我是如何做到的...

首先,你需要在 Google 端注册你的应用程序并获取“客户端 ID”和“客户端密钥”。一旦完成,你就可以继续进行(以后会用到它)。有关如何执行此操作的详细信息,请参见此处

app.UseGoogleAuthentication();替换为

    var googleOAuth2AuthenticationOptions = new GoogleOAuth2AuthenticationOptions
    {
        ClientId = "<<CLIENT ID FROM GOOGLE>>",
        ClientSecret = "<<CLIENT SECRET FROM GOOGLE>>",
        CallbackPath = new PathString("/Account/ExternalGoogleLoginCallback"),
        Provider = new GoogleOAuth2AuthenticationProvider() {
            OnAuthenticated = async context =>
            {
                context.Identity.AddClaim(new Claim("picture", context.User.GetValue("picture").ToString()));
                context.Identity.AddClaim(new Claim("profile", context.User.GetValue("profile").ToString()));
            }
        }
    };

    googleOAuth2AuthenticationOptions.Scope.Add("email");

    app.UseGoogleAuthentication(googleOAuth2AuthenticationOptions);

之后你可以使用这段代码获取个人资料图片的URL,与其他属性的方式相同

var externalIdentity = HttpContext.GetOwinContext().Authentication.GetExternalIdentityAsync(DefaultAuthenticationTypes.ExternalCookie);
var pictureClaim = externalIdentity.Result.Claims.FirstOrDefault(c => c.Type.Equals("picture"));
var pictureUrl = pictureClaim.Value;

7

使用asp.net身份验证的RTW版本后,在ExternalLoginCallback中以下代码可以为我完成此操作。(参考链接)

var externalIdentity = await HttpContext.GetOwinContext().Authentication
    .GetExternalIdentityAsync(DefaultAuthenticationTypes.ExternalCookie);
var displayName = externalIdentity.Name;
var email = externalIdentity.FindFirstValue(ClaimTypes.Email);

RTM版本中FindFirstValue扩展方法去哪了?我在VS2013调试时只看到了externalIdentity.Result.Claims! - PussInBoots

5

借鉴了Alex Wheat的答案,我想出了一种使用Google身份验证来检索Google+个人资料、性别和电子邮件的解决方案。

Startup.Auth.cs:

var googleOptions = new GoogleOAuth2AuthenticationOptions()
{
    ClientId = "<<client id - google>>",
    ClientSecret = "<<secret for your app>>",
    Provider = new GoogleOAuth2AuthenticationProvider()
    {
        OnAuthenticated = context =>
        {
            var userDetail = context.User;
            context.Identity.AddClaim(new Claim(ClaimTypes.Name,context.Identity.FindFirstValue(ClaimTypes.Name)));
            context.Identity.AddClaim(new Claim(ClaimTypes.Email,context.Identity.FindFirstValue(ClaimTypes.Email)));

            var gender = userDetail.Value<string>("gender");
            context.Identity.AddClaim(new Claim(ClaimTypes.Gender, gender));

            var picture = userDetail.Value<string>("picture");
            context.Identity.AddClaim(new Claim("picture", picture));

            return Task.FromResult(0);
        },
    },
};
googleOptions.Scope.Add("https://www.googleapis.com/auth/plus.login");
googleOptions.Scope.Add("https://www.googleapis.com/auth/userinfo.email");

app.UseGoogleAuthentication(googleOptions);

为了获取扩展资料数据,您应该在请求中添加两个范围 - plus.login和userinfo.email。如果您只添加plus.login范围,则无法查看用户的电子邮件。如果使用ASP.NET MVC5的默认模板进行身份认证,它只会显示用户的电子邮件、名字、姓氏和Google+个人资料网址。使用这里展示的方法,您还可以访问用户的图片链接。
context.User属性包含用户通过网络发送的JSON序列化数据,并具有让用户通过其键查找属性的有用方法。
要了解更多有关登录范围概念的信息,请查看: https://developers.google.com/+/api/oauth#login-scopes

4
以下是我为 Facebook 所使用的方式:
StartupAuth.cs:
var facebookAuthenticationOptions = new FacebookAuthenticationOptions()
{
    AppId = "x",
    AppSecret = "y"
};
facebookAuthenticationOptions.Scope.Add("email");
app.UseFacebookAuthentication(facebookAuthenticationOptions);

ExternalLoginCallback方法:

var externalIdentity = HttpContext.GetOwinContext().Authentication.GetExternalIdentityAsync(DefaultAuthenticationTypes.ExternalCookie);
var emailClaim = externalIdentity.Result.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Email);
var email = emailClaim.Value;

对于谷歌:

StartupAuth.cs

app.UseGoogleAuthentication();

ExternalLoginCallback方法(与Facebook相同):

var externalIdentity = HttpContext.GetOwinContext().Authentication.GetExternalIdentityAsync(DefaultAuthenticationTypes.ExternalCookie);
var emailClaim = externalIdentity.Result.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Email);
var email = emailClaim.Value;

如果我在这里设置断点:

var email = emailClaim.Value;

我在调试器中看到了Facebook和Google的电子邮件地址。
更新:请查看此帖子以获取正确和完整的解决方案:在默认的MVC5应用程序中在帐户关联步骤中从外部提供程序Google和Facebook获取电子邮件

4

1
该类GoogleAuthenticationOptions没有属性Scope。这篇文章展示了如何为FacebookAuthenticationOptions::Scope添加作用域。那么如何为Google添加作用域呢? - subsci
@subsci:原始的Google Auth是基于OpenID的,不支持作用域。它只是纯粹的身份验证,没有用户信息。Identity 2.0为Google引入了真正的OAuth,就像Facebook等一样。如果您不能或不想升级到最新的Identity,那么有一个Nuget包,https://www.nuget.org/packages/Owin.Security.GooglePlus/ - Chris Pratt

3
很遗憾,这并不是非常直接的。您可以通过挂钩GoogleProvider Authenticated事件,并向Claims Identity添加自定义声明(包括头像)来实现此操作。
public class MyGoogleProvider : GoogleAuthenticationProvider {
    public override Task Authenticated(GoogleAuthenticatedContext context) {
        context.Identity.AddClaim(new Claim("avatarClaim", "<fetch avatar url here>"));
        return base.Authenticated(context);
    }
}

app.UseGoogleAuthentication(new GoogleAuthenticationOptions() { Provider = new MyGoogleProvider() });

然后在您的AccountController中,当提取外部身份时,您可以获取此头像声明并将其存储到您的用户对象中以供以后使用。


我认为这样行不通...你必须使用GoogleOAuth2AuthenticationProvider而不是GoogleAuthenticationProvider..只有这样你才能访问到个人资料图片...我错了吗? - Mr. Pumpkin

0

这里是AndrewPolland的一个很好的答案,对我很有用。他使用了新的OAuth访问令牌,在登录后检索用户信息。从这里Deepak Goswami解释了如何使用此API调用。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接