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()?
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)] –
Mi chiedo se sia possibile rendere "ActiveAuthenticationSchemes = OAuthValidationDefaults.AuthenticationScheme" come predefinito, in modo che non possa impostarlo su ogni controller. –