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

问题描述:

为了支持原生应用的功能,我建立了原生移动应用程序和多个Web API,Im对我的Web API的所有请求进行了验证,所以我使用IdentityServer3与ASP.Net身份通过验证外部令牌(Facebook,Twitter等)来生成基于本地用户的访问令牌

我想为我的本地应用程序(Twitter和Digits)使用社交登录提供程序,并且我希望本机应用程序负责使用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/

+0

你有什么试过的?你的代码在哪里?有一个*特定的*编程问题,我们可以帮助你? –

+0

我使用[IdentityServer3](https://github.com/identityserver/IdentityServer3.AspNetIdentity)来满足所有认证和授权需求。当我使用ResourceOwnerPasswordCredential Flow生成令牌时,我肯定会获得本地访问令牌。但我想在本地应用程序上处理外部登录(通过twitter或其他登录),没有涉及密码,并且当我从Twitter接收到外部访问令牌时,我需要能够将其发送到Identity Server 3 ,注册用户,如果尚未在系统中,并创建一个本地访问令牌,希望有助于谢谢 – user5656173

下面是一些代码,使用IdentityServer3权利要求的基础登陆(的OAuth2) 到你可以找到外部登录和OpenID登录的网站identityServer

服务器:

范围:

   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, "[email protected]"), 
       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"); 
} 

您需要使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 = "..." 
           } 
        } 
       })); 
     } 
} 

设置的提供商向signInAsType的SignInAsAuthenticationType属性是关键部分,因为这在建立PRINICIPAL的签署和身份服务器之间的联系。

还有更多关于此的信息;

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