2016-01-24 105 views
3

我有一个angularJS应用程序,它使用使用JwtBearerAuthentication进行身份验证的asp.net vnext。要验证应用程序,我使用AspNet.Security.OpenIdConnect.Server。当我登录时,我收到一个包含access_token的json响应,我可以使用它来获得授权请求。我想,也收到刷新令牌。这怎么可能?在asp.net上使用不记名令牌身份验证刷新令牌vnext

Startup.cs

public void Configure(IApplicationBuilder app) { 
    app.UseJwtBearerAuthentication(options => { 
     options.AutomaticAuthenticate = true; 
     options.AutomaticChallenge = true; 
     options.TokenValidationParameters.ValidateAudience = false; 
     options.Authority = Configuration.Get<string>("OAuth:Authority"); 
     options.ConfigurationManager = new ConfigurationManager<OpenIdConnectConfiguration>(
      metadataAddress: options.Authority + ".well-known/openid-configuration", 
      configRetriever: new OpenIdConnectConfigurationRetriever(), 
      docRetriever: new HttpDocumentRetriever() { RequireHttps = false }); 
    }); 

    app.UseOpenIdConnectServer(configuration => { 
     configuration.Issuer = new Uri(Configuration.Get<string>("OpenId:Issuer")); 
     configuration.AllowInsecureHttp = true; 
     configuration.AuthorizationEndpointPath = PathString.Empty; 
     configuration.AuthenticationScheme = OpenIdConnectServerDefaults.AuthenticationScheme; 
     configuration.Provider = new AuthorizationProvider(); 
    }); 
} 

AuthorizationProvider.cs

public class AuthorizationProvider : OpenIdConnectServerProvider { 
    public override Task ValidateClientAuthentication(ValidateClientAuthenticationContext context) { 
     context.Skipped(); 

     return Task.FromResult<object>(null); 
    } 

    public override Task GrantResourceOwnerCredentials(GrantResourceOwnerCredentialsContext context) { 
     string username = context.UserName; 
     string password = context.Password; 

     UserManager<ApplicationUser> userManager = context.HttpContext.RequestServices.GetRequiredService<UserManager<ApplicationUser>>(); 
     ApplicationUser user = userManager.FindByNameAsync(username).Result; 

     if (userManager.CheckPasswordAsync(user, password).Result) { 
      ClaimsIdentity identity = new ClaimsIdentity(OpenIdConnectServerDefaults.AuthenticationScheme); 
      identity.AddClaim(ClaimTypes.Name, username, "token id_token"); 

      List<string> roles = userManager.GetRolesAsync(user).Result.ToList(); 
      foreach (string role in roles) { 
       identity.AddClaim(ClaimTypes.Role, role, "token id_token"); 
      } 

      ClaimsPrincipal principal = new ClaimsPrincipal(identity); 
      context.Validated(principal); 
     } else { 
      context.Rejected("invalid credentials"); 
     } 

     return Task.FromResult<object>(null); 
    } 
} 

AngularJS登录码

$http({ 
    method: 'POST', 
    url: 'connect/token', 
    headers: { 
     'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' 
    }, 
    data: $.param({ 
     grant_type: 'password', 
     username: email, 
     password: password 
    }) 
}).then(function (response) { 
    if (response.status == 200) { 
     var token = response.data.access_token; 
     localStorage.setItem('token', token); 
    } 
}); 
+0

在一个侧面说明,你不应该禁止观众验证('options.TokenValidationParameters.ValidateAudience = FALSE')。相反,请考虑使用'ticket.SetResources(new [] {“resource_server_1”})'在访问令牌中设置正确的受众并将其配置到您的JWT承载中间件选项中:'options.Audience =“resource_server_1”'。 – Pinpoint

+0

你让我不再问另一个问题。我会尝试。谢谢 –

回答

2

不像OAuthAuthorizationServerMiddleware,ASOS提供内置的刷新令牌支持:你不必创建你自己的令牌提供商。

注意,开始ASOS素β3(以2015年10月发布),你现在要问,并授予offline_access范围检索刷新令牌,as recommended by the OpenID Connect specshttps://github.com/aspnet-contrib/AspNet.Security.OpenIdConnect.Server/issues/128

你需要更新你的GrantResourceOwnerCredentials允许ASOS发出刷新令牌您的客户端应用程序:

public override async Task GrantResourceOwnerCredentials(GrantResourceOwnerCredentialsContext context) { 
    string username = context.UserName; 
    string password = context.Password; 

    UserManager<ApplicationUser> userManager = context.HttpContext.RequestServices.GetRequiredService<UserManager<ApplicationUser>>(); 
    ApplicationUser user = await userManager.FindByNameAsync(username); 

    if (await userManager.CheckPasswordAsync(user, password)) { 
     ClaimsIdentity identity = new ClaimsIdentity(
      context.Options.AuthenticationScheme); 

     identity.AddClaim(ClaimTypes.Name, username, 
      OpenIdConnectConstants.Destinations.AccessToken, 
      OpenIdConnectConstants.Destinations.IdentityToken); 

     foreach (string role in await userManager.GetRolesAsync(user)) { 
      identity.AddClaim(ClaimTypes.Role, role, 
       OpenIdConnectConstants.Destinations.AccessToken, 
       OpenIdConnectConstants.Destinations.IdentityToken); 
     } 

     AuthenticationTicket ticket = new AuthenticationTicket(
      new ClaimsPrincipal(identity), 
      new AuthenticationProperties(), 
      context.Options.AuthenticationScheme); 

     // Call SetResources with the list of resource servers 
     // the access token should be issued for. 
     ticket.SetResources("resource_server_1"); 

     // Only grant the "offline_access" scope 
     // if it was requested by the client application: 
     List<string> scopes = new List<string>(); 
     if (context.Request.HasScope("offline_access")) { 
      scopes.Add("offline_access"); 
     } 

     // Call SetScopes with the list of scopes you want to grant. 
     ticket.SetScopes(scopes); 

     context.Validate(ticket); 
    } else { 
     context.Reject("invalid credentials"); 
    } 

    return Task.FromResult(0); 
} 

...和你的角码指定scope参数:

$http({ 
    method: 'POST', 
    url: 'connect/token', 
    headers: { 
     'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' 
    }, 
    data: $.param({ 
     grant_type: 'password', 
     username: email, 
     password: password, 
     scope: 'offline_access' 
    }) 
}).then(function (response) { 
    if (response.status == 200) { 
     var token = response.data.access_token; 
     var refreshToken = response.data.refresh_token; 
     localStorage.setItem('token', token); 
     localStorage.setItem('refresh_token', refreshToken); 
    } 
}); 

要获取新的访问令牌,使用refresh_token批:

$http({ 
    method: 'POST', 
    url: 'connect/token', 
    headers: { 
     'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' 
    }, 
    data: $.param({ 
     grant_type: 'refresh_token', 
     refresh_token: refreshToken 
    }) 
}).then(function (response) { 
    if (response.status == 200) { 
     var token = response.data.access_token; 
     localStorage.setItem('token', token); 
    } 
}); 
+0

是否有任何示例在EF上持续刷新令牌? – MRainzo

+0

经过更新以匹配ASOS beta5(用于ASP.NET Core RC2)中使用的新名称。 – Pinpoint