7

Vorrei utilizzare Openiddict OAuth per proteggere gli endpoint delle API nella mia applicazione Web ASP.NET Core 1.0. Gli endpoint api verranno richiamati da un'app telefonica e gli utenti dovranno accedere con nome utente e password.Server OAuth di ASP.NET Core 1.0 che utilizza Openiddict

Il flusso è questa:

  • utente può registrarsi ed effettuare il login tramite l'applicazione web: installare https://www.domain.com
  • utente telefono app, e possono accedere e registrarsi utilizzando l'applicazione telefono. Login, registrazione e l'accesso ai dati avviene tramite api endpoint: Esempio: https://www.domain.com/api/service/getsomedata

Come posso configurare Openiddict OAuth quindi in grado di proteggere gli endpoint API tramite OAuth?

risposta

5

Come posso configurare Openiddict OAuth in modo da poter proteggere gli endpoint API utilizzando OAuth?

Lo scenario sembra un buon candidato per the simple "resource owner password credentials" grant, che è sostanzialmente l'equivalente OAuth2 dell'autenticazione di base o di moduli.

Ecco cosa mi consiglia:

Creare un nuovo controller AccountController/RegistrationController API responsabile della creazione di nuovi account:

Dal momento che l'account utente non esiste in questa fase, è possibile' t utilizzare l'autenticazione token qui (proprio come il modello predefinito AccountController.Register non può richiedere l'autenticazione dei cookie prima che l'utente sia registrato).

Configura OpenIddict per consentire l'endpoint token e consentire le credenziali di password del proprietario alle sovvenzioni:

services.AddOpenIddict<ApplicationDbContext>() 
    // Disable the HTTPS requirement during development. 
    .DisableHttpsRequirement() 

    // Enable the token endpoint, required to use 
    // the resource owner password credentials grant. 
    .EnableTokenEndpoint("/connect/token") 

    // Enable the password and the refresh token flows. 
    .AllowPasswordFlow() 
    .AllowRefreshTokenFlow(); 

Utilizzare la convalida middleware OAuth2 per proteggere le vostre API:

Per abilitare l'autenticazione del token, riferimento AspNet.Security.OAuth.Validation 1.0.0-alpha2-final package e aggiungere app.UseOAuthValidation() prima dello app.UseMvc(). Per rendere obbligatoria l'autenticazione, usa semplicemente l'attributo [Authorize] come faresti con l'autenticazione dei cookie.

Non esitate a giocare con this sample. Non usa un'app mobile per la parte lato client, ma dovresti capire facilmente come funziona.

Per ulteriori informazioni, si può anche leggere questo post del blog, scritto da Mike Rousos per Microsoft .NET per lo sviluppo Web e strumenti di blog: Bearer Token Authentication in ASP.NET Core

1

Ok, grazie @Pinpoint per me indicando la direzione giusta.

Tuttavia qui è la mia configurazione Startup.cs:

public class Startup 
{ 
    public Startup(IHostingEnvironment env) 
    { 
     var builder = new ConfigurationBuilder() 
      .SetBasePath(env.ContentRootPath) 
      .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) 
      .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true); 

     if (env.IsDevelopment()) 
     { 
      // For more details on using the user secret store see http://go.microsoft.com/fwlink/?LinkID=532709 
      builder.AddUserSecrets(); 
     } 

     builder.AddEnvironmentVariables(); 
     Configuration = builder.Build(); 
    } 

    public IConfigurationRoot Configuration { get; } 

    // This method gets called by the runtime. Use this method to add services to the container. 
    public void ConfigureServices(IServiceCollection services) 
    { 
     // Add framework services. 
     services.AddDbContext<ApplicationDbContext>(options => 
      options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"))); 

     services.AddIdentity<ApplicationUser, ApplicationRole>() 
      .AddEntityFrameworkStores<ApplicationDbContext>() 
      .AddDefaultTokenProviders(); 

     services.AddOpenIddict<ApplicationUser, ApplicationRole, ApplicationDbContext>() 
      .DisableHttpsRequirement() 
      .EnableTokenEndpoint("/connect/token") 
      .AllowPasswordFlow() 
      .AllowRefreshTokenFlow() 
      .UseJsonWebTokens(); 

     services.AddMvc(); 

     // Add application services. 
     services.AddTransient<IEmailSender, AuthMessageSender>(); 
     services.AddTransient<ISmsSender, AuthMessageSender>(); 
    } 

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 
    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) 
    { 


     loggerFactory.AddConsole(Configuration.GetSection("Logging")); 
     loggerFactory.AddDebug(); 

     if (env.IsDevelopment()) 
     { 
      app.UseDeveloperExceptionPage(); 
      app.UseDatabaseErrorPage(); 
      app.UseBrowserLink(); 
     } 
     else 
     { 
      app.UseExceptionHandler("/Home/Error"); 
     } 

     app.UseStaticFiles();  

     app.UseIdentity(); 

     app.UseOpenIddict(); 

     app.UseJwtBearerAuthentication(new JwtBearerOptions 
     { 
      AutomaticAuthenticate = true, 
      AutomaticChallenge = true, 
      RequireHttpsMetadata = false, 
      Audience = "http://localhost:24624/", 
      Authority = "http://localhost:24624/" 
     }); 


     // Add external authentication middleware below. To configure them please see http://go.microsoft.com/fwlink/?LinkID=532715 

     app.UseMvc(routes => 
     { 
      routes.MapRoute(
       name: "default", 
       template: "{controller=Home}/{action=Index}/{id?}"); 
     }); 
    } 
} 

ApplicationDbContext.cs:

public class ApplicationDbContext : OpenIddictDbContext<ApplicationUser, ApplicationRole> 
{ 
    public ApplicationDbContext(DbContextOptions options) 
     : base(options) 
    { 
     Database.EnsureCreated(); 
    } 

    protected override void OnModelCreating(ModelBuilder builder) 
    { 
     base.OnModelCreating(builder); 
     // Customize the ASP.NET Identity model and override the defaults if needed. 
     // For example, you can rename the ASP.NET Identity table names and more. 
     // Add your customizations after calling base.OnModelCreating(builder); 
    } 
} 

ApplicationRole.cs:

public class ApplicationRole : IdentityRole 
{ 
} 

ApplicationUser.cs:

public class ApplicationUser : OpenIddictUser 
{ 
} 

ServiceController.cs:

[Authorize(ActiveAuthenticationSchemes = OAuthValidationDefaults.AuthenticationScheme)] 
[Route("api/service")] 
public class ServiceController : Controller 
{ 
    private readonly UserManager<ApplicationUser> _userManager; 

    public ServiceController(UserManager<ApplicationUser> userManager) 
    { 
     _userManager = userManager; 
    } 

    [HttpGet] 
    [Route("getdata")] 
    public async Task<IActionResult> GetData() 
    { 
     var user = await _userManager.GetUserAsync(User); 
     if (user == null) return Ok("No user/not logged in");// if Authorize is not applied 
     return Ok(user); 
    } 
} 

La chiave qui è la ServiceController. cs: [Authorize(ActiveAuthenticationSchemes = OAuthValidationDefaults.AuthenticationScheme)]

@Pinpoint: non ho utilizzato app.UseOAuthValidation() perché restituiva 302 e reindirizza a Account/Login.

Così ora funziona in questo modo:

  • l'accesso alla http://domain.com, l'utente può registrarsi, accedere, visualizzare i dati, ecc
  • utente può scaricare app mobile, registrarsi, accedere e ottenere i dati

L'implementazione del login di registrazione utente nel lato api è facile e immediata.

Il problema era che l'utilizzo del violinista e l'emissione di un GET a http://domain.com/api/service/getdata restituivano un 302 e reindirizzano su Account/Login. Se rimuovo app.UseIdentity(), allora se restituito 401 Non autorizzato ma l'utente non sarebbe stato in grado di accedere più utilizzando l'interfaccia utente http://domain.com. L'aggiunta di questo [Authorize(ActiveAuthenticationSchemes = OAuthValidationDefaults.AuthenticationScheme)] al mio ServiceController ha risolto il problema.

@Pinpoint qual è stato il vantaggio di app.UseOAuthValidation()?

+0

Controlla questa risposta http://stackoverflow.com/questions/41551430/asp-net-core-no-redirect-on-api-auth-error/41551965#41551965, utilizzando app.MapWhen è un altro modo in modo che non devi [Autorizza (ActiveAuthenticationSchemes = OAuthValidationDefaults.AuthenticationScheme)] –

+0

Mi chiedo se sia possibile rendere "ActiveAuthenticationSchemes = OAuthValidationDefaults.AuthenticationScheme" come predefinito, in modo che non possa impostarlo su ogni controller. –