.net 4.6 web api2 401 未经身份服务器 4 授权
.net 4.6 web api2 401 Unauthorized with identity server 4
我已经在 .net 核心应用程序中有一个可用的身份服务器 4。
namespace IdentityServer
{
public class Config
{
public static IEnumerable<ApiResource> GetApiResources()
{
return new List<ApiResource>
{
new ApiResource("myresourceapi", "My Resource API")
{
Scopes = {new Scope("apiscope")}
}
};
}
public static IEnumerable<Client> GetClients()
{
return new[]
{
// for public api
new Client
{
ClientId = "secret_client_id",
AllowedGrantTypes = GrantTypes.ClientCredentials,
ClientSecrets =
{
new Secret("secret".Sha256())
},
AllowedScopes = { "apiscope" }
}
};
}
}
}
namespace IdentityServer
{
public class Startup
{
// This method gets called by the runtime. Use this method to add services to the container.
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
public void ConfigureServices(IServiceCollection services)
{
services.AddIdentityServer()
.AddDeveloperSigningCredential()
.AddOperationalStore(options =>
{
options.EnableTokenCleanup = true;
options.TokenCleanupInterval = 30; // interval in seconds
})
.AddInMemoryApiResources(Config.GetApiResources())
.AddInMemoryClients(Config.GetClients());
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseIdentityServer();
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapGet("/", async context =>
{
await context.Response.WriteAsync("Hello World!");
});
});
}
}
}
问题是现在我需要向 .net 4.6 web api2(非核心)发出经过身份验证的请求。 IdentityServer4.AccessTokenValidation 包对此不起作用。
根据这个问题 ( 3 (IdentityServer3.AccessTokenValidation) 的相同包。
这是我在 webapi 2
中实现的代码
using IdentityServer3.AccessTokenValidation;
using Microsoft.Owin;
using Owin;
using Microsoft.Owin.Host.SystemWeb;
using IdentityModel.Extensions;
using System.Web.Http;
[assembly: OwinStartup(typeof(WebApplication10.Startup))]
namespace WebApplication10
{
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
app.UseIdentityServerBearerTokenAuthentication(new IdentityServerBearerTokenAuthenticationOptions
{
Authority = "https://localhost:44357",
// For access to the introspection endpoint
ClientId = "secret_client_id",
ClientSecret = "secret".ToSha256(),
RequiredScopes = new[] { "apiscope" }
});
}
}
}
namespace WebApplication10.Controllers
{
public class ValuesController : ApiController
{
[Authorize]
// GET api/values
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
}
}
我一直得到的状态是401未经授权。
难道我做错了什么?
有什么帮助吗?
谢谢
没有日志无法确定你的情况是什么问题,但我做了几个修复来让它工作:
- 关于
Statup.cs
class 的 IdentityServer 项目
- 将
AccessTokenJwtType
更改为 JWT
,IdentityServer4 上的默认值是 at+jwt
但 .Net Framework Api (OWIN/Katana) 需要 JWT
.
- 通过将
EmitLegacyResourceAudienceClaim
设置为 true 添加 /resources
音频,这已在 IdentityServer4 上删除。
您可以通过检查 "typ"
和 "aud"
来验证 https://jwt.ms/ 上的 access_token。
var builder = services.AddIdentityServer(
options =>
{
options.AccessTokenJwtType = "JWT";
options.EmitLegacyResourceAudienceClaim = true;
});
- 在 .Net Framework Api 项目的
Statup.cs
class 上,将 ValidationMode
设置为 ValidationMode.Local
,此方法使用的自定义访问令牌验证端点是在 IdentityServer4 上删除。
app.UseIdentityServerBearerTokenAuthentication(new IdentityServerBearerTokenAuthenticationOptions
{
Authority = "https://localhost:44357",
// For access to the introspection endpoint
ClientId = "secret_client_id",
ClientSecret = "secret".ToSha256(),
RequiredScopes = new[] { "apiscope" },
ValidationMode = ValidationMode.Local,
});
我有示例工作实施 here
我强烈建议您在 API 上收集日志,这有助于找到您案例中的实际问题并找到修复方法。 here 是在 Api 上打开 OWIN 登录的示例。
您可以按照 CrossVersionIntegrationTests 中的示例进行操作。
身份服务器 4 没有 connect/accesstokenvalidation
端点。所以在 identity server4 app 中,您可以修改 ApiResource
以添加 ApiSecret
:
new ApiResource("api1", "My API"){ ApiSecrets = new List<Secret> {new Secret("scopeSecret".Sha256())}}
在您的网站 api 中,将 IdentityServerBearerTokenAuthenticationOptions
配置为:
app.UseIdentityServerBearerTokenAuthentication(new IdentityServerBearerTokenAuthenticationOptions
{
Authority = "http://localhost:5000",
ValidationMode = ValidationMode.ValidationEndpoint,
ClientId = "api1",
ClientSecret = "scopeSecret",
RequiredScopes = new[] { "api1" }
});
ClientId
& ClientSecret
都来自您的 ApiResource 。
我已经在 .net 核心应用程序中有一个可用的身份服务器 4。
namespace IdentityServer
{
public class Config
{
public static IEnumerable<ApiResource> GetApiResources()
{
return new List<ApiResource>
{
new ApiResource("myresourceapi", "My Resource API")
{
Scopes = {new Scope("apiscope")}
}
};
}
public static IEnumerable<Client> GetClients()
{
return new[]
{
// for public api
new Client
{
ClientId = "secret_client_id",
AllowedGrantTypes = GrantTypes.ClientCredentials,
ClientSecrets =
{
new Secret("secret".Sha256())
},
AllowedScopes = { "apiscope" }
}
};
}
}
}
namespace IdentityServer
{
public class Startup
{
// This method gets called by the runtime. Use this method to add services to the container.
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
public void ConfigureServices(IServiceCollection services)
{
services.AddIdentityServer()
.AddDeveloperSigningCredential()
.AddOperationalStore(options =>
{
options.EnableTokenCleanup = true;
options.TokenCleanupInterval = 30; // interval in seconds
})
.AddInMemoryApiResources(Config.GetApiResources())
.AddInMemoryClients(Config.GetClients());
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseIdentityServer();
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapGet("/", async context =>
{
await context.Response.WriteAsync("Hello World!");
});
});
}
}
}
问题是现在我需要向 .net 4.6 web api2(非核心)发出经过身份验证的请求。 IdentityServer4.AccessTokenValidation 包对此不起作用。
根据这个问题 (
using IdentityServer3.AccessTokenValidation;
using Microsoft.Owin;
using Owin;
using Microsoft.Owin.Host.SystemWeb;
using IdentityModel.Extensions;
using System.Web.Http;
[assembly: OwinStartup(typeof(WebApplication10.Startup))]
namespace WebApplication10
{
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
app.UseIdentityServerBearerTokenAuthentication(new IdentityServerBearerTokenAuthenticationOptions
{
Authority = "https://localhost:44357",
// For access to the introspection endpoint
ClientId = "secret_client_id",
ClientSecret = "secret".ToSha256(),
RequiredScopes = new[] { "apiscope" }
});
}
}
}
namespace WebApplication10.Controllers
{
public class ValuesController : ApiController
{
[Authorize]
// GET api/values
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
}
}
我一直得到的状态是401未经授权。 难道我做错了什么? 有什么帮助吗? 谢谢
没有日志无法确定你的情况是什么问题,但我做了几个修复来让它工作:
- 关于
Statup.cs
class 的 IdentityServer 项目- 将
AccessTokenJwtType
更改为JWT
,IdentityServer4 上的默认值是at+jwt
但 .Net Framework Api (OWIN/Katana) 需要JWT
. - 通过将
EmitLegacyResourceAudienceClaim
设置为 true 添加/resources
音频,这已在 IdentityServer4 上删除。
- 将
您可以通过检查 "typ"
和 "aud"
来验证 https://jwt.ms/ 上的 access_token。
var builder = services.AddIdentityServer(
options =>
{
options.AccessTokenJwtType = "JWT";
options.EmitLegacyResourceAudienceClaim = true;
});
- 在 .Net Framework Api 项目的
Statup.cs
class 上,将ValidationMode
设置为ValidationMode.Local
,此方法使用的自定义访问令牌验证端点是在 IdentityServer4 上删除。
app.UseIdentityServerBearerTokenAuthentication(new IdentityServerBearerTokenAuthenticationOptions
{
Authority = "https://localhost:44357",
// For access to the introspection endpoint
ClientId = "secret_client_id",
ClientSecret = "secret".ToSha256(),
RequiredScopes = new[] { "apiscope" },
ValidationMode = ValidationMode.Local,
});
我有示例工作实施 here
我强烈建议您在 API 上收集日志,这有助于找到您案例中的实际问题并找到修复方法。 here 是在 Api 上打开 OWIN 登录的示例。
您可以按照 CrossVersionIntegrationTests 中的示例进行操作。
身份服务器 4 没有 connect/accesstokenvalidation
端点。所以在 identity server4 app 中,您可以修改 ApiResource
以添加 ApiSecret
:
new ApiResource("api1", "My API"){ ApiSecrets = new List<Secret> {new Secret("scopeSecret".Sha256())}}
在您的网站 api 中,将 IdentityServerBearerTokenAuthenticationOptions
配置为:
app.UseIdentityServerBearerTokenAuthentication(new IdentityServerBearerTokenAuthenticationOptions
{
Authority = "http://localhost:5000",
ValidationMode = ValidationMode.ValidationEndpoint,
ClientId = "api1",
ClientSecret = "scopeSecret",
RequiredScopes = new[] { "api1" }
});
ClientId
& ClientSecret
都来自您的 ApiResource 。