C# Web Api Bearer Token Tabanlı Authentication İşlemi
19-10-2019Öncelikle Nuget kütüphanelerinin kurulması gerekir:
Install-Package Microsoft.AspNet.WebApi.Owin -Version 5.2.2 Install-Package Microsoft.Owin.Host.SystemWeb -Version 2.1.0 Install-Package Microsoft.AspNet.Identity.Owin -Version 2.0.1 Install-Package Microsoft.AspNet.Identity.EntityFramework -Version 2.0.1 Install-Package Microsoft.Owin.Security.OAuth -Version 2.1.0 Install-Package Microsoft.Owin.Cors -Version 2.1.0
Daha sonra Startup.cs sınıfı eklenir:
using System; using System.Web.Http; using MapToner.Helpers; using Microsoft.AspNet.Identity; using Microsoft.Owin; using Microsoft.Owin.Cors; using Microsoft.Owin.Security.Cookies; using Microsoft.Owin.Security.OAuth; using Owin; [assembly: OwinStartup(typeof(MapToner.Startup))] namespace MapToner { public class Startup { public static string PublicClientId { get; private set; } public void Configuration(IAppBuilder app) { var config = new HttpConfiguration(); // Configure Web API to use only bearer token authentication. config.SuppressDefaultHostAuthentication(); config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType)); ConfigureAuth(app); WebApiConfig.Register(config); app.UseCors(CorsOptions.AllowAll); app.UseWebApi(config); } public void ConfigureAuth(IAppBuilder app) { // Configure the application for OAuth based flow PublicClientId = "self"; var oAuthOptions = new OAuthAuthorizationServerOptions { TokenEndpointPath = new PathString("/token"), Provider = new AppOAuthProvider(PublicClientId), AuthorizeEndpointPath = new PathString("/Account/ExternalLogin"), AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(30), AllowInsecureHttp = true }; app.UseOAuthAuthorizationServer(oAuthOptions);//Oauth2 ayarlarinin yapilmasini saglar //Http request header'daki bearer token olup olmadigini anlamak icin kullanilir. app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions()); } } }
WebApiConfig.cs sınıfı aşağıdaki gibi olursa çok iyi olur:
public static class WebApiConfig { public static void Register(HttpConfiguration config) { config.MapHttpAttributeRoutes(); config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/v1/{controller}/{id}", defaults: new {id = RouteParameter.Optional} ); ConfigureJsonResponse(config); } private static void ConfigureJsonResponse(HttpConfiguration config) { //Removes XML response, return JSON response var contractResolver = new DefaultContractResolver { NamingStrategy = new SnakeCaseNamingStrategy() }; var jsonFormatter = config.Formatters.OfType<jsonmediatypeformatter>().First(); jsonFormatter.SerializerSettings.ContractResolver = contractResolver; // Adding JSON type web api formatting. config.Formatters.Clear(); config.Formatters.Add(jsonFormatter); } } </jsonmediatypeformatter>
Son olarak AppOAuthProvider.cs sınıfı tanımlanır:
using System.Collections.Generic; using System.Security.Claims; using System.Threading.Tasks; using System.Web; using MapToner.EntityFramework; using MapToner.Models; using Microsoft.Owin.Security; using Microsoft.Owin.Security.OAuth; namespace MapToner.Helpers { /// <summary> /// Application OAUTH Provider class. /// </summary> public class AppOAuthProvider : OAuthAuthorizationServerProvider { public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context) { // Initialization. var user = await new LoginHelper().Login(context.UserName, context.Password); if (user == null) { context.SetError("invalid_grant", "Böyle bir kullanıcı bulunamadı"); new LogHelper().SaveUserLog(HttpContext.Current.Request.Browser.Browser, HttpContext.Current.Request.UserHostAddress); return; } var representative = new UserHelper().GetUser((int)user.temsilci_id); new LogHelper().SaveUserLog(HttpContext.Current.Request.Browser.Browser, HttpContext.Current.Request.UserHostAddress, user.id); var claims = new List<Claim> { new Claim(ClaimTypes.Name, context.UserName), new Claim(ClaimTypes.NameIdentifier, user.id.ToString()) }; var oAuthClaimIdentity = new ClaimsIdentity(claims, OAuthDefaults.AuthenticationType); var ticket = new AuthenticationTicket(oAuthClaimIdentity, CreateProperties(user, representative)); context.Validated(ticket); } /// <summary> /// Accesss token generate olurken yani /token linkine post edildiginde CreateProperties metodunun donderdigi Map degeri json response da ekstra /// parametre olarak gonderilir. /// </summary> /// <param name="user"></param> /// <param name="representative"></param> /// <returns></returns> public static AuthenticationProperties CreateProperties(User user,User representative) { IDictionary<string, string> data = new Dictionary<string, string> { {"full_name", user.adi_soyadi}, {"phone", user.tel}, {"email", user.mail}, {"user_login", "evet"}, {"user_guid", user.GUID}, {"iskonto_id", user.iskonto_id.ToString()}, {"representative_id", user.temsilci_id.ToString()}, {"representative_full_name", representative.adi_soyadi}, {"representative_phone", representative.tel.Replace(" ","")}, {"representative_email", representative.mail}, {"is_current_payment_active", user.cari=="1"?"true":"false"}, }; return new AuthenticationProperties(data); } /// <summary> /// CreateProperties metodundaki parametrelere ek olarak baska parametreler eklemek icin kullanilabilir. Yine ayni sekilde /token linkine post edilince /// post sonucunda donen json da bu parametreler yer alacaktir. /// </summary> /// <param name="context"></param> /// <returns></returns> public override Task TokenEndpoint(OAuthTokenEndpointContext context) { foreach (var property in context.Properties.Dictionary) context.AdditionalResponseParameters.Add(property.Key, property.Value); return Task.FromResult<object>(null); } /// <summary> /// Client Id leri validate etmek icin kullanilir. Bizim uygulamamızda 1 tane olduğu için context.Validated() demek yeterli olacaktır. /// </summary> /// <param name="context"></param> /// <returns></returns> public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context) { if (context.ClientId == null) context.Validated(); return Task.FromResult<object>(null); } public override Task GrantRefreshToken(OAuthGrantRefreshTokenContext context) { var newIdentity = new ClaimsIdentity(context.Ticket.Identity); var newTicket = new AuthenticationTicket(newIdentity, context.Ticket.Properties); context.Validated(newTicket); return Task.FromResult<object>(null); } } }
Daha fazla bilgi için:
https://blogs.perficient.com/2017/06/11/token-based-authentication-in-web-api-2-via-owin/