OAuth2 是目前大廠都有支援的一種授權機制, Swagger 也有支援,我將使用 Resource Owner Password / Implicit flow + Identity Framework 來進行演練。
開發環境
- VS 2017 Enterprise 15.9.5
- Swashbuckle 5.6.0
實作步驟
這裡需要一個 OAuth Server,所以這次的範本用這個並且給予授權,這個範本會幫我們建立 OAuth Server
安裝
Install-Package Swashbuckle
@SwaggerConfig.cs
套用 Filter
c.OperationFilter<OAuth2OperationFilter>();
指定 Grant Flow
c.OAuth2("oauth2") .Description("OAuth2 password Grant") .Flow("password") .TokenUrl("http://localhost:58310/token") ;
有關 Swagger OAuth 請參考
https://swagger.io/docs/specification/authentication/oauth2/
Filter 指定授權方式
public class OAuth2OperationFilter : IOperationFilter { public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription) { var filterPipeline = apiDescription.ActionDescriptor.GetFilterPipeline(); // check if authorization is required var isAuthorized = filterPipeline .Select(filterInfo => filterInfo.Instance) .Any(filter => filter is IAuthorizationFilter); // check if anonymous access is allowed var allowAnonymous = apiDescription.ActionDescriptor.GetCustomAttributes<AllowAnonymousAttribute>().Any(); if (isAuthorized && !allowAnonymous) { if (operation.security == null) { operation.security = new List<IDictionary<string, IEnumerable<string>>>(); } var auth = new Dictionary<string, IEnumerable<string>> { {"oauth2", Enumerable.Empty<string>()} }; operation.security.Add(auth); } } }
@ApplicationOAuthProvider.cs
這個範例我不用 Client 驗證,所以讓它通過驗證
public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context) { context.Validated(this._publicClientId); return Task.FromResult<object>(null); }
完成之後需要授權的 API 就會有紅色驚嘆號,但帳號密碼哪裡來?
建立帳號
這個專案範本用到了 Identity Framework,為了能順利測試 Swagger ,得先建立帳號,成功之後再去訪問需要授權的方法
通過授權之後紅色就變藍色了
同場加映 implicit flow
@SwaggerConfig.cs
Swagger UI 打 ClientId 進去
GlobalConfiguration.Configuration .EnableSwagger(c => { c.OperationFilter<OAuth2OperationFilter>(); c.SingleApiVersion("v1", "Server"); //https://swagger.io/docs/specification/authentication/oauth2/ c.OAuth2("oauth2") .Description("OAuth2 password Grant") .Flow("implicit") .TokenUrl("http://localhost:58310/token") .AuthorizationUrl("http://localhost:58310/authorize") ; }) .EnableSwaggerUi(c => { c.EnableOAuth2Support( clientId: "self", clientSecret: null, realm: "test-realm", appName: "Swagger UI" ); });
@ApplicationOAuthProvider.cs
加上授權的 EndPoint
public override Task AuthorizeEndpoint(OAuthAuthorizeEndpointContext context) { if (context.AuthorizeRequest.IsImplicitGrantType) { //implicit 授權方式 var identity = new ClaimsIdentity("Bearer"); context.OwinContext.Authentication.SignIn(identity); context.RequestCompleted(); } return Task.FromResult<object>(null); }
用 Implicit 就不用按帳號密碼了
你應該針對你的需求嚴格把關Client Id,不要照抄唷
利用 Fidder 可以觀察到,Swagger UI 用 /swagger/ui/o2c-html 來接收 Token
範例位置
https://github.com/yaochangyu/sample.dotblog/tree/master/WebAPI/Swagger/OAuth2
若有謬誤,煩請告知,新手發帖請多包涵
Microsoft MVP Award 2010~2017 C# 第四季
Microsoft MVP Award 2018~2022 .NET