2016-01-24 3 views
3

У меня есть приложение angularJS, которое использует asp.net vnext, который аутентифицируется с использованием JwtBearerAuthentication. Для аутентификации приложения я использую AspNet.Security.OpenIdConnect.Server. Когда я вхожу в систему, я получаю ответ json, который содержит access_token, который я могу использовать для авторизованных запросов. Я бы хотел, чтобы также получить токен обновления. Как это возможно?обновить токен с аутентификацией токена на предъявителя на 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 года), теперь вы должны спросить и предоставить offline_access возможности для получения токен обновления, as recommended by the OpenID Connect specs: https://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

Смежные вопросы