Web API无法重定向到身份服务器登录页面

时间:2018-12-01 00:00:26

标签: asp.net-web-api asp.net-web-api2 identityserver4

我正在尝试使用身份服务器和Web Api实现SSO

到目前为止,我已经创建了一个身份服务器项目和一个Web Api项目,并根据我遵循的Pluralsight course对其进行了配置。自创建此课程以来,似乎已经发生了一些变化,因此我必须做的某些操作与本教程不符(这可能是造成我痛苦的原因,但我认为不是)。

我希望发生的是,我遇到了一个需要授权的控制器,并且如果需要,我将被重定向到Identity Server登录页面。目前我收到了401。我查看了implicit flow here的github示例,看来我做对了。

有人可以帮我找到我想念的东西吗?

身份服务器

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddIdentityServer()
                .AddSigningCredential(new X509Certificate2(@"cert.pfx", "password"))
                .AddInMemoryApiResources(Resources.GetApiResources())
                .AddInMemoryIdentityResources(Resources.GetIdentityResources())
                .AddInMemoryClients(Clients.Get())
                .AddTestUsers(Users.Get())
                .AddDeveloperSigningCredential();

        services.AddMvc();
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
        loggerFactory.AddConsole();

        app.UseDeveloperExceptionPage();//todo: add if debug

        app.UseIdentityServer();

        app.UseStaticFiles();

        app.UseMvcWithDefaultRoute();
    }
}

internal class Resources
{
    public static IEnumerable<IdentityResource> GetIdentityResources()
    {
        return new List<IdentityResource> {
            new IdentityResources.OpenId(),
            new IdentityResources.Profile()
        };
    }

    public static IEnumerable<ApiResource> GetApiResources()
    {
        return new List<ApiResource> {
            new ApiResource("gateway", "Gateway Service")
        };
    }
}

internal class Clients
{
    public static IEnumerable<Client> Get()
    {
        return new List<Client> {
            new Client {
                ClientId = "gatewayClient",
                ClientSecrets = new List<Secret> { new Secret("password".Sha256())},//todo:secure password
                AllowedGrantTypes = GrantTypes.ResourceOwnerPasswordAndClientCredentials,
                AllowedScopes = new List<string> { "gateway" }
            },
            new Client {
                ClientId = "gateway_implicitClient",
                ClientSecrets = new List<Secret> { new Secret("password".Sha256())},//todo:secure password
                AllowedGrantTypes = GrantTypes.Implicit,
                AllowedScopes = new List<string> {
                    IdentityServerConstants.StandardScopes.OpenId,
                    IdentityServerConstants.StandardScopes.Profile,
                    "gateway"
                },
                RedirectUris = new [] { "http://localhost:49942/signin-oidc" },
                PostLogoutRedirectUris = new [] { "http://localhost:49942/signout-callback-oidc" }
            }
        };
    }
}

internal class Users
{
    public static List<TestUser> Get()
    {
        return new List<TestUser> {
            new TestUser {
                SubjectId = "5BE86359-073C-434B-AD2D-A3932222DABE",
                Username = "scott",
                Password = "password"
            }
        };
    }
}

Web API

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

        _container = new Container();
    }

    public IConfigurationRoot Configuration { get; }
    private Container _container;

    public void ConfigureServices(IServiceCollection services)
    {
        AddAuthentication(services);
        services.AddMvc();
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env, IAntiforgery antiforgery)
    {
        app.UseAuthentication();
        app.UseMvc();
    }

    private void AddAuthentication(IServiceCollection services)
    {
        new IdentityServerConfig(services, Configuration);
    }
}

public class IdentityServerConfig
{
    public IdentityServerConfig(IServiceCollection services, IConfigurationRoot configuration)
    {
        services.AddMvcCore()
                .AddAuthorization()
                .AddJsonFormatters();

        services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
                .AddIdentityServerAuthentication(options =>
                {
                    options.RequireHttpsMetadata = false;
                    options.Authority = "http://localhost:5000";
                    options.ApiName = "gateway_implicit";
                })
                .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme)
                .AddOpenIdConnect("oidc", options =>
                {
                    options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                    options.Authority = "http://localhost:5000";
                    options.RequireHttpsMetadata = false;
                    options.ClientId = "gateway_implicitClient";
                    options.SaveTokens = true;
                });
    }
}


[Produces("application/json")]
[Route("api/properties")]
public class PropertiesController : AuthController
{
    [HttpGet]
    [Route("GetProperty/{agentId}/{propertyId}")]
    public async Task<IActionResult> GetProperty(int agentId, Guid propertyId)
    {            
        return Ok(property);
    }
}

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

namespace MyNameSpace.Controllers
{
    [Route("api/[controller]")]
    [Authorize]
    public class AuthController : ControllerBase
    {

    }
}

当我打电话给http://localhost:49942/api/properties/GetPropertySummaries/1时,我可以在VS中看到以下输出

  

Microsoft.AspNetCore.Hosting.Internal.WebHost:信息:请求启动HTTP / 1.1 GET http://localhost:49942/api/properties/GetPropertySummaries/1
  'dotnet.exe'(CoreCLR:clrhost):已加载'C:\ Users \ me.nuget \ packages \ microsoft.aspnetcore.http.extensions \ 2.1.1 \ lib \ netstandard2.0 \ Microsoft.AspNetCore.Http.Extensions。 dll”。跳过的加载符号。模块已优化,调试器选项“ Just My Code”已启用。   'dotnet.exe'(CoreCLR:clrhost):已加载'C:\ Program Files \ dotnet \ shared \ Microsoft.NETCore.App \ 2.1.6 \ System.ComponentModel.Annotations.dll'。跳过的加载符号。模块已优化,调试器选项“ Just My Code”已启用。   Microsoft.AspNetCore.Authorization.DefaultAuthorizationService:信息:授权失败。   Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:信息:过滤器“ Microsoft.AspNetCore.Mvc.Authorization.AuthorizeFilter”上的请求授权失败。   Microsoft.AspNetCore.Mvc.ChallengeResult:信息:使用身份验证方案()执行ChallengeResult。   'dotnet.exe'(CoreCLR:clrhost):已加载'C:\ Program Files \ dotnet \ sdk \ NuGetFallbackFolder \ microsoft.identitymodel.tokens \ 5.2.0 \ lib \ netstandard1.4 \ Microsoft.IdentityModel.Tokens.dll'。跳过的加载符号。模块已优化,调试器选项“ Just My Code”已启用。   'dotnet.exe'(CoreCLR:clrhost):已加载'C:\ Program Files \ dotnet \ sdk \ NuGetFallbackFolder \ system.identitymodel.tokens.jwt \ 5.2.0 \ lib \ netstandard1.4 \ System.IdentityModel.Tokens.Jwt .dll”。跳过的加载符号。模块已优化,调试器选项“ Just My Code”已启用。   'dotnet.exe'(CoreCLR:clrhost):已加载'C:\ Program Files \ dotnet \ shared \ Microsoft.NETCore.App \ 2.1.6 \ System.Xml.ReaderWriter.dll'。跳过的加载符号。模块已优化,调试器选项“ Just My Code”已启用。   'dotnet.exe'(CoreCLR:clrhost):已加载'C:\ Program Files \ dotnet \ sdk \ NuGetFallbackFolder \ microsoft.identitymodel.logging \ 5.2.0 \ lib \ netstandard1.4 \ Microsoft.IdentityModel.Logging.dll'。跳过的加载符号。模块已优化,调试器选项“ Just My Code”已启用。   'dotnet.exe'(CoreCLR:clrhost):已加载'C:\ Program Files \ dotnet \ sdk \ NuGetFallbackFolder \ microsoft.identitymodel.protocols \ 5.2.0 \ lib \ netstandard1.4 \ Microsoft.IdentityModel.Protocols.dll。跳过的加载符号。模块已优化,调试器选项“ Just My Code”已启用。   'dotnet.exe'(CoreCLR:clrhost):已加载'C:\ Program Files \ dotnet \ sdk \ NuGetFallbackFolder \ microsoft.identitymodel.protocols.openidconnect \ 5.2.0 \ lib \ netstandard1.4 \ Microsoft.IdentityModel.Protocols.OpenIdConnect .dll”。跳过的加载符号。模块已优化,调试器选项“ Just My Code”已启用。   Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler:信息:AuthenticationScheme:BearerIdentityServerAuthenticationJwt被质疑。   IdentityServer4.AccessTokenValidation.IdentityServerAuthenticationHandler:信息:AuthenticationScheme:承载被质询。   Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information:执行的动作MyNamespace.PropertiesController.GetPropertySummaries(MyService.Gateway.Service)在142.4256毫秒内   Microsoft.AspNetCore.Hosting.Internal.WebHost:信息:请求在526.0233ms中完成401

1 个答案:

答案 0 :(得分:2)

对于API(而不是服务于HTML的服务器端Web应用程序),返回401是正确的行为。这将通知客户端(例如javascript客户端应用程序)需要获取新令牌。即正是该API的客户端负责启动隐式/混合/无论何种登录流程,以获取合适的承载令牌。

如果您采用的是OpenID Connect / OAuth2处理方式,则您的API根本不会使用Cookie进行身份验证,而只会通过AddIdentityServerAuthentication()中间件使用承载令牌身份验证。