ASP.NET Identity 2.0针对我们自己的承载服务器进行身份验证

Ste*_*tes 7 c# authentication asp.net-mvc owin asp.net-identity-2

所有,

我有一个安全服务器,其唯一目的是从单个端点提供承载令牌:http://example.com/token

示例请求:

POST http://example.com/token HTTP/1.1
User-Agent: Fiddler
Content-Type: x-www-form-urlencoded
Host: example.com
Content-Length: 73

grant_type=password&username=example@example.com&password=examplePassword
Run Code Online (Sandbox Code Playgroud)

响应示例:

HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Type: application/json;charset=UTF-8
Expires: -1
Server: Microsoft-IIS/10.0
X-Powered-By: ASP.NET
Date: Tue, 16 Aug 2016 12:04:39 GMT
{
  "access_token": "xxxx",
  "token_type": "bearer",
  "expires_in": 17999,
  "refresh_token": "xxxx",
  ".issued": "Tue, 16 Aug 2016 12:04:38 GMT",
  ".expires": "Tue, 16 Aug 2016 17:04:38 GMT"
}
Run Code Online (Sandbox Code Playgroud)

我们有一个角度应用程序,它使用此端点进行身份验证,并且这样做很好.

我们试图在没有太大成功的情况下实现的是创建一个使用相同服务器进行身份验证的MVC应用程序,我们希望代码尽可能位于Identity 2.0之上.

在我们的AccountController(示例项目)中,我们有Login(LoginModel model)处理登录的方法,看起来像这样(与示例项目模板相同):

var result = await _signInManager.PasswordSignInAsync(model.UserName, model.Password, model.RememberMe, shouldLockout: false);
Run Code Online (Sandbox Code Playgroud)

我们有自己的IUserStore,UserManager,SignInManager实现.

我考虑过压倒一切

public Task<SignInStatus> PasswordSignInAsync(string userName, string password, bool isPersistent, bool shouldLockout) on `SignInManager<,>` and make a web call across to the security server.
Run Code Online (Sandbox Code Playgroud)

默认的PasswordSignInAsync调用实现,UserManager.FindByNameAsync但这意味着我必须在我的安全服务器上公开一个查找方法,以确认存在一个真的听起来不错的用户名.

我必须遗漏一些东西而且我知道它不会那么复杂,我们的MVC应用程序需要使用cookie身份验证,但也为后续调用我们的其他资源服务器维护熊令牌.

(我很欣赏我可能会在这里混合技术,因此问题).

这也在OWIN上运行.

Kha*_* TO 2

在这种情况下,我认为您不应该在 MVC 应用程序中使用 Identity 2.0。您应该创建一个AuthenticationClient来调用您的身份验证服务器,您也可以使用此库来构建这样的客户端https://www.nuget.org/packages/Thinktecture.IdentityModel.Client/

public class AuthenticationClient {
    public ClaimsIdentity GetClaimsIdentity(string username, string password) {
         //Call your authentication server to get your token and also claims associated with your identity.
         //You can look at an example code how to do it: https://github.com/IdentityServer/IdentityServer3.Samples/blob/master/source/Clients/ConsoleResourceOwnerClient/Program.cs
         //and create a ClaimsIdentity object out of those information

         var identity = GetIdentity();

         //The key point here is to add AccessToken and RefreshToken as custom claims to your identity so you retrieve these tokens back on subsequent requests.
        identity.AddClaim(new Claim("access_token", accessToken));
        identity.AddClaim(new Claim("refresh_token", refreshToken));
    }
}
Run Code Online (Sandbox Code Playgroud)

这将满足您的要求:

使用 cookie 身份验证,但也维护 bear 令牌,以便后续调用我们的其他资源服务器。

你的Login方法AccountController应该是这样的:

public ActionResult Login(LoginModel model)
{
     var identity = authenticationClient.GetClaimsIdentity(model.UserName, model.Password);

     if (identity == null) {
         return new HttpUnauthorizedResult();
     }
     //Sign in the user
     var ctx = Request.GetOwinContext();
     var authenticationManager = ctx.Authentication;
     authenticationManager.SignIn(identity);

     return new HttpStatusCodeResult(HttpStatusCode.OK);
}
Run Code Online (Sandbox Code Playgroud)

我假设您已经注册此中间件以使用 Cookie 身份验证:

public void ConfigureAuth(IAppBuilder app)
{
   app.UseCookieAuthentication(new CookieAuthenticationOptions
   {
      AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
      LoginPath = new PathString("/Account/Login")
   });
}
Run Code Online (Sandbox Code Playgroud)

现在,对于所有后续请求,您可以检索访问令牌以从您的 ClaimsIdentity 调用您的资源服务器:

User.Identity.Claims.FirstOrDefault(x => x.Type == "access_token");
Run Code Online (Sandbox Code Playgroud)