ASP.NET WebAPI 集成 Swagger 启用 OAuth 2.0 配置问题
在 ASP.NET WebAPI 集成 Swagger 后,由于接口使用了 IdentityServer 做的认证,调试起来很不方便;看了下 Swashbuckle 的文档 ,是支持 OAuth2.0 的配置的,使用的简化模式(Implicit grant type),交互的流程如下:
Implicit Grant Type (简化模式)
参数:
- response_type:表示授权类型,此处的值固定为"token",必选项。
- client_id:表示客户端的ID,必选项。
- redirect_uri:表示重定向的URI,可选项。
- scope:表示权限范围,可选项。
- state:表示客户端的当前状态,可以指定任意值,认证服务器会原封不动地返回这个值。
GET /authorize?response_type=token&client_id=s6BhdRkqt3&state=xyz &redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb HTTP/1.1 Host: server.example.com
认证服务器回应客户端的URI,包含以下参数:
- access_token:表示访问令牌,必选项。
- token_type:表示令牌类型,该值大小写不敏感,必选项。
- expires_in:表示过期时间,单位为秒。如果省略该参数,必须其他方式设置过期时间。
- scope:表示权限范围,如果与客户端申请的范围一致,此项可省略。
- state:如果客户端的请求中包含这个参数,认证服务器的回应也必须一模一样包含这个参数。
HTTP/1.1 302 Found
Location: http://example.com/cb#access_token=2YotnFZFEjr1zCsicMWpAA
&state=xyz&token_type=example&expires_in=3600
Swagger 启用 OAuth 2.0 配置
Idrv 中配置客户端(Client)
new Client { ClientName = "Test_API_Flow", ClientId = "api_test_api_flow", Flow = Flows.Implicit, ClientUri = "https://identityserver.io", RequireConsent = true, AllowRememberConsent = true, RedirectUris = new List<string> { "http://localhost:39106/swagger/ui/o2c-html", }, AllowedCorsOrigins = new List<string> { "http://localhost:39106" }, AccessTokenLifetime = 3600, AccessTokenType = AccessTokenType.Jwt, AllowAccessToAllScopes=true },
API:
app.UseIdentityServerBearerTokenAuthentication(new IdentityServerBearerTokenAuthenticationOptions { Authority = IdsvSetting.Authority, ValidationMode = ValidationMode.ValidationEndpoint, RequiredScopes=new List<string> {"all","user","order"}} });
/// <summary> /// 早餐控制器 /// </summary> [RoutePrefix("api/v1/breakfast")] public class BreakfastController : ApiController { private static readonly Logger logger = LogManager.GetCurrentClassLogger(); /// <summary> /// 早餐服务 /// </summary> private readonly IBreakfastService _breakfastService; /// <summary> /// 构造方法 /// </summary> /// <param name="breakfastService">早餐服务</param> public BreakfastController(IBreakfastService breakfastService) { _breakfastService = breakfastService; } #region 获得酒店关联的餐厅的酒店 /// <summary> /// 获得酒店关联的餐厅的酒店 /// </summary> /// <param name="hotelcd">酒店编号</param> /// <returns>获得酒店关联的餐厅的酒店</returns> [Authorize] [HttpGet] [Route("{hotelcd}/mapping")] public async Task<IHttpActionResult> GetXhotelBreakfastHotelMappingRequest(string hotelcd) { var response = await _breakfastService.GetXhotelBreakfastHotelMappingRequest(hotelcd); return Json(response); } #endregion } }
配置 SwaggerConfig
//https://tsso.xxx.cn/connect/authorize?response_type=token&redirect_uri=http%3A%2F%2Flocalhost%3A39106%2Fswagger%2Fui%2Fo2c-html&realm=test-realm&client_id=api_test_api_flow&scope=all%20%20&state=oauth2 c.OAuth2("oauth2") .Description("OAuth2 Implicit Grant") .Flow("implicit") .AuthorizationUrl("https://tsso.xxx.cn/connect/authorize") //.TokenUrl("https://sso.xxx.cn/connect/token") .Scopes(scopes => { scopes.Add("all", "all access to protected resources"); scopes.Add("user", "user access to protected resources"); scopes.Add("order", "order access to protected resources"); }); ...
c.OperationFilter<AssignOAuth2SecurityRequirements>(); c.EnableOAuth2Support( clientId: "api_test_api_flow", clientSecret: null, realm: "test-realm", appName: "Swagger UI" //additionalQueryStringParams: new Dictionary<string, string>() { { "foo", "bar" } } );
public class AssignOAuth2SecurityRequirements : IOperationFilter { public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription) { var actFilters = apiDescription.ActionDescriptor.GetFilterPipeline(); var allowsAnonymous = actFilters.Select(f => f.Instance).OfType<OverrideAuthorizationAttribute>().Any(); if (allowsAnonymous) return; // must be an anonymous method //var scopes = apiDescription.ActionDescriptor.GetFilterPipeline() // .Select(filterInfo => filterInfo.Instance) // .OfType<AllowAnonymousAttribute>() // .SelectMany(attr => attr.Roles.Split(',')) // .Distinct(); if (operation.security == null) operation.security = new List<IDictionary<string, IEnumerable<string>>>(); var oAuthRequirements = new Dictionary<string, IEnumerable<string>> { {"oauth2", new List<string> {"all","user","order"}} }; operation.security.Add(oAuthRequirements); } }
OK ,配置完成,点击红色的圈圈,登录成功会302到 http://localhost:39106/swagger/ui/o2c-htm 上
当然也可以退出授权:
REFER:
https://www.scottbrady91.com/Identity-Server/ASPNET-Core-Swagger-UI-Authorization-using-IdentityServer4
https://stackoverflow.com/questions/33752900/enable-oauth2-client-credentials-flow-in-swashbuckle
https://stackoverflow.com/questions/29275499/swagger-swashbuckle-oauth2-with-resource-owner-password-credentials-grant?rq=1
http://knowyourtoolset.com/2015/08/secure-web-apis-with-swagger-swashbuckle-and-oauth2-part-2/