Добрый день, уважаемые пользователи.
Пытаюсь сделать OAuth2 аутентификацию в ASP.NET WebApi, основанную на токенах, с использованием контейнеров внедрения зависимостей. В качестве DI используется Autofac
Для использования OAuth2 я установил следующие библиотеки:
- Microsoft.AspNet.WebApi.Owin
- Microsoft.Owin.Host.SystemWeb
- Microsoft.AspNet.Identity.Owin
- Microsoft.AspNet.Identity.EntityFramework
- Microsoft.Owin.Security.OAuth
- Microsoft.Owin.Cors
Зарегистрировал новый фильтр
config.SuppressDefaultHostAuthentication(); config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));
Добавил класс для загрузки
[assembly: OwinStartup(typeof(SimpleStore.Api.Startup))] namespace SimpleStore.Api { public class Startup { public static OAuthAuthorizationServerOptions OAuthOptions { get; private set; } public static string PublicClientId { get; private set; } public void Configuration(IAppBuilder app) { var builder = new ContainerBuilder(); var apiConfig = new HttpConfiguration(); WebApiConfig.Register(apiConfig); builder.RegisterApiControllers(Assembly.GetExecutingAssembly()).InstancePerRequest(); builder.RegisterModule<DataModule>(); builder.RegisterModule(new ManagerModule(app)); builder.RegisterModule<ServiceModule>(); builder.RegisterModule<ValidatorModule>(); builder.RegisterType<FluentValidationModelValidatorProvider>().As<ModelValidatorProvider>(); builder.RegisterType<AutofacValidatorFactory>().As<IValidatorFactory>().SingleInstance(); var container = builder.Build(); apiConfig.DependencyResolver = new AutofacWebApiDependencyResolver(container); app.UseAutofacMiddleware(container); app.UseAutofacWebApi(apiConfig); app.UseWebApi(apiConfig); app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll); PublicClientId = "self"; OAuthOptions = new OAuthAuthorizationServerOptions { TokenEndpointPath = new PathString("/token"), Provider = new AppOAuthProvider(PublicClientId), AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"), AccessTokenExpireTimeSpan = TimeSpan.FromDays(60), AllowInsecureHttp = true }; #if DEBUG OAuthOptions.AllowInsecureHttp = false; #endif app.UseOAuthAuthorizationServer(OAuthOptions); app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions()); } } }
ManagerModule для Autofac
public class ManagerModule : Module { private readonly IAppBuilder app; public ManagerModule(IAppBuilder app) => this.app = app; protected override void Load(ContainerBuilder builder) { builder.RegisterType<AppSignInManager>() .As<SignInManager<User, Guid>>() .InstancePerRequest(); builder.Register<IAuthenticationManager>((c, p) => c.Resolve<IOwinContext>().Authentication) .InstancePerRequest(); builder.Register<AppUserManager>((c, p) => { var manager = new AppUserManager(c.Resolve<IUserStore<User, Guid>>()); manager.UserValidator = new UserValidator<User, Guid>(manager) { AllowOnlyAlphanumericUserNames = false, RequireUniqueEmail = true }; manager.PasswordValidator = new PasswordValidator { RequiredLength = 8, RequireDigit = true, RequireLowercase = true, RequireUppercase = true, RequireNonLetterOrDigit = true }; manager.UserLockoutEnabledByDefault = true; manager.DefaultAccountLockoutTimeSpan = TimeSpan.FromMinutes(5); manager.MaxFailedAccessAttemptsBeforeLockout = 5; var dataProtectionProvider = app.GetDataProtectionProvider(); if (dataProtectionProvider != null) { manager.UserTokenProvider = new DataProtectorTokenProvider<User, Guid>( dataProtectionProvider.Create("ASP.NET Identity")); } return manager; }).AsSelf().InstancePerLifetimeScope(); builder.RegisterType<AppRoleManager>() .AsSelf() .InstancePerLifetimeScope(); builder.RegisterType<TicketDataFormat>() .As<ISecureDataFormat<AuthenticationTicket>>(); builder.RegisterType<TicketSerializer>() .As<IDataSerializer<AuthenticationTicket>>(); builder.Register(c => new DpapiDataProtectionProvider().Create("ASP.NET Identity")) .As<IDataProtector>(); base.Load(builder); } }
А так же OAuth провайдер
public class AppOAuthProvider : OAuthAuthorizationServerProvider { private readonly string _publicClientId; public AppOAuthProvider(string publicClientId) { if (publicClientId == null) { throw new ArgumentNullException(nameof(publicClientId)); } _publicClientId = publicClientId; } public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context) { var userManager = context.OwinContext.GetUserManager<AppUserManager>(); var user = await userManager.FindAsync(context.UserName, context.Password); if (user == null) { context.SetError("invalid_grant", "Имя пользователя или пароль указаны неправильно."); return; } var oAuthIdentity = await userManager.CreateIdentityAsync(user, OAuthDefaults.AuthenticationType); var cookiesIdentity = await userManager.CreateIdentityAsync(user, CookieAuthenticationDefaults.AuthenticationType); var properties = CreateProperties(user.UserName); var ticket = new AuthenticationTicket(oAuthIdentity, properties); context.Validated(ticket); context.Request.Context.Authentication.SignIn(cookiesIdentity); } public override Task TokenEndpoint(OAuthTokenEndpointContext context) { foreach (KeyValuePair<string, string> property in context.Properties.Dictionary) { context.AdditionalResponseParameters.Add(property.Key, property.Value); } return Task.FromResult<object>(null); } public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context) { if (context.ClientId == null) { context.Validated(); } return Task.FromResult<object>(null); } public override Task ValidateClientRedirectUri(OAuthValidateClientRedirectUriContext context) { if (context.ClientId == _publicClientId) { Uri expectedRootUri = new Uri(context.Request.Uri, "/"); if (expectedRootUri.AbsoluteUri == context.RedirectUri) { context.Validated(); } } return Task.FromResult<object>(null); } public static AuthenticationProperties CreateProperties(string userName) { IDictionary<string, string> data = new Dictionary<string, string> { {"userName", userName} }; return new AuthenticationProperties(data); } }
При попытке получить токен средствами Postman, получаю ошибку 404
В качестве примера использовал статью от Sarshern Lin “Token Based Authentication in Web API 2 via OWIN”
Как реализовать данную аутентификацию средставами Autofac ?