7

我想使用 Openiddict OAuth 来保护我的 ASP.NET Core 1.0 Web 应用程序中的 api 端点。这api端点将由电话应用程序调用,用户必须使用用户名和密码登录

流程是这样的:

  • 用户可以通过 Web 应用程序注册和登录:https://www.domain.com
  • 用户安装手机应用程序,他们可以使用手机应用程序登录和注册。登录、注册和数据访问是通过api端点完成的:示例:https://www.domain.com/api/service/getsomedata

如何配置 Openiddict OAuth,以便使用 OAuth 保护 API 端点?

4

2 回答 2

5

如何配置 Openiddict OAuth,以便使用 OAuth 保护 API 端点?

您的场景听起来很适合简单的“资源所有者密码凭据”授权,这基本上是基本或表单身份验证的 OAuth2 等效项。

这是我的建议:

创建一个负责创建新帐户的新AccountController/ API 控制器:RegistrationController

由于这个阶段用户账户不存在,所以这里不能使用token认证(就像默认AccountController.Register模板在用户注册之前不能要求cookies认证一样)。

配置 OpenIddict 以启用令牌端点并允许资源所有者密码凭据授予:

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();

使用 OAuth2 验证中间件保护您的 API:

要启用令牌认证,请参考AspNet.Security.OAuth.Validation1.0.0-alpha2-final 包并在app.UseOAuthValidation()之前添加app.UseMvc(). 要强制进行身份验证,只需[Authorize]像使用 cookie 身份验证一样使用该属性。

不要犹豫,玩这个样本。它的客户端部分不使用移动应用程序,但您应该很容易理解它是如何工作的。

有关更多信息,您还可以阅读 Mike Rousos 为 Microsoft .NET Web 开发和工具博客撰写的这篇博文:ASP.NET Core 中的承载令牌身份验证

于 2016-07-19T18:03:31.907 回答
1

好的,感谢@Pinpoint 为我指明了正确的方向。

但是,这是我的 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);
    }
}

应用程序角色.cs:

public class ApplicationRole : IdentityRole
{
}

应用程序用户.cs:

  public class ApplicationUser : OpenIddictUser
{
}

服务控制器.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);
    }
}

这里的关键是 ServiceController.cs:[Authorize(ActiveAuthenticationSchemes = OAuthValidationDefaults.AuthenticationScheme)]

@Pinpoint:我没有使用 app.UseOAuthValidation() 因为它返回 302 并重定向到帐户/登录。

所以现在它是这样工作的:

  • 访问http://domain.com,用户可以注册、登录、查看数据等。
  • 用户可以下载移动应用程序、注册、登录和获取数据

在 api 端实现用户注册登录非常简单直接。

问题是使用提琴手并向http://domain.com/api/service/getdata发出 GET返回 302 并重定向到 Account/Login。如果我删除 app.UseIdentity(),那么 if 将返回 401 Unauthorized 但用户将无法再使用 UI http://domain.com登录。将此添加[Authorize(ActiveAuthenticationSchemes = OAuthValidationDefaults.AuthenticationScheme)]到我的 ServiceController 解决了这个问题。

@Pinpoint app.UseOAuthValidation() 有什么好处?

于 2016-07-19T21:12:15.843 回答