Pada
artikel kali ini Agung Panduan akan menunjukkan cara mengamankan Web API ASP
NET menggunakan Authentication berbasis token.
ASP NET
WEB API adalah kerangka kerja yang memudahkan pembuatan layanan HTTP yang
menjangkau berbagai klien, termasuk browser, perangkat seluler, dan aplikasi desktop.
Saat ini adopsi Web API meningkat dengan sangat cepat. Jadi sangat penting menerapkan
keamanan untuk semua jenis klien yang mencoba mengakses data dari layanan WEB API.
Pendekatan
yang paling sering digunakan untuk mengamankan sumber daya server dengan
mengautentikasi user di WEB API adalah menggunakan token yang berisi cukup data
untuk identifikasi user tertentu yang disebut pendekatan berbasis token.
- Loose Coupling - Aplikasi klien tidak terikat dengan skema otentikasi tertentu. Token dibuat, divalidasi dan melakukan otentikasi oleh server.
- Mobile Friendly - Dalam platform asli seperti iOS, Android, Windows 8, dll. Menangani cookie bukanlah tugas yang mudah. Pendekatan berbasis token dapat sangat menyederhanakan ini.
Bagaimana otentikasi berbasis token bekerja?
Dalam
pendekatan berbasis Token, aplikasi klien pertama-tama mengirimkan permintaan
ke endpoint Authentication server dengan kredensial yang sesuai. Sekarang Jika user
dan password ditemukan adalah benar maka Authentication mengirim token ke klien
sebagai tanggapan. Token ini berisi cukup data untuk mengidentifikasi pengguna
tertentu dan waktu kadaluwarsa. Aplikasi klien kemudian menggunakan token untuk
mengakses sumber daya yang dibatasi dalam permintaan berikutnya sampai token
tersebut valid.
Ikuti Langkah-langlah
berikut ini secara seksama
Langkah 1.
Jalankan
Visual Studio 2015 ke atas, jangan gunakan Visual di bawahnya. Setelah itu klik
Create New Project > ASP NET WEB Application (.Net Framework).
Langkah 2
Berikan
Project Name: “RestAPIAuthenticationToken” dan pilih lokasi penyimpanan projek,
gunakan Net Framework 4.8. Lalu pilih Template: Web API.
Langkah 3.
Tambahkan
references yang diperlukan dari NuGet Package ke dalam project.
Untuk
menerapkan otentikasi berbasis token di WEB API, kita perlu menginstal
referensi berikut dari NuGet Package:
Install-Package Microsoft.Owin.Security.OAuth -Version 4.1.1
Install-Package Microsoft.Owin.Cors -Version 4.1.1
Install-Package System.IdentityModel.Tokens.Jwt -Version 6.7.1
Langkah 4
Tambahkan
class untuk memvalidasi kredensial user yang meminta token.
Untuk
menambahkan class, arahkan mouse ke project RestAPIAuthenticationToken di Solution Explorer >> klik kanan mouse
pilih Add Class. Berikan nama classnya MyAuthorizationServerProvider.
Class ini akan inherit dari "OAuthAuthorizationServerProvider" untuk overriding dua metode "ValidateClientAuthentication" dan "GrantResourceOwnerCredentials". Metode "ValidateClientAuthentication" digunakan untuk memvalidasi aplikasi klien dan dan dalam metode "GrantResourceOwnerCredentials" kami akan memvalidasi kredensial user. Jika kami menemukan kredensial yang valid, kami akan menghasilkan token, yang dengannya pengguna dapat mengakses sumber daya server yang sah.
using Microsoft.Owin.Security.OAuth;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using System.Web.Http;
namespace RestAPIAuthenticationToken
{
public class MyAuthorizationServerProvider : OAuthAuthorizationServerProvider
{
public override async Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
{
context.Validated(); //
}
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
var identity = new ClaimsIdentity(context.Options.AuthenticationType);
if (context.UserName == "admin" && context.Password == "admin")
{
identity.AddClaim(new Claim(ClaimTypes.Role, "admin"));
identity.AddClaim(new Claim("username", "admin"));
identity.AddClaim(new Claim(ClaimTypes.Name, "Agung Panduan"));
context.Validated(identity);
}
else if (context.UserName == "user" && context.Password == "user")
{
identity.AddClaim(new Claim(ClaimTypes.Role, "user"));
identity.AddClaim(new Claim("username", "user"));
identity.AddClaim(new Claim(ClaimTypes.Name, "Agung Kasep"));
context.Validated(identity);
}
else
{
context.SetError("invalid_grant", "Provided username and password is incorrect");
return;
}
}
}
}
Anda
dapat melihat pada metode “GrantResourceOwnerCredentials”, telah menggunakan
data statos untuk memvalidasi kredensial user.
Langkah 5
Add New Items Owin Startup Class pada projek dengan nama Startup.cs.
using System;
using System.Threading.Tasks;
using Microsoft.Owin;
using Owin;
using Microsoft.Owin.Security.OAuth;
using System.Net.Http;
using RestAPIAuthenticationToken;
//[assembly: OwinStartup(typeof(RestAPIAuthenticationToken.Startup))]
namespace RestAPIAuthenticationToken
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
// For more information on how to configure your application, visit http://go.microsoft.com/fwlink/?LinkID=316888
//enable cors origin requests
//agungpanduan.com
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
var myProvider = new MyAuthorizationServerProvider();
OAuthAuthorizationServerOptions options = new OAuthAuthorizationServerOptions
{
AllowInsecureHttp = true,
TokenEndpointPath = new PathString("/token"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),
Provider = myProvider
};
app.UseOAuthAuthorizationServer(options);
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
System.Web.Http.HttpConfiguration config = new System.Web.Http.HttpConfiguration();
WebApiConfig.Register(config);
}
}
}
Langkah 6
Tambahkan
class lain untuk override atribut otorisasi.
Saat
membuat HTTP Rest API, kita harus menggunakan code respons HTTP yang sesuai
untuk menunjukkan status respons. Saya selalu menggunakan kode status 401 dan
403 untuk mendapatkan status Authentication. 401 (tidak sah) – menunjukkan bahwa
permintaan belum diterapkan karena tidak memiliki kredensial authentikasi yang
valid untuk resource target. Dan 403 (forbidden) – saat user di authentikasi
tetapi tidak diijinkan untuk melakukan operasi yang diminta pada resource yang
diberikan.
Sayangnya, atribut ASP.NET MVC / Web API (Authorize) tidak seperti itu- atribut selalu mengeluarkan 401. Jadi, pada projek ini, saya akan menambahkan class untuk menggantinya. Di projek ini akan mengembalikan 403 ketika user di authentikasi tetapi tidak diijinkan untuk melakukan operasi yang diminta.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace RestAPIAuthenticationToken
{
public class AuthorizeAttribute : System.Web.Http.AuthorizeAttribute
{
protected override void HandleUnauthorizedRequest(System.Web.Http.Controllers.HttpActionContext actionContext)
{
if (!HttpContext.Current.User.Identity.IsAuthenticated)
{
base.HandleUnauthorizedRequest(actionContext);
}
else
{
actionContext.Response = new System.Net.Http.HttpResponseMessage(System.Net.HttpStatusCode.Forbidden);
}
}
}
}
Langkah 7
Tambahkan
Web API Controller. Di mana kita akan menambahkan beberapa action yang dapat
memeriksa apakah otentikasi token berfungsi dengan baik atau tidak.
Solution Explorer > klik kanan mouser pada folder Controllers > Add > Controller > pilih WEB API Controller Class (V2.1), berikan dengan nama DataController.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Security.Claims;
using System.Web.Http;
namespace RestAPIAuthenticationToken.Controllers
{
public class DataController : ApiController
{
[AllowAnonymous]
[HttpGet]
[Route("api/data/forall")]
public IHttpActionResult Get()
{
return Ok("Now server time is: " + DateTime.Now.ToString());
}
[Authorize]
[HttpGet]
[Route("api/data/authenticate")]
public IHttpActionResult GetForAuthenticate()
{
var identity = (ClaimsIdentity)User.Identity;
return Ok("Hello " + identity.Name);
}
[Authorize(Roles = "admin")]
[HttpGet]
[Route("api/data/authorize")]
public IHttpActionResult GetForAdmin()
{
var identity = (ClaimsIdentity)User.Identity;
var roles = identity.Claims
.Where(c => c.Type == ClaimTypes.Role)
.Select(c => c.Value);
return Ok("Hello " + identity.Name + " Role: " + string.Join(",", roles.ToList()));
}
}
}
Penjelasan
Methode pada DataController:
·
IHttpActionResult Get() : semua
pengguna anonim. Semua jenis permintaan, apakah itu diautentikasi atau tidak,
dapat mengakses tindakan ini.
·
IHttpActionResult GetForAuthenticate() : Action
untuk semua jenis user yang diautentikasi, baik itu pengguna Admin atau
pengguna biasa.
·
IHttpActionResult GetForAdmin() : Action hanya
untuk user dengan role Admin.
Setelah
menambahkan Web Api Controller, anda dapat menghapus HomeController.cs dan
ValueController.cs.
Langkah 8
Sebelum Run Application, atur terlebih dahulu WebApiConfig dengan routeTemplate: "api/{controller}/{action}/{id}".
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Http;
namespace RestAPIAuthenticationToken
{
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
}
Untuk mengambil
urlnya di browser yang akan di copy ke Postman. Postman adalah extensions dari
Chrome, yang digunakan sebagai aplikasi klien untuk menguji permintaan dan
respons layanan web dan klien.
Saat
anda membuka aplikasi, anda akan mendapatkan pesan kesalahan “The resource
cannot be found.”. Anda tidak perlu khawatir itu bukanlah error yang menyebalkan
dikarenakan error yang tidak diketahui, hal ini disebabkan anda telah menghapus
HomeController (yang merupakan controller yang pertama di jalankan).
Apa
yang perlu kita lakukan sekarang, kita harus membuka POSTMAN untuk menguji API
Web kita. Setelah itu link berikut.
Langkah 9
Kita akan
melakukan pengujian dengan postman dengan cara pilih Get lalu masukan url
http://localhost:portnumber/api/data/forall
(bagian 2).
Kita akan mendapatkan kode status : 200 OK (lihat bagian 3 pada gambar di bawah) dan hasilnya pada bagian 4 pada gambar itu. Itu berarti tindakan pertama kita berfungsi dengan baik jika permintaannya anonim.
Langkah 10
Tetapi
jika kita mencoba mengakses Action GetForAuthenticate dengan url: http://
localhost:portnumber/api/data/authentication) maka kita akan mendapatkan 401
Unauthenticated karena permintaan tersebut belum diautentikasi. Ini juga akan
sama untuk aksi ke-3.
Jadi, apa yang kita butuhkan untuk mengakses aksi ke-2 dan ke-3? Kita membutuhkan token akses dari server terlebih dahulu dan kemudian kita dapat mengakses tindakan ke-2 dan ke-3 dengan token akses itu.
Langkah 11
Untuk dapat
mengakses Metode Action GetForAuthenticate dan GetForAdmin kita harus
mendapatkan terlebih dahulu kode tokennya. Pilih POST, masukan url http://localhost:port/
token dan pilih x-www-form-urlencoded lalu masukan tiga parameter
Username,
value: user
Password,
value: user
Grant_Type,
value: password
Setelah
itu klik tombol SEND dan lihat pada bagian 5.
Langkah 12
Sekarang
kita dapat mengakses https://localhost:/api/data/authenticate dengan menggunakan
token akses itu.
Pilih
GET (di bagian 1), Masukkan URL https://localhost:/api/data/authenticate (di
bagian 2) lalu klik Headers (di bagian 3) dan masukkan 1 parameter, Authorization
(nilai: Bearer nomor token) dan lalu klik tombol kirim. Setelah klik tombol
kirim kita akan mendapatkan 200 OK (lihat bagian 4) dan hasilnya (lihat bagian
5).
Dengan cara yang sama, kita dapat mengakses method action ke-3 tetapi kita harus mendapatkan token yang masuk dengan username: admin dan password: admin karena action ke-3 hanya dapat diakses oleh user dengan type Admin. Anda dapat mendapatkan file projek ini dengan mengunjungi GitHub
0 Comments