通过验证外部令牌(Facebook,Twitter等)生成基于本地用户的访问令牌

时间:2015-12-08 20:03:34

标签: asp.net-identity twitter-oauth identityserver3 thinktecture

我正在构建本机移动应用程序和多个Web API以支持本机应用程序的功能,我对我的Web API的所有请求都进行了身份验证,因此我使用IdentityServer3和ASP.Net Identity

我想将社交登录提供程序用于我的原生应用程序(Twitter和数字),我希望本机应用程序能够使用Twitter进行身份验证,一旦通过身份验证,Twitter上的外部访问令牌就可以使用本机应用程序。现在,我想在我的Identity Server 3设置中提供端点,以支持验证外部访问令牌并根据用户生成本地访问令牌?

使用asp.net身份和身份服务器3实现这一目标的最佳方式是什么?

这篇博客文章的作者似乎正在解释我想要实现的目标,但是,他没有使用identityserver3 http://bitoftech.net/2014/08/11/asp-net-web-api-2-external-logins-social-logins-facebook-google-angularjs-app/

2 个答案:

答案 0 :(得分:0)

以下是一些使用IdentityServer3声明基本登录的代码(OAuth2) 您可以在identityServer网站上找到外部登录和openId登录

服务器:

范围:

             new Scope
             {
                 Name ="morhipo",
                  Type = ScopeType.Resource,
                  Claims = new List<ScopeClaim>
                {
                    new ScopeClaim(Constants.ClaimTypes.Name),
                    new ScopeClaim(Constants.ClaimTypes.Email),
                    new ScopeClaim(Constants.ClaimTypes.FamilyName),
                    new ScopeClaim(Constants.ClaimTypes.GivenName),
                    new ScopeClaim(Constants.ClaimTypes.Gender),
                    new ScopeClaim(Constants.ClaimTypes.Id),
                    new ScopeClaim(Constants.ClaimTypes.PhoneNumber),
                    new ScopeClaim(Constants.ClaimTypes.Subject),
                    new ScopeClaim(Constants.ClaimTypes.AccessTokenHash),
                    new ScopeClaim(Constants.ClaimTypes.Role)
                }
             }

用户:

        new InMemoryUser{ Subject = "bob", Username = "bob", Password = "bob", 
            Claims = new Claim[]
            {
                new Claim(Constants.ClaimTypes.GivenName, "Bob"),
                new Claim(Constants.ClaimTypes.Role, "Admin"),
                new Claim(Constants.ClaimTypes.Role, "User"),
                new Claim(Constants.ClaimTypes.FamilyName, "Smith"),
                new Claim(Constants.ClaimTypes.Email, "BobSmith@email.com"),
                new Claim(Constants.ClaimTypes.Name, "Bob Smith"),
            }
        },

客户端:

        new Client
        {
            ClientName = "Silicon on behalf of Carbon Client",
            ClientId = "carbon",
            Enabled = true,
            AccessTokenType = AccessTokenType.Jwt,

            Flow = Flows.ResourceOwner,

            ClientSecrets = new List<Secret>
            {
                new Secret("21B5F798-BE55-42BC-8AA8-0025B903DC3B".Sha256())
            },


             AllowedScopes = new List<string>
            {
                Constants.StandardScopes.OpenId,
                Constants.StandardScopes.Profile,
                Constants.StandardScopes.Email,
                Constants.StandardScopes.Roles,
                Constants.StandardScopes.OfflineAccess,
                "read",
                "write",
                "api1",
                "morhipo"
            },



        }

MVC客户端:

启动:

public void ConfigureAuth(IAppBuilder app)
{
    AntiForgeryConfig.UniqueClaimTypeIdentifier = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier";
    app.UseCookieAuthentication(new CookieAuthenticationOptions
    {
        LoginPath = new PathString("/account/login"),
        AuthenticationType = "Cookies"
    });
}

AccountController:

[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
{
    if (!ModelState.IsValid)
    {
        return View(model);
    }

    TokenResponse token = await GetToken(model.Email, model.Password);

    await SignInAsync(token);

    return View(model);
}

private async Task<TokenResponse> GetToken(string user, string password)
{
    var client = new TokenClient(
       "https://localhost:44333/core/connect/token",
       "carbon",
       "21B5F798-BE55-42BC-8AA8-0025B903DC3B");

    var result = await client.RequestResourceOwnerPasswordAsync(user, password, "morhipo api1 offline_access");
    return result;

}
public async Task SignInAsync(TokenResponse token)
{
    var claims = await ValidateIdentityTokenAsync(token);

    var id = new ClaimsIdentity(claims, "Cookies");
    id.AddClaim(new Claim("access_token", token.AccessToken));
    id.AddClaim(new Claim("expires_at", DateTime.Now.AddSeconds(token.ExpiresIn).ToLocalTime().ToString()));
    id.AddClaim(new Claim("refresh_token", token.RefreshToken));
    Request.GetOwinContext().Authentication.SignIn(id);
}

private async Task<IEnumerable<Claim>> ValidateIdentityTokenAsync(TokenResponse token)
{
    return await Task.Run<IEnumerable<Claim>>(() =>
    {
        JwtSecurityTokenHandler tokenHandler = new JwtSecurityTokenHandler();

        var certString = "MIIDBTCCAfGgAwIBAgIQNQb+T2ncIrNA6cKvUA1GWTAJBgUrDgMCHQUAMBIxEDAOBgNVBAMTB0RldlJvb3QwHhcNMTAwMTIwMjIwMDAwWhcNMjAwMTIwMjIwMDAwWjAVMRMwEQYDVQQDEwppZHNydjN0ZXN0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqnTksBdxOiOlsmRNd+mMS2M3o1IDpK4uAr0T4/YqO3zYHAGAWTwsq4ms+NWynqY5HaB4EThNxuq2GWC5JKpO1YirOrwS97B5x9LJyHXPsdJcSikEI9BxOkl6WLQ0UzPxHdYTLpR4/O+0ILAlXw8NU4+jB4AP8Sn9YGYJ5w0fLw5YmWioXeWvocz1wHrZdJPxS8XnqHXwMUozVzQj+x6daOv5FmrHU1r9/bbp0a1GLv4BbTtSh4kMyz1hXylho0EvPg5p9YIKStbNAW9eNWvv5R8HN7PPei21AsUqxekK0oW9jnEdHewckToX7x5zULWKwwZIksll0XnVczVgy7fCFwIDAQABo1wwWjATBgNVHSUEDDAKBggrBgEFBQcDATBDBgNVHQEEPDA6gBDSFgDaV+Q2d2191r6A38tBoRQwEjEQMA4GA1UEAxMHRGV2Um9vdIIQLFk7exPNg41NRNaeNu0I9jAJBgUrDgMCHQUAA4IBAQBUnMSZxY5xosMEW6Mz4WEAjNoNv2QvqNmk23RMZGMgr516ROeWS5D3RlTNyU8FkstNCC4maDM3E0Bi4bbzW3AwrpbluqtcyMN3Pivqdxx+zKWKiORJqqLIvN8CT1fVPxxXb/e9GOdaR8eXSmB0PgNUhM4IjgNkwBbvWC9F/lzvwjlQgciR7d4GfXPYsE1vf8tmdQaY8/PtdAkExmbrb9MihdggSoGXlELrPA91Yce+fiRcKY3rQlNWVd4DOoJ/cPXsXwry8pWjNCo5JD8Q+RQ5yZEy7YPoifwemLhTdsBz3hlZr28oCGJ3kbnpW0xGvQb3VHSTVVbeei0CfXoW6iz1";
        var cert = new X509Certificate2(Convert.FromBase64String(certString));
        TokenValidationParameters validationParameters = new TokenValidationParameters
        {
            ValidAudience = "https://localhost:44333/core/resources",
            ValidIssuer = "https://localhost:44333/core",
            NameClaimType ="name",

            IssuerSigningTokens = new X509CertificateSecurityTokenProvider(
                     "https://localhost:44333/core",
                     cert).SecurityTokens
        };

        SecurityToken t;
        ClaimsPrincipal id = tokenHandler.ValidateToken(token.AccessToken, validationParameters, out t);
        var claimList =id.Claims.ToList();
        claimList.Add(new Claim(ClaimTypes.Name, id.Identity.Name));
        return claimList.AsEnumerable();
    });

}

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult LogOff()
{
    Request
   .GetOwinContext()
   .Authentication
   .SignOut("Cookies");
    return RedirectToAction("Index", "Home");
}

答案 1 :(得分:0)

您需要让Identity Server了解社交登录提供程序。您可以通过在IdentityServerOptions的AuthenticationOptions上将它们注册为IdentityProviders来执行此操作。

例如添加Facebook身份验证;

Install-Package Microsoft.Owin.Security.Facebook -Version 2.1.0
public static void Configuration(IAppBuilder appBuilder)
{
    appBuilder.Map("/core", builder =>
        {
            builder
                .UseIdentityServer(new IdentityServerOptions
                {
                    AuthenticationOptions = new AuthenticationOptions
                    {
                        IdentityProviders = (app, signInAsType) => 
                            app.UseFaceBookAuthentication(
                                new FacebookAuthenticationOptions
                                {
                                    AuthenticationType = "Facebook",
                                    Caption = "Facebook",
                                    SignInAsAuthenticationType = signInAsType,
                                    AppId = "...",
                                    AppSecret = "..."
                                }
                    }
                }));
        }
}

将提供者上的SignInAsAuthenticationType属性设置为signInAsType是关键部分,因为这将建立已登录的prin都与身份服务器之间的链接。

此处有更多相关信息;

https://identityserver.github.io/Documentation/docsv2/configuration/identityProviders.html