Utilizzo Visual Studio 2015 Enterprise e ASP.NET vNext Beta8 per creare un endpoint che riscontri problemi e consumi token JWT. Mi sono avvicinato inizialmente generando me stesso i token, come descritto in here. Successivamente un utile article da @Pinpoint ha rivelato che AspNet.Security.OpenIdConnect.Server (a.k.a. OIDC) può essere configurato per emettere e consumare i token per me.Convalida di token emessi da AspNet.Security.OpenIdConnect.Server (ASP.NET vNext)
così ho seguito queste istruzioni, si alzò un endpoint, e presentando un posto x-www-form-urlencoded da postman ricevo indietro di un token legit:
{
"token_type": "bearer",
"access_token": "eyJ0eXAiO....",
"expires_in": "3599"
}
Questo è grande, ma anche il luogo dove ho bloccarsi. Ora, come annoto un'azione del controllore in modo che richieda questo token al portatore?
ho pensato tutto quello che avrei dovuto fare è decorare il mio metodo di controllo con il [Autorizza ("portatore")], aggiungere uno schema di autenticazione:
services.AddAuthorization
(
options =>
{
options.AddPolicy
(
JwtBearerDefaults.AuthenticationScheme,
builder =>
{
builder.
AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme).
RequireAuthenticatedUser().
Build();
}
);
}
);
e quindi chiamare la mia azione di controllo con il " Intestazione di autorizzazione eyJ0eXAiO .... "come ho fatto nel mio esempio precedente. Tristemente, tutto ciò sembra funzionare sebbene generi un'eccezione:
Si è verificata un'eccezione non gestita durante l'elaborazione della richiesta.
SocketException: Nessuna connessione potrebbe essere fatto perché la macchina di destinazione rifiutata attivamente 127.0.0.1:50000
WebException: Impossibile connettersi al server remoto
HttpRequestException: Si è verificato un errore durante l'invio della richiesta.
IOException: IDX10804: impossibile recuperare il documento da: 'http://localhost:50000/.well-known/openid-configuration'. Microsoft.IdentityModel.Logging.LogHelper.Throw (String message, Tipo ExceptionType, EventLevel logLevel, Exception innerException)
InvalidOperationException: IDX10803: Impossibile ottenere la configurazione da: 'http://localhost:50000/.well-known/openid-configuration'. Eccezione interna: 'IDX10804: impossibile recuperare il documento da:' http://localhost:50000/.well-known/openid-configuration '.'.
considerare le seguenti operazioni per riprodurre (ma per favore non considerano questa produzione Codice degno):
Applicare l'attrezzatura ASP.NET Beta8 come descritto here
Aperto Visual Studio Enterprise 2015 e creare una nuova API Web Progetto di anteprima ASP.NET 5 progetto
Cambio project.json
{
"Webroot": "wwwroot",
"versione": "1.0.0- *",
"dipendenze": {
"Microsoft.AspNet.IISPlatformHandler ":" 1.0.0-beta8 ",
" Microsoft.AspNet.Mvc ":" 6.0.0-beta8 ",
" Microsoft.AspNet.Server.Kestrel ":" 1.0.0-beta8 ",
"Microsoft.AspNet.Authentication.JwtBearer": "1.0.0-beta8",
"AspNet.Security.OpenIdConnect.Server": "1.0.0-beta3",
"Microsoft.AspNet.Authentication.OpenIdConnect" : "1.0.0-beta8",
"Microsoft.Framework.ConfigurationModel.Json": "1.0.0-beta4",
"Microsoft.AspNet.Diagnostics": "1.0.0-beta8"
},
"comandi": {
"web": "Microsoft.AspNet.Server.Kestrel"
},
"quadri": {
"dnx451": {}}
,
"escludere": [
"wwwroot",
"node_modules"
],
"publishExclude": [
".user",
" .VS PSCC"
]
}Change Startup.cs come segue (questo è per gentile concessione di @ Articolo originale di Pinpoint; Ho rimosso i commenti e ha aggiunto l'insulsa AddAuthorization):
public class Startup
{
public Startup(IHostingEnvironment env)
{
}
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthorization
(
options =>
{
options.AddPolicy
(
JwtBearerDefaults.AuthenticationScheme,
builder =>
{
builder.
AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme).
RequireAuthenticatedUser().
Build();
}
);
}
);
services.AddAuthentication();
services.AddCaching();
services.AddMvc();
services.AddOptions();
}
// Configure is called after ConfigureServices is called.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, IOptions<AppSettings> appSettings)
{
app.UseDeveloperExceptionPage();
// Add a new middleware validating access tokens issued by the OIDC server.
app.UseJwtBearerAuthentication(options => {
options.AutomaticAuthentication = true;
options.Audience = "http://localhost:50000/";
options.Authority = "http://localhost:50000/";
options.ConfigurationManager = new ConfigurationManager<OpenIdConnectConfiguration>
(
metadataAddress : options.Authority + ".well-known/openid-configuration",
configRetriever : new OpenIdConnectConfigurationRetriever(),
docRetriever : new HttpDocumentRetriever { RequireHttps = false }
);
});
// Add a new middleware issuing tokens.
app.UseOpenIdConnectServer
(
configuration =>
{
configuration.Options.TokenEndpointPath= "/authorization/v1";
configuration.Options.AllowInsecureHttp = true;
configuration.Provider = new OpenIdConnectServerProvider {
OnValidateClientAuthentication = context =>
{
context.Skipped();
return Task.FromResult<object>(null);
},
OnGrantResourceOwnerCredentials = context =>
{
var identity = new ClaimsIdentity(OpenIdConnectDefaults.AuthenticationScheme);
identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, "todo") );
identity.AddClaim(new Claim("urn:customclaim", "value", "token id_token"));
context.Validated(new ClaimsPrincipal(identity));
return Task.FromResult<object>(null);
}
};
}
);
app.UseMvc();
}
}
- Change wizarded ValuesController.cs per specificare un attributo Autorizza:
[Route("api/[controller]")]
public class ValuesController : Controller
{
// GET: api/values
[Authorize("Bearer")]
[HttpGet]
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
}
Eseguire il progetto, e acquisire un token utilizzando postman. Per acquisire un token, utilizzare POST x-www-form-urlencoded con "grant_type" di "password", "nomeutente" qualsiasi, "password" e "risorsa" l'indirizzo dell'endpoint API. Il mio particolare URL, per esempio, è http://localhost:37734/authorization/v1.
Copiare il token codificato Base64, quindi utilizzare il token per chiamare il controller dei valori guidati utilizzando postman. Per usare il token, fai un GET con le intestazioni Content-Type application/json e Authorization bearer eyJ0eXAiO .... (il tuo token). Il mio particolare URL è http://localhost:37734/api/values.
Osservare l'eccezione menzionata in precedenza.
Se il [Autorizza ("portatore")] approccio che sto cercando di cui sopra è il modo sbagliato di procedere sarei molto riconoscente se qualcuno potesse aiutarmi a capire le migliori pratiche su come ingerire la JWT Token utilizzando OIDC.
Grazie.
Nota: è consigliabile rimuovere 'options.TokenValidationParameters.ValidateAudience' e iniziare a utilizzare il parametro' resource' quando si effettua la richiesta di token, poiché potrebbe diventare obbligatorio in una versione futura. È sufficiente aggiungere '& resource = http% 3A% 2F% 2Flocalhost% 3A37734% 2F' nei dati del modulo (lato JS) e dovrebbe funzionare. Ho aggiornato il mio post originale per dirlo. – Pinpoint
@Pinpoint, ok grazie. Ho aggiunto la richiesta di risorse al momento della richiesta di token e di ricevere un token in questo modo: { "sub": "todo", "iss": "http: // localhost: 37734 /", "aud": " http: // localhost: 37734/", " exp ": 1446131180, " nbf ": 1446127580 } Ma quando commento le opzioni.TokenValidationParameters.ValidateAudience = false e tenta di utilizzare il token che ricevo" IDX10208: impossibile validate audience. validationParameters.ValidAudience è null o whitespace e validationParameters.ValidAudiences è null. " – 42vogons
Non dimenticare di aggiungere 'options.Audience =" http: // localhost: 37734/";' alle opzioni di autenticazione del portatore JWT;) – Pinpoint