2016-01-24 103 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