2015-10-28 32 views
5

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.

+0

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

+0

@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

+0

Non dimenticare di aggiungere 'options.Audience =" http: // localhost: 37734/";' alle opzioni di autenticazione del portatore JWT;) – Pinpoint

risposta

3

options.Authority corrisponde all'indirizzo dell'emittente (cioè l'indirizzo del server OIDC).

http://localhost:50000/ non sembra essere corretto in quanto si utilizza http://localhost:37734/ in seguito nella domanda. Prova a correggere l'URL e provalo di nuovo.

+0

grazie è stato! – 42vogons