2015年9月4日 星期五

Securing WebApi with OWIN Identity Authentication server

 ASP.NET   IDENTITY   Token based authentication   Web Api

背景

當完成了OWIN IdentityAuthentication Server後,我們已可認證並取得Token
下一步當然是利用加入Token認證機制到其他的Http Restful Service



如此在SOASP的架構下,可降低Authentication serverResource serer的耦合性。

PS. 在實作本篇程式碼之前,必須先建立一個Identity Authentication Service 可參考相關文章建立。

相關文章


環境

l   Visual Studio 2015
l   WEB API 2.2
l   Entity Framework 6



實作


Packages we need

先安裝相關套件:
Microsoft.OWIN.Host.SystemWeb
MIcrosoft.AspNet.Identity.Owin
Microsoft.Owin.Security.OAuth
Microsoft.Owin.Security
Microsoft.AspNet.WebApi.Cors


OWIN Startup.cs

先移除預設WebApiRegister方法,


l   Global.asax

protected void Application_Start()
{
            AreaRegistration.RegisterAllAreas();
            //GlobalConfiguration.Configure(WebApiConfig.Register);
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
}


l   OWIN Startup

public partial class Startup
    {

        public void Configuration(IAppBuilder appBuilder)
        {
            HttpConfiguration config = new HttpConfiguration();

            //Configure OAuth
            this.configureOAuth(appBuilder);

            //Configure WebApi
            this.configureWebApi(appBuilder);
        }

        private void configureOAuth(IAppBuilder app)
        {
            app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions
            {
            });

        }

       
        private void configureWebApi(IAppBuilder app)
        {
            var config = new HttpConfiguration();

            // Configure Web API to use only bearer token authentication.
          config.SuppressDefaultHostAuthentication();
          config.Filters.Add(
                new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));


            // Web API routes
            config.MapHttpAttributeRoutes();

            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{action}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );

            //Enable CORS
            config.EnableCors();

            app.UseWebApi(config);
        }
    }



Securing Http Restful Service

最後,只要在我們的WebApi Http方法上加上 [Authorize] ,表示此方法需要經過認證的Request才可使用。

[Authorize]
[HttpGet]
public IEnumerable<string> Get()
return new string[] { "The website is protected by an authentication server. @2015" };
}



測試



Testing in IIS Express

環境為:
Authentication Service is on http://localhost:7531
Resource Service (Web Api) is on http://localhost:3241

如下圖,先取得token後,在第一次送出Get並無夾帶token,因此回應為401
夾帶token後再次request,認證成功可取得資源。





Testing in physical IIS at different servers

接下來,我嘗試將Authentication ServerResource Server分開到兩台不同的機器;
DB ConnectionURL調整後,重新做一次測試。

備註:
在佈署後,送出要求token時出現 401的錯誤

確認HttpDB連線及防火牆都沒有問題的情況下,偶然在Authentication ServiceApplication Start加入查詢資料庫的程式碼;
重啟Authentication Service後,再次送出Request給它,此時正常取得資料庫資料,並且Authentication Service的授權功能恢復正常,可正常取得token

我猜想可能的原因在於使用EF Code first的情況下,必須由第一次作動EF來建立APDB之間的連線,否則Authentication Server會一直回傳401

另因為兩個服務在不同的機器,所以必須產生Machine key後,再加入到兩個服務的Web Config

<system.web>
    <compilation debug="true" targetFramework="4.5.2" />
    <httpRuntime targetFramework="4.5.2" />
    <!--<authentication mode="None" />-->
    <machineKey validationKey=""
decryptionKey=""
validation="SHA1" decryption="AES"/>
</system.web>


測試結果如下,我是把Web Api (Resource Server)放在localhost Authentication Server放在另一台開發機器。







Reference






沒有留言:

張貼留言