Настройка конечной точки сервера авторизации

Вопрос

Как использовать токен-носитель с ASP.NET 5 с использованием streamа имени пользователя и пароля? Для нашего сценария мы хотим, чтобы пользователь регистрировался и заходил в систему с помощью вызовов AJAX без необходимости использования внешнего входа.

Для этого нам нужно иметь конечную точку сервера авторизации. В предыдущих версиях ASP.NET мы сделали бы следующее, а затем ourdomain.com/Token URL-адрес ourdomain.com/Token .

 // Configure the application for OAuth based flow PublicClientId = "self"; OAuthOptions = new OAuthAuthorizationServerOptions { TokenEndpointPath = new PathString("/Token"), Provider = new ApplicationOAuthProvider(PublicClientId), AccessTokenExpireTimeSpan = TimeSpan.FromDays(14) }; 

Однако в текущей версии ASP.NET приведенное выше не работает. Мы пытались выяснить новый подход. Например, пример aspnet / identity в GitHub настраивает аутентификацию Facebook, Google и Twitter, но не создает конфигурацию конечной точки сервера внешней аутентификации OAuth, если это не то, что AddDefaultTokenProviders() , и в этом случае нам интересно, что URL-адрес поставщика будет.

Исследование

Мы узнали от чтения источника здесь, что мы можем добавить «промежуточное ПО аутентификации на предъявителя» в конвейер HTTP, вызывая IAppBuilder.UseOAuthBearerAuthentication в нашем classе Startup . Это хорошее начало, хотя мы все еще не уверены в том, как установить конечную точку маркера. Это не помогло:

 public void Configure(IApplicationBuilder app) { app.UseOAuthBearerAuthentication(options => { options.MetadataAddress = "meta"; }); // if this isn't here, we just get a 404 app.Run(async context => { await context.Response.WriteAsync("Hello World."); }); } 

При переходе на ourdomain.com/meta мы просто получаем нашу всемирную страницу приветствия.

Дальнейшие исследования показали, что мы также можем использовать IAppBuilder.UseOAuthAuthentication расширения IAppBuilder.UseOAuthAuthentication и что он принимает параметр OAuthAuthenticationOptions . Этот параметр имеет свойство TokenEndpoint . Поэтому, хотя мы не уверены, что делаем, мы попробовали это, что, конечно же, не сработало.

 public void Configure(IApplicationBuilder app) { app.UseOAuthAuthentication("What is this?", options => { options.TokenEndpoint = "/token"; options.AuthorizationEndpoint = "/oauth"; options.ClientId = "What is this?"; options.ClientSecret = "What is this?"; options.SignInScheme = "What is this?"; options.AutomaticAuthentication = true; }); // if this isn't here, we just get a 404 app.Run(async context => { await context.Response.WriteAsync("Hello World."); }); } 

Другими словами, при переходе на ourdomain.com/token , нет ошибки, так же как и наша всемирная страница приветствия.

Хорошо, давайте вспомним другое промежуточное ПО OAuth2 (и их соответствующие расширения IAppBuilder ), которые были предложены OWIN / Katana 3, и те, которые будут перенесены в ASP.NET Core :

  • app.UseOAuthBearerAuthentication / OAuthBearerAuthenticationMiddleware : его имя не было явно очевидным, но оно было (и по-прежнему, поскольку оно было перенесено в ASP.NET Core), ответственное за проверку токенов доступа, выпущенных промежуточным программным обеспечением OAuth2. Это, в основном, токен-копия промежуточного программного обеспечения cookie и используется для защиты ваших API-интерфейсов. В ASP.NET Core он был дополнен дополнительными функциями OpenID Connect (теперь он может автоматически получать сертификат подписи с сервера OpenID Connect, который выдал токены).

Примечание: начиная с ASP.NET Core beta8, теперь он называется app.UseJwtBearerAuthentication / JwtBearerAuthenticationMiddleware .

  • app.UseOAuthAuthorizationServer / OAuthAuthorizationServerMiddleware : как следует из названия, OAuthAuthorizationServerMiddleware является промежуточным программным обеспечением сервера авторизации OAuth2 и используется для создания и выпуска токенов доступа. Это промежуточное программное обеспечение не будет перенесено в службу ASP.NET Core : OAuth Authorization Service в ASP.NET Core .

  • app.UseOAuthBearerTokens : это расширение действительно не соответствовало промежуточному программному обеспечению и было просто оболочкой вокруг app.UseOAuthAuthorizationServer и app.UseOAuthBearerAuthentication . Он был частью пакета ASP.NET Identity и был просто удобным способом настройки сервера авторизации OAuth2 и промежуточного программного обеспечения OAuth2, используемого для проверки токенов доступа в одном вызове. Он не будет перенесен в ASP.NET Core .

ASP.NET Core предложит совершенно новое промежуточное ПО (и я с гордостью могу сказать, что я его разработал):

  • app.UseOAuthAuthentication / OAuthAuthenticationMiddleware : это новое промежуточное программное обеспечение представляет собой общий интерактивный клиент OAuth2, который ведет себя точно так же, как app.UseFacebookAuthentication или app.UseGoogleAuthentication но поддерживает практически любой стандартный поставщик OAuth2, включая ваши. Поставщики Google, Facebook и Microsoft все были обновлены, чтобы наследовать это новое базовое промежуточное ПО.

Таким образом, промежуточное программное обеспечение, которое вы действительно ищете, – это промежуточное программное обеспечение сервера авторизации OAuth2 , например OAuthAuthorizationServerMiddleware .

Хотя он считается важным компонентом значительной части сообщества, он не будет перенесен в ASP.NET Core .

К счастью, уже есть прямая замена: AspNet.Security.OpenIdConnect.Server ( https://github.com/aspnet-contrib/AspNet.Security.OpenIdConnect.Server )

Это промежуточное программное обеспечение является передовой версией промежуточного программного обеспечения сервера авторизации OAuth2, которое поставляется вместе с Katana 3, но оно предназначено для OpenID Connect (которое основано на OAuth2). Он использует тот же подход на низком уровне, который предлагает мелкомасштабный контроль (через различные уведомления) и позволяет использовать свою собственную инфраструктуру (Nancy, ASP.NET Core MVC) для обслуживания ваших страниц авторизации, как вы могли, с помощью промежуточного ПО сервера OAuth2 , Конфигурирование легко:

ASP.NET Core 1.x:

 // Add a new middleware validating access tokens issued by the server. app.UseOAuthValidation(); // Add a new middleware issuing tokens. app.UseOpenIdConnectServer(options => { options.TokenEndpointPath = "/connect/token"; // Create your own `OpenIdConnectServerProvider` and override // ValidateTokenRequest/HandleTokenRequest to support the resource // owner password flow exactly like you did with the OAuth2 middleware. options.Provider = new AuthorizationProvider(); }); 

ASP.NET Core 2.x:

 // Add a new middleware validating access tokens issued by the server. services.AddAuthentication() .AddOAuthValidation() // Add a new middleware issuing tokens. .AddOpenIdConnectServer(options => { options.TokenEndpointPath = "/connect/token"; // Create your own `OpenIdConnectServerProvider` and override // ValidateTokenRequest/HandleTokenRequest to support the resource // owner password flow exactly like you did with the OAuth2 middleware. options.Provider = new AuthorizationProvider(); }); 

Существует версия OWIN / Katana 3 и версия ASP.NET Core, которая поддерживает как .NET Desktop, так и .NET Core.

Не стесняйтесь дать образец Postman попробовать понять, как это работает. Я бы рекомендовал прочитать связанное сообщение в блоге , в котором объясняется, как вы можете реализовать stream пароля владельца ресурса.

Не стесняйтесь пинговать меня, если вам все еще нужна помощь. Удачи!

С помощью @ Pinpoint мы связали рудименты ответа. Он показывает, как компоненты соединяются вместе, не будучи полным решением.

Демоверсия Fiddler

С нашей рудиментарной настройкой проекта мы смогли сделать следующий запрос и ответ в Fiddler.

Запрос

 POST http://localhost:50000/connect/token HTTP/1.1 User-Agent: Fiddler Host: localhost:50000 Content-Length: 61 Content-Type: application/x-www-form-urlencoded grant_type=password&username=my_username&password=my_password 

отклик

 HTTP/1.1 200 OK Cache-Control: no-cache Pragma: no-cache Content-Length: 1687 Content-Type: application/json;charset=UTF-8 Expires: -1 X-Powered-By: ASP.NET Date: Tue, 16 Jun 2015 01:24:42 GMT { "access_token" : "eyJ0eXAiOi ... 5UVACg", "expires_in" : 3600, "token_type" : "bearer" } 

Ответ обеспечивает маркер-носитель, который мы можем использовать для доступа к защищенной части приложения.

Структура проекта

Такова структура нашего проекта в Visual Studio. Нам нужно было установить его Properties > Debug > Port до 50000 чтобы он работал в качестве сервера идентификации, который мы настроили. Вот соответствующие файлы:

 ResourceOwnerPasswordFlow Providers AuthorizationProvider.cs project.json Startup.cs 

Startup.cs

Для удобства чтения я разделил class Startup на две частичные.

Startup.ConfigureServices

Для самих основ нам требуется только AddAuthentication() .

 public partial class Startup { public void ConfigureServices(IServiceCollection services) { services.AddAuthentication(); } } 

Startup.Configure

 public partial class Startup { public void Configure(IApplicationBuilder app) { JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear(); JwtSecurityTokenHandler.DefaultOutboundClaimTypeMap.Clear(); // Add a new middleware validating access tokens issued by the server. app.UseJwtBearerAuthentication(new JwtBearerOptions { AutomaticAuthenticate = true, AutomaticChallenge = true, Audience = "resource_server_1", Authority = "http://localhost:50000/", RequireHttpsMetadata = false }); // Add a new middleware issuing tokens. app.UseOpenIdConnectServer(options => { // Disable the HTTPS requirement. options.AllowInsecureHttp = true; // Enable the token endpoint. options.TokenEndpointPath = "/connect/token"; options.Provider = new AuthorizationProvider(); // Force the OpenID Connect server middleware to use JWT // instead of the default opaque/encrypted format. options.AccessTokenHandler = new JwtSecurityTokenHandler { InboundClaimTypeMap = new Dictionary(), OutboundClaimTypeMap = new Dictionary() }; // Register an ephemeral signing key, used to protect the JWT tokens. // On production, you'd likely prefer using a signing certificate. options.SigningCredentials.AddEphemeralKey(); }); app.UseMvc(); app.Run(async context => { await context.Response.WriteAsync("Hello World!"); }); } } 

AuthorizationProvider.cs

 public sealed class AuthorizationProvider : OpenIdConnectServerProvider { public override Task ValidateTokenRequest(ValidateTokenRequestContext context) { // Reject the token requests that don't use // grant_type=password or grant_type=refresh_token. if (!context.Request.IsPasswordGrantType() && !context.Request.IsRefreshTokenGrantType()) { context.Reject( error: OpenIdConnectConstants.Errors.UnsupportedGrantType, description: "Only grant_type=password and refresh_token " + "requests are accepted by this server."); return Task.FromResult(0); } // Since there's only one application and since it's a public client // (ie a client that cannot keep its credentials private), call Skip() // to inform the server that the request should be accepted without // enforcing client authentication. context.Skip(); return Task.FromResult(0); } public override Task HandleTokenRequest(HandleTokenRequestContext context) { // Only handle grant_type=password token requests and let the // OpenID Connect server middleware handle the other grant types. if (context.Request.IsPasswordGrantType()) { // Validate the credentials here (eg using ASP.NET Core Identity). // You can call Reject() with an error code/description to reject // the request and return a message to the caller. var identity = new ClaimsIdentity(context.Options.AuthenticationScheme); identity.AddClaim(OpenIdConnectConstants.Claims.Subject, "[unique identifier]"); // By default, claims are not serialized in the access and identity tokens. // Use the overload taking a "destinations" parameter to make sure // your claims are correctly serialized in the appropriate tokens. identity.AddClaim("urn:customclaim", "value", OpenIdConnectConstants.Destinations.AccessToken, OpenIdConnectConstants.Destinations.IdentityToken); var ticket = new AuthenticationTicket( new ClaimsPrincipal(identity), new AuthenticationProperties(), context.Options.AuthenticationScheme); // Call SetResources with the list of resource servers // the access token should be issued for. ticket.SetResources("resource_server_1"); // Call SetScopes with the list of scopes you want to grant // (specify offline_access to issue a refresh token). ticket.SetScopes("profile", "offline_access"); context.Validate(ticket); } return Task.FromResult(0); } } 

project.json

 { "dependencies": { "AspNet.Security.OpenIdConnect.Server": "1.0.0", "Microsoft.AspNetCore.Authentication.JwtBearer": "1.0.0", "Microsoft.AspNetCore.Mvc": "1.0.0", } // other code omitted } 
  • google oauth2 redirect_uri с несколькими параметрами
  • Получить информацию о пользователе через API Google
  • Как защитить веб-API ASP.NET
  • Реализация HMAC-SHA1 в python
  • Сделать Android WebView не хранить cookies или пароли
  • Ошибка Omniauth Facebook - Faraday :: Ошибка :: ConnectionFailed
  • OAuth 2.0 с API Google Analytics v3
  • Почему заканчиваются токены доступа?
  • Есть ли способ получить идентификатор электронной почты пользователя после проверки его / ее идентификатора Twitter с помощью OAuth?
  • Пример Facebook Connect в JSP (tomcat)
  • Создание API для мобильных приложений - Аутентификация и авторизация
  • Давайте будем гением компьютера.